Recently I wanted to use gstreamer to add some very basic audio support to an application. I just used the playbin element to play audio files and added some logic to control volume (easy enough with playbin since you can just set it directly) and looping a sound N number of times (which is also easy enough, since you can just watch EOS on the pipeline, seek to the beginning and play again).
There was however one thing that I wanted to implement that left me a bit puzzled. I wanted to control the volume of each channel of an audio file independently. The why is not really important. My first thought was to use the “volume” element. It implements the GstMixer interface, which supposedly could be used to control independently the volume of each of the channels. Easy enough, right? Wrong… Even though the volume element implements the mixer interface, it does not actually implement the part where you can control the volume of each of the audio channels. If you look at the mixer track, you just see one channel.
So what can you do? It turns out that what you need to do is to take your audio, deinterleave the multichannel audio into single multiple mono channels. Then to put a volume element of each of those mono channels and finally to interleave those channels again. Even though this is maybe still relatively simple, it took me quite some time to figure it out. Anyway, here is the pipeline that would do this:
gst-launch-0.10 -v filesrc location=audio.wav name=src ! decodebin ! deinterleave keep-positions=true name=d interleave name=i ! autoaudiosink d.src0 ! queue ! volume volume=0.5 ! i.sink1 d.src1 ! queue ! volume volume=1 ! i.sink2
This would play the file “audio.wav” with the left channel at 0.5 and the right channel at 1. Note that I had to put keep-positions to true on the deinterleave element (although I don’t know exactly why, it seems to have something to do with the pulsesink element: #657457.
Since I’m a gstreamer newbie, please let me know if there is something I misunderstood about all of this, or if there is a better way to do what I want.
The GstMixer/GstMixerTrack way should work as well. It’s only supposed to expose one GstMixerTrack (just like a volume control will usually show left+right channels of one input/output grouped together). gst_mixer_set_volume() takes a mixer track and an array of volume values, one for each channel.
I know, note that when I say it only exposes one channel, is that I really mean one “channel”, not track. If you look at the first (and only) track in the volume element, it still only has one channel you can control.