我想就如何进一步调查问题的原因征求意见
我正在开发一个音频分析器python应用程序。预期的硬件由一个64位的raspberry pi 4、8 GB Ram、32 GB sd卡和一个外部声卡(hifi berry adc+dac)组成。 有趣的代码位于Capture.py模块中,该模块将执行以下任务
我偶尔会遇到一些回调状态:(输入溢出,输出下溢),主要是在捕获时间很短(不到两秒)时。大多数情况下,代码都是按预期工作的,但有时这种行为开始发生,就好像回调占用了大量CPU资源一样。有趣的是,如果我增加实验持续时间,超过两三秒(也就是说,更大的缓冲区和更多的内存使用),问题似乎就消失了。(从我的角度来看)这似乎很奇怪。因为它们是预分配和预计算的,所以缓冲区大小对回调函数应该是透明的,对吗? 到目前为止,我已经尝试:
这些行动似乎都没有对问题产生任何影响
我的Capture.py模块代码供参考。捕获实验由start方法启动,但问题发生在回调方法上
from .Config import Config
import sounddevice as sd
import numpy as np
class Capture:
def __init__(self, config):
self.paa_config = config
self.capturing = False
pass
def start(self):
self.getCaptureTime()
self.time = np.arange(self.total_frames)*1/self.paa_config.SamplingFrequency
self.computeTones()
self.frame_counter = 0
print("Start capture")
self.capturing = True
with sd.Stream(channels=2, device=self.paa_config.SoundDevice, samplerate=self.paa_config.SamplingFrequency, dtype='float32', callback=self.callback, finished_callback=self.finished_callback):
sd.sleep(int(self.capture_time)*1100)
while self.capturing:
pass
# capture ended... perform some testing... to be moved to Process.py module
start_index = self.smooth_frames+self.latency_frames
end_index = self.process_frames + start_index
print("input_buffer shape is ", self.input_buffer.shape)
self.process_data = self.input_buffer[start_index:end_index]
self.fft_signal = abs(np.fft.rfft(self.process_data, axis=0)/self.process_frames*2)
self.fft_signal[0,:] /= 2
self.fft_signal = 20 * np.log10(self.fft_signal)
print("fft_signal shape is", self.fft_signal.shape)
print("self.process_data.size is: ", self.process_data.size)
self.fft_frequency = np.fft.rfftfreq(int(self.process_data.size/2), d=1/self.paa_config.SamplingFrequency)
print("fft_frequency shape is", self.fft_frequency.shape)
pass
def callback(self, indata, outdata, frames, time, status):
#print("new chunk capture, ", frames, " frames to process")
if status:
print("At frame ", self.frame_counter, "of ", self.total_frames, "frames")
print(status)
#raise sd.CallbackStop
if (self.frame_counter+frames) <= self.total_frames:
self.input_buffer[self.frame_counter:self.frame_counter+frames, :] = indata
outdata[:] = self.output_buffer[self.frame_counter:self.frame_counter+frames,:]
self.frame_counter += frames
else:
aframes = self.total_frames-self.frame_counter
self.input_buffer[self.frame_counter:self.total_frames, :] = indata[aframes,:]
outdata[0:aframes,:] = self.output_buffer[self.frame_counter:self.total_frames,:]
self.frame_counter += aframes
raise sd.CallbackStop
pass
def finished_callback(self):
self.capturing = False
print("End capture")
pass
def getCaptureTime(self):
self.smooth_frames = int(self.paa_config.SmoothTime * self.paa_config.SamplingFrequency)
self.process_frames = int((1/self.paa_config.Resolution.resolution)*self.paa_config.Averaging.averaging * self.paa_config.SamplingFrequency)
self.latency_frames = int(self.paa_config.LatencyExtraTime * self.paa_config.SamplingFrequency)
self.total_frames = 2*self.smooth_frames+self.process_frames+self.latency_frames
self.capture_time = self.total_frames/self.paa_config.SamplingFrequency
return self.capture_time
pass
def smoothEnvelope(self):
t = self.time
smooth_time = self.paa_config.SmoothTime
start_time = t[0]+smooth_time
end_time = t[-1]-smooth_time
ret = np.ones(t.shape)
x_smooth = ((t[t<start_time]-t[0])/smooth_time)
ret[t<start_time] = ( 6*(x_smooth**5) - 15*(x_smooth**4) + 10*(x_smooth**3) )
x_smooth = ((t[-1]-t[t>end_time])/smooth_time)
ret[t>end_time] = ( 6*(x_smooth**5) - 15*(x_smooth**4) +10*(x_smooth**3) )
return ret
pass
def computeTones(self):
self.output_buffer = np.zeros((self.total_frames, 2))
self.input_buffer = np.zeros((self.total_frames, 2))
self.envelope = self.smoothEnvelope()
for it_g in range(len(self.paa_config.Generators)):
for t in self.paa_config.Generators[it_g].Tones:
if t.Enabled:
if t.Wave == Config.Enums.Wave.Sine:
self.output_buffer[:,it_g] += t.Amplitude*np.sin(2*np.pi*t.Frequency*self.time)
elif t.Wave == Config.Enums.Wave.Square:
#self.output_buffer[:,it_g] += t.Amplitude*np.sign(np.sin(2*np.pi*t.Frequency*self.time))
#print(((t.Frequency*self.time)%1)>0.0, flush=True)
self.output_buffer[((t.Frequency*self.time)%1)>0.5,it_g] += -t.Amplitude
self.output_buffer[((t.Frequency*self.time)%1)<0.5,it_g] += t.Amplitude
elif t.Wave == Config.Enums.Wave.Triangle:
# TODO
#self.output_buffer[:,it_g] += t.Amplitude*np.sin(2*np.pi*t.Frequency*self.time)
self.output_buffer[:,it_g] += 4*(np.abs(((t.Frequency*self.time-0.25)%1)-0.5)-0.25)*t.Amplitude
elif t.Wave == Config.Enums.Wave.Sawthoot:
# TODO
#self.output_buffer[:,it_g] += t.Amplitude*np.sin(2*np.pi*t.Frequency*self.time)
self.output_buffer[:,it_g] += -(((t.Frequency*self.time)%1)-0.5)*2*t.Amplitude
elif t.Wave == Config.Enums.Wave.Pulse:
# TODO
#self.output_buffer[:,it_g] += t.Amplitude*np.sin(2*np.pi*t.Frequency*self.time)
self.output_buffer[((t.Frequency*self.time)%1)>0.225,it_g] += t.Amplitude
self.output_buffer[((t.Frequency*self.time)%1)>0.275,it_g] += -t.Amplitude
self.output_buffer[((t.Frequency*self.time)%1)>0.725,it_g] += -t.Amplitude
self.output_buffer[((t.Frequency*self.time)%1)>0.775,it_g] += t.Amplitude
else:
raise ValueError("Invalid value for Wave Enum")
pass
pass
pass
self.output_buffer[:,it_g] *= self.envelope
pass
pass
目前没有回答
相关问题 更多 >
编程相关推荐