Gobinda Sinha
Gobinda Sinha

Reputation: 99

Play two input with each output on two different channels simultaneously using sounddevice

I have two different wav files which are both in mono, what I am trying to do is combine both using sounddevice and mapping the first wav to the first channel and second wav to the second channel and play both at the same time.

weight = 1.4
data, fs = [soundfile.read("tone.wav"),soundfile.read("sound.wav")]
sounddevice.play(data * weight, fs, loop=True, mapping=[1,2])

I have tried a very foolish way which did not work, and I could no figure out a way to do what I am trying.

Upvotes: 1

Views: 1700

Answers (1)

Matthias
Matthias

Reputation: 4914

You should combine the two arrays (which you get from reading the two files) into a single array with two columns. When you play a two-column array, the first column will be played on the first output channel and the second on the second channel (typically left and right, respectively).

If your two mono files happen to have the exact same number of frames, you can simply use

import numpy as np
data_stereo = np.column_stack([data_left, data_right])

Typically, however, the two files will have different lengths. In that case you have to decide if you want to cut the longer one or fill the shorter one up with zeros (or some mix of both).

You can use soundfile.read() for this, which has the argument frames to select how many frames are read from the file, and the argument fill_value to select which value should be used to fill up the resulting array in case the file contains less frames than requested by the frames argument.

You could try something like this:

import numpy as np
import soundfile as sf
import sounddevice as sd

weight = 1.4
length = 100000

data_left, fs_left = sf.read('tone.wav', frames=length, fill_value=0)
data_right, fs_right = sf.read('sound.wav', frames=length, fill_value=0)

assert fs_left == fs_right
assert data_left.ndim == data_right.ndim == 1

data_stereo = np.column_stack([data_left, data_right])

sd.play(data_stereo * weight, fs_left, loop=True)
sd.wait()

If you don't know the length beforehand, you can just read one full file and then adapt the length of the second file, e.g.:

data_left, fs_left = sf.read('tone.wav')
data_right, fs_right = sf.read('sound.wav', frames=len(data_left), fill_value=0)

Upvotes: 1

Related Questions