我的目标是记录计算机的音频输出,实时处理它,然后实时做出反应。我正在使用 PyAudio 和允许环回设备的补丁。我可以毫无问题地将音频录制到文件中,而且听起来很完美,但是当我尝试将其转换为 numpy 数组来处理它时,它主要是噪音,您可以听到信号极度失真。
这是产生噪声输出的最小示例。在这种情况下,输入是麦克风来剪切输入选择代码,但结果是相同的:我的输入的极其嘈杂的表示。
import numpy as np
import pyaudiowpatch as pyaudio
import wave
import sounddevice as sd
from matplotlib import pyplot as plt
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
CHUNK = 1048
RECORD_SECONDS = 5
WAVE_OUTPUT_FILENAME = "file.wav"
p = pyaudio.PyAudio()
stream = p.open(format=FORMAT, channels=CHANNELS,
rate=RATE, input=True,
frames_per_buffer=CHUNK)
print("recording...")
frames = []
fulldata = np.empty(RATE*RECORD_SECONDS*CHANNELS)
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
print(i)
data = stream.read(CHUNK)
numpydata = np.frombuffer(data, dtype='int16')
fulldata[i*CHUNK*CHANNELS:(i+1)*CHUNK*CHANNELS] = numpydata
frames.append(data)
print("finished recording")
channel0 = fulldata[0::CHANNELS]
print('playing')
sd.play(channel0, samplerate=RATE, blocking=True)
# stop Recording
stream.stop_stream()
stream.close()
p.terminate()
waveFile = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
waveFile.setnchannels(CHANNELS)
waveFile.setsampwidth(p.get_sample_size(FORMAT))
waveFile.setframerate(RATE)
waveFile.writeframes(b''.join(frames))
waveFile.close()
为了达到这一点,我遵循了从 pyaudio 中获取 numpy 数据的其他问题,并且录制的文件听起来很完美,因此转换之前的一切似乎都有效。输入有两个通道,我不确定数据是如何构造的,所以我假设数据正在交替通道,这也在提供channel0代码的另一个问题中建议。我假设在获取数据和使用 SD 播放数据之间存在问题。我什至尝试先将其保存到文件中,然后使用 librosa 再次加载它,当使用 sd 播放时,这听起来很完美。我确实注意到,在记录时采样率为 48000,但在加载 wav 文件时,sr 为 22050。我还尝试查看 writeframes 函数以获取有关此问题的任何线索,但没有运气。 p.get_sample_size(FORMAT) 是两个,因为 waveFile 期望提供它,但 np 不知道它,我认为这可能会导致一些问题,但我不知道如何调查这个问题。
我刚刚在堆栈上搜索了更多内容,有几个关于转换为 np 的问题,他们都说通道是交替的,这个解决方案应该有效。这可能与延迟有关吗?但我真的不知道如何设置。
是否有不同的方法将其转换为 np 数组,或者我在这里遗漏了其他内容?非常感谢任何对此的帮助。
哇我自己发现了错误。问题出在
fulldata = np.empty(RATE*RECORD_SECONDS*CHANNELS)
我没有指定数据类型,因此 np 创建了一个 float64 数组,并且可能做了一些奇怪的转换,导致了失真。我将其更改为 int16 现在可以使用了。