我正在使用 pyaudio 从多通道音频设备进行录制,并且很难将每个通道保存在单独的文件中。我使用 pyaudio,因为我在录音的同时播放音频,并且两者都使用不同的音频设备。它可以很好地保存到一个文件,然后该文件就是一个多通道波形文件。 作为第二步,但这可能是一个较小的问题,我想使用 Float32 进行保存,wave 模块不支持它,所以目前我使用 Int24 代替。看来对于 Float32 我应该使用声音文件。我想这不会影响我在保存之前分割录音的方式,不是吗?
这是我的相关代码部分:
import pyaudio
import wave
sample_format = pyaudio.paInt24 # will need to change later to Float32
fs = 48000
chunk = 1024
rec_stream = p.open(format=sample_format,
channels=channels_in, # usually 6
rate=fs,
frames_per_buffer=chunk,
input=True,
input_device_index=recdevice)
# recording and playback simultaneously from different devices
while len(playdata := wf_play.readframes(chunk)):
play_stream.write(playdata)
data = rec_stream.read(chunk)
frames.append(data)
# saving as multichannel file
wf_rec = wave.open(filename, 'wb')
wf_rec.setnchannels(channels_in)
wf_rec.setsampwidth(p.get_sample_size(sample_format))
wf_rec.setframerate(fs)
wf_rec.writeframes(b''.join(frames))
wf_rec.close()
我的测试录音有6秒长,从中我看到以下内容: 我的框架变量是一个字节对象列表,每个对象的大小为 chunkchannel_in3。 Int24 格式为 3 个字节(Float32 为 4 个字节)。列表中是持续时间*fs/块元素。
那么,如何将帧正确展开到每个通道? 我尝试使用 np.reshape 展开它,但没有弄清楚通道是如何交错的。
我自己想出来了,在录音while循环之后插入并通过声音文件用wave替换保存:
import soundfile as sf
all_channels = np.frombuffer(b''.join(frames), dtype=np.float32)
all_channels = all_channels.reshape(-1, channels_in)
for i in range(channels_in):
filename = str(i+1)
sf.write(filename, all_channels[:,i], fs, 'FLOAT')
您可以使用cutcutcodec轻松完成:
from cutcutcodec.core.io import read, write
from cutcutcodec.core.filter.audio.equation import FilterAudioEquation
with read("multi_channels.mp3") as container:
stream = container.out_streams[0]
for channel, name in stream.layout.channels:
stream_mono = FilterAudioEquation([stream], f"{channel}_0").out_streams[0]
write([stream_mono], f"{name}.mp3", [{"encodec": "libmp3lame", "rate": stream.rate}])