2

I'm trying to mix audio from 6 mono audio input channels (and a few wav files) to two audio output channels.

I've skimmed though the PyAudio documentation and figured out how to access the sound card I want and get the audio. I noticed the channel map example, but I'm a bit confused about using it.

I've also spotted this answer and this technique would work, but for 6+ channels wouldn't this get a bit slow ?

What's the recommended or most efficient way of mixing multiple sound channels with pyaudio ?

Community
  • 1
  • 1
George Profenza
  • 50,687
  • 19
  • 144
  • 218
  • What makes you think mixing in NumPy will be too slow? Do you really think it'll take more than 20ms to zip together and mix 6 different 20ms frames using NumPy? Also, why not just _try_ it instead of trying to guess? – abarnert May 17 '15 at 23:40
  • @abarnert good point, I will test as soon as I get my hands on the hardware again. I guess one facet of my question was making sure I don't try to implement this in some weird way, when the pyaudio api might already provide something built in, but I'm not spotting it. – George Profenza May 17 '15 at 23:52

1 Answers1

4

The answer you linked to uses NumPy to mix together two streams by averaging the frames from each stream.

You're worried that this might be too slow. I doubt it, because NumPy is just looping over a C array in C, the same way a dedicated software mixer would (whether in your sound server, your soundcard driver, or some OS-level mixer). But rather than guessing, let's find out.

First, let's assume that we're dealing with 20ms frames, and our callback will be called for every single frame, since that's just about the worst case scenario. And let's assume for concreteness that we've got 44.1KHz 16-bit stereo streams, so each one is 1764 samples. So, let's write this the most inefficient way I can think of and then test it:

In [4]: frame = np.zeros(1764, dtype=np.int16)
In [5]: %timeit np.mean([frame]*6, axis=0, dtype=np.int16)
1000 loops, best of 3: 1.01 ms per loop

To get to 20ms, I have to mix 387 streams. 6 isn't going to be a problem.

And if it is a problem, you need to do something trickier—e.g., prebuffer the mix so you have much larger chunks to work on than single frames (for more looping in C, less in Python), or even access a hardware mixer—which you probably can't do through PyAudio.

Community
  • 1
  • 1
abarnert
  • 354,177
  • 51
  • 601
  • 671
  • Thank you sharing these results(+1), I'll be sure to test with the sound card as well. – George Profenza May 17 '15 at 23:54
  • @GeorgeProfenza: The sound card doesn't really matter here (except maybe indirectly influencing how often PyAudio will call your callback); it's more an issue of your CPU. At any rate, unless you actually need to access a hardware mixer on your soundcard (in which case you don't want to use PyAudio, but something that provides lower-level access), the software mixing provided by custom code in the OS or sound server or soundcard driver or whatever is at best going to be faster than NumPy by a small constant multiplier; they're both effectively just looping over a C array in C. – abarnert May 17 '15 at 23:58