I know this is a basic question and I have no doubt that it has been answered but I cant find any good info anywhere, so:
I have a list of methods that work wonderfully when outside of a class and when variables are declared globally. However, when I try to contain the methods and variables within a class I run into all sorts of errors concerning the variables.
class AudioFeatures(object):
def __init__(self, track, sr):
self.track = track
self.sr = sr
hop_length = 2048
frame_length_in_seconds = 10
frame_length = sr*frame_length_in_seconds
final_sample = int(librosa.get_duration(track)*sr)
full_rms = librosa.feature.rms(track, frame_length=frame_length, hop_length=hop_length, center=True)
std_rms = np.std(full_rms)
rms_selection = std_rms + (std_rms-(std_rms*(1-std_rms)))
return
def find_nearest(self, array, value):
array = array
idx = (np.abs(array - value)).argmin()
return idx
def get_min_energy_sample(self, track, sr):
min_value = np.mean(full_rms) - rms_selection
min_value_loc = find_nearest(full_rms, min_value)
min_energy_frame_start = librosa.frames_to_samples(min_value_loc, hop_length=hop_length)
min_energy_frame_end = min_energy_frame_start + frame_length
#check to make sure the frame is 10seconds long otherwise set frame to final 10 seconds
if min_energy_frame_end > final_sample:
min_energy_sample = track[(final_sample-frame_length): final_sample]
else:
min_energy_sample = track[min_energy_frame_start: min_energy_frame_end]
return min_energy_sample
temp_track = AudioFeatures(file_loc, sr) #this works fine
temp_track.get_min_energy_sample()
when running this i am told that full_rms (which is the first variable referenced from the class in the get_min_energy_sample) is not defined. I've tried every combination of self. that I can think of. Any help would be wonderful.
2 Answers 2
You need to remember to store information that you will need to use in the methods as attributes, and then reference them using self., like so:
class AudioFeatures(object):
def __init__(self, track, sr):
self.track = track
self.sr = sr
self.hop_length = 2048
frame_length_in_seconds = 10
self.frame_length = sr*frame_length_in_seconds
self.final_sample = int(librosa.get_duration(track)*sr)
self.full_rms = librosa.feature.rms(track, frame_length=self.rame_length, hop_length=hop_length, center=True)
std_rms = np.std(self.full_rms)
self.rms_selection = std_rms + (std_rms-(std_rms*(1-std_rms)))
def find_nearest(self, array, value):
idx = (np.abs(array - value)).argmin()
return idx
def get_min_energy_sample(self, track, sr):
min_value = np.mean(self.full_rms) - self.rms_selection
min_value_loc = find_nearest(self.full_rms, min_value)
min_energy_frame_start = librosa.frames_to_samples(min_value_loc, hop_length=self.hop_length)
min_energy_frame_end = min_energy_frame_start + self.frame_length
#check to make sure the frame is 10seconds long otherwise set frame to final 10 seconds
if min_energy_frame_end > self.final_sample:
min_energy_sample = track[(self.final_sample-self.frame_length): self.final_sample]
else:
min_energy_sample = track[min_energy_frame_start: min_energy_frame_end]
return min_energy_sample
Comments
@ATony is correct, but let's look at a simpler example, cut down to demonstrate the core issue.
>>> class A(object):
... def __init__(self):
... self.foo = 42
... bar = 27
... def baz(self):
... print(self.foo)
... print(bar)
...
>>> a = A()
>>> a.baz()
42
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 7, in baz
NameError: global name 'bar' is not defined
>>>
Now compare this to the following, where both foo and bar are attributes of self. Now we can access both of them from other methods.
>>> class A(object):
... def __init__(self):
... self.foo = 42
... self.bar = 27
... def baz(self):
... print(self.foo)
... print(self.bar)
...
>>> a = A()
>>> a.baz()
42
27
>>>
self.function_name()rms_selection(and possible other variables) is local to__init__. If you want it available in other methods, you have to make it an instance attribute, liketrackandsr.