CSCore - Convert stereo to surround

790 views Asked by At

I have to decode a stereo mp4 file and map the L and R channel to 5.1 or 7.1 surround. In addition I have to provide a specific output format: 16bit pcm 44.1kHz. Its no problem to convert the audio source to 44100Hz 16bit. The only problem is the channel mixing. I've got the following coding:

const string filename = @"stereo.mp3";
IWaveSource waveSource = CodecFactory.Instance.GetCodec(filename)
    .AppendSource(x => new CSCore.Streams.CachedSoundSource(x))
    .ChangeSampleRate(44100) //44.1kHz
    .ToSampleSource()
    .ToWaveSource(16); //16bit

The official project page here: http://cscore.codeplex.com/ tells me that channel mixing is possible. I've found the CSCore.DSP.ChannelMatrix class but its pretty hard to figure out how to use it. Maybe someone could help me out?

1

There are 1 answers

0
Florian On

You are absolutely right, you have to use the CSCore.DSP.ChannelMatrix class. I've created a little example for you and added some comments. It should be pretty much self explaining:

static void Main(string[] args)
{
    const string filename = @"stereo.mp3";

    /*
     * First of all you need a channel matrix that fits your needs.
     * There are many ways to get one...:
     */

    //Simply use one of the predefined...
    ChannelMatrix channelMatrix = ChannelMatrix.StereoToSevenDotOneSurround;

    //or

    //use some kind of factory to get one
    channelMatrix = ChannelMatrix.GetMatrix(
        ChannelMasks.StereoMask,
        ChannelMasks.SevenDotOneMask);

    //or

    //or create your own one (the matrix below equals the two above but of course you can use custom values)
    //the rows represent your input channels (the stereo signal) and the columns your output channels.
    //specify with a value from 0-1 how much percentage of the L (row index 0) or the R (row index 1) channel
    //you want to apply to the specific column (the columns are getting mapped to the output channel mask
    // -> the SevenDotOneMask ordered by the values of the certain flags inside of the channel mask).
    channelMatrix = new ChannelMatrix(
        ChannelMasks.StereoMask,
        ChannelMasks.SevenDotOneMask);
    channelMatrix.SetMatrix(
        new[,]
        {
            {0.222f, 0f, 0.157f, 0.022f, 0.189f, 0.116f, 0.203f, 0.090f},
            {0f, 0.222f, 0.157f, 0.022f, 0.116f, 0.189f, 0.090f, 0.203f}
        });

    IWaveSource waveSource = CodecFactory.Instance.GetCodec(filename)
        .AppendSource(x => new CSCore.Streams.CachedSoundSource(x))
        .ChangeSampleRate(44100) //44.1kHz
        .AppendSource(x => new DmoChannelResampler(x, channelMatrix)) //append a channelresampler with the channelmatrix
        .ToSampleSource()
        .ToWaveSource(16); //16bit

    ...
}

I would strongly recommend you to use a predefined channel matrix. Of course, if you need some custom values define your own like in the example above.

Btw. you can also change the channel matrix in realtime: Simply make your changes to the channelMatrix and after that call CommitChannelMatrixChanges (of course you would have to store the DmoChannelResampler instance -> do that by using the out parameter of the AppendSource method).