How to realize a multi channel audio pre-mixer in .net

孤街醉人 提交于 2019-12-04 12:25:49

Finally got it: bass.dll allows to apply a matrix as volume settings for every speaker separately using the method BassMix.BASS_Mixer_ChannelSetMatrix(int streamHandle, float[,] volumeMatrix). You can see a sample here, they're using this to upmix a stereo stream to four speakers. Below the full class I created to solve my problem.

public class SeparateVolumeLevelPlayer : IDisposable
{
    private readonly int outputMixerStream;
    private readonly int inputStream;
    private readonly int numberOfSpeakers;

    public SeparateVolumeLevelPlayer(string fileName, int numberOfSpeakers)
    {
        this.numberOfSpeakers = numberOfSpeakers;
        outputMixerStream = BassMix.BASS_Mixer_StreamCreate(44100, numberOfSpeakers, BASSFlag.BASS_MIXER_MATRIX);
        ThrowOnError();

        // create a stream from the media file
        inputStream = Bass.BASS_StreamCreateFile(fileName, 0L, 0L, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_MIXER_MATRIX | BASSFlag.BASS_SAMPLE_MONO);
        ThrowOnError();

        // add the stream to the mixer
        BassMix.BASS_Mixer_StreamAddChannel(outputMixerStream, inputStream, BASSFlag.BASS_MIXER_MATRIX);
        ThrowOnError();
    }

    public void Play()
    {
        // start playback of the mixed streams
        Bass.BASS_ChannelPlay(outputMixerStream, false);
        ThrowOnError();
    }

    public void SetVolume(float[] volumeValues)
    {
        if (volumeValues == null) 
        {
            throw new ArgumentNullException("volumeValues");
        }

        if (volumeValues.Length != numberOfSpeakers)
        {
            string message =
                string.Format("You must pass a volume level for every speaker. You provided {0} values for {1} speakers",
                                            volumeValues.Length, numberOfSpeakers);
            throw  new ArgumentException(message);
        }

        var volumeMatrix = new float[numberOfSpeakers, 1];

        for (int i = 0; i < numberOfSpeakers; i++)
        {
            volumeMatrix[i, 0] = volumeValues[i];
        }

        // adjust the volume using the matrix
        BassMix.BASS_Mixer_ChannelSetMatrix(inputStream, volumeMatrix);
        ThrowOnError();

    }

    private static void ThrowOnError()
    {
        BASSError err = Bass.BASS_ErrorGetCode();
        if (err != BASSError.BASS_OK)
        {
            throw new ApplicationException(string.Format("bass.dll reported {0}.", err));
        }
    }

    public void Dispose()
    {
        Bass.BASS_StreamFree(inputStream);
        Bass.BASS_StreamFree(outputMixerStream);
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!