bmcfee / muda

A library for augmenting annotated audio data
ISC License
230 stars 33 forks source link

AttributeError: 'dict' object has no attribute '_audio' #42

Closed YazhouZhang0709 closed 7 years ago

YazhouZhang0709 commented 7 years ago

I tried to run the muda code example from documentaion:

import muda 
import librosa 
clip=muda.load_jam_audio('audio/7061-6-0-0_bgnoise0.jams','audio/6902-2-0-7.wav')
pitch = muda.deformers.LinearPitchShift(n_samples=5,lower=-1,upper=1)
for i, jam_out in pitch.transform(clip):
          muda.save('output_{:02d}.wav'.format(i),'output_{:02d}.jams'.format(i),jam_out) `

but this error occurs:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-7-e235d022c3b3> in <module>()
      1 pitch = muda.deformers.LinearPitchShift(n_samples=5,lower=-1,upper=1)
----> 2 for i, jam_out in pitch.transform(clip):
      3     muda.save('output_{:02d}.wav'.format(i),'output_{:02d}.jams'.format(i),jam_out)

/home/uri7910/anaconda2/envs/tensorflow011/lib/python2.7/site-packages/muda/base.pyc in transform(self, jam)
    140         '''
    141 
--> 142         for state in self.states(jam):
    143             yield self._transform(jam, state)
    144 

/home/uri7910/anaconda2/envs/tensorflow011/lib/python2.7/site-packages/muda/deformers/pitch.pyc in states(self, jam)
    251                              endpoint=True)
    252 
--> 253         for state in AbstractPitchShift.states(self, jam):
    254             for n_semitones in shifts:
    255                 state['n_semitones'] = n_semitones

/home/uri7910/anaconda2/envs/tensorflow011/lib/python2.7/site-packages/muda/deformers/pitch.pyc in states(self, jam)
     67     def states(self, jam):
     68         mudabox = jam.sandbox.muda
---> 69         state = dict(tuning=librosa.estimate_tuning(y=mudabox._audio['y'],
     70                                                     sr=mudabox._audio['sr']))
     71         yield state

AttributeError: 'dict' object has no attribute '_audio' 
bmcfee commented 7 years ago

Not sure if you meant to close this out already, but I'm guessing the problem is that the jams object did not have the audio buffer loaded. An example of how to do this is here.

YazhouZhang0709 commented 7 years ago

Thanks for your answer. @bmcfee . I tried the example you showed to me. But this error still there. @

bmcfee commented 7 years ago

@YazhouZhang0709 strange indeed..

After loading clip with muda.load_jam_audio, can you do:

>>> repr(clip.sandbox.muda)

and report the results?

Also, it would be helpful to have some info about your environment. Would you mind reporting the results of

>>> import jams
>>> jams.__version__

as well as, since you appear to be using conda, conda list?

YazhouZhang0709 commented 7 years ago
clip=muda.load_jam_audio('audio/7061-6-0-0_bgnoise0.jams','audio/6902-2-0-7.wav')
repr(clip.sandbox.muda)

output: "{u'state': [], u'version': {u'muda': u'0.1.1', u'jams': u'0.2.1', u'pysoundfile': u'0.8.1', u'librosa': u'0.4.2'}, '_audio': {'y': array([ 0.02293396, 0.02362061, 0.02113342, ..., -0.02062988,\n 0.02101135, 0.04855347], dtype=float32), 'sr': 22050}, u'history': [{u'transformer': {u'params': {u'files': [u'/Users/justin/datasets/UrbanSound8K/deepsonyc/background_noise/converted/150993__saphe__street-scene-1.wav', u'/Users/justin/datasets/UrbanSound8K/deepsonyc/background_noise/converted/173955__saphe__street-scene-3.wav', u'/Users/justin/datasets/UrbanSound8K/deepsonyc/background_noise/converted/207208__jormarp__high-street-of-gandia-valencia-spain.wav', u'/Users/justin/datasets/UrbanSound8K/deepsonyc/background_noise/converted/268903__yonts__city-park-tel-aviv-israel.wav'], u'weight_max': 0.5, u'n_samples': 1, u'weight_min': 0.1}, u'__class__': u'BackgroundNoise'}, u'state': {u'weight': 0.48259326124346635, u'filename': u'/Users/justin/datasets/UrbanSound8K/deepsonyc/background_noise/converted/150993__saphe__street-scene-1.wav'}}]}"

import jams
jams.__version__

output: '0.2.2'

bmcfee commented 7 years ago

Huh -- very strange. Just to verify, can you print type(clip.sandbox.muda) as well?

YazhouZhang0709 commented 7 years ago

output is dict

bmcfee commented 7 years ago

output is dict

aha! This is definitely a bug then.

sandbox.muda is a jams.Sandbox when first created. It appears that your jams file has been serialized from a previous muda session, and when it gets reloaded, the muda object is interpreted as a dict instead. This makes sense from JAMS's perspective, since it has no schema to dictate that muda should be a sandbox instead of a dict.

The following example reproduces the error (python 3):

In [2]: clip = muda.load_jam_audio('fixture.jams', 'fixture.wav')
In [3]: clip.sandbox.muda
Out[3]: <Sandbox: version, _audio, history, state>

In [4]: type(clip.sandbox.muda)
Out[4]: jams.core.Sandbox

In [12]: import io

In [13]: buf = io.StringIO(clip.dumps())
In [14]: clip2 = jams.load(buf)

In [15]: clip2
Out[15]: <JAMS: file_metadata, annotations, sandbox>

In [16]: clip2.sandbox
Out[16]: <Sandbox: muda>

In [17]: clip2.sandbox.muda
Out[17]: 
{'history': [],
 'state': [],
 'version': {'jams': '0.2.2',
  'librosa': '0.5.0',
  'muda': '0.1.2',
  'pysoundfile': '0.8.1'}}

In [18]: type(clip2.sandbox.muda)
Out[18]: dict

n [19]: type(clip.sandbox.muda)
Out[19]: jams.core.Sandbox

Thanks for uncovering this error!

For now, you should be able to work around it by doing the following to reload the jams/audio objects:

>>> import jams
>>> jam = jams.load('your_file.jams')
>>> jam.sandbox.muda = jams.Sandbox(**jam.sandbox.muda)
>>> muda.load_jam_audio(jam, 'your_audio_file.wav')

I'll get working on a proper fix in the meantime.

bmcfee commented 7 years ago

@YazhouZhang0709 ok, the fix is merged now, and will be included in 0.1.3. If you can't wait for that, you can install the current master and it ought to work. Thanks again for the bug report.

YazhouZhang0709 commented 7 years ago

@bmcfee Thanks a lot ! I installed the current master and reloaded the jams/audio objects as you said, but I got an another error. Here is the code:

import muda
import jams
jam = jams.load('audio/7061-6-0-0_bgnoise0.jams')
jam.sandbox.muda = jams.Sandbox(**jam.sandbox.muda)
muda.load_jam_audio(jam, 'audio/6902-2-0-7.wav')
pitch = muda.deformers.LinearPitchShift(n_samples=5,lower=-1,upper=1)
for i, jam_out in pitch.transform(jam):
    muda.save('output_{:02d}.wav'.format(i),'output_{:02d}.jams'.format(i),jam_out)

Here is the error info:

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-3-e981e6c67b91> in <module>()
      1 pitch = muda.deformers.LinearPitchShift(n_samples=5,lower=-1,upper=1)
----> 2 for i, jam_out in pitch.transform(jam):
      3     muda.save('output_{:02d}.wav'.format(i),'output_{:02d}.jams'.format(i),jam_out)

/home/uri7910/anaconda2/envs/tensorflow011/lib/python2.7/site-packages/jams/core.pyc in __getitem__(self, key)
    263     def __getitem__(self, key):
    264         """Dict-style interface"""
--> 265         return self.__dict__[key]
    266 
    267     def __setattr__(self, name, value):

KeyError: 0
bmcfee commented 7 years ago

Hrmm.. looks like a typo in the example.

This bit:

for i, jam_out in pitch.transform(jam):

should be:

for i, jam_out in enumerate(pitch.transform(jam)):

Also, if you're running of the latest master, this bit

jam.sandbox.muda = jams.Sandbox(**jam.sandbox.muda)

is no longer necessary. It shouldn't hurt to keep it though.

YazhouZhang0709 commented 7 years ago

Thank you so much!

bmcfee commented 7 years ago

Docs have been corrected -- should be up shortly.