anton
anton

Reputation: 61

Saving multichannel audio to one channel per file

I am recording from a multichannel audio device using pyaudio and struggle saving each channel in a separate file. I use pyaudio since I am playing back audio simultaneously with the recording, and both use different audio devices. It works fine saving to one file, which is then a multichannel wave file. As a second step, but this is probably a smaller problem, I want to save using Float32, which is not supported by the wave module, so currently I use Int24 instead. Seems for Float32 I should use soundfile. I guess this would not influence the way I split up my recording before saving, or does it?

Here my relevant code parts:

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()

My test recording is 6s long, and from this I see the following: My frames variable is a list of byte object, each the size of chunkchannel_in3. 3 bytes is for Int24 format (for Float32 it would be 4). In the list are duration*fs/chunk elements.

So, how do I unfold frames correctly to one channel each? I tried unfolding it using np.reshape, but didn't figure it out how the channels are interleaved.

Upvotes: 0

Views: 488

Answers (1)

anton
anton

Reputation: 61

Figured it out by myself, to insert after the recording while-loop and replacing the saving with wave by soundfile:

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')

Upvotes: 0

Related Questions