4

C# を使用して、複数のオーディオ ストリームを同時に再生できるアプリケーションを実装したいと考えています。ピーナッツ - ここで興味深いのは、すべてのストリームが単一チャンネル (モノラル) であると仮定して、すべてのストリームのすべてのスピーカー (5.1 または 7.1) の音量を個別に調整したいということです。Windows ミキサーを使用してこれを行うことができますが、問題は、ミキサーが 1 つしかなく、ストリームごとに個別に調整したいということです。これを実装する方法はありますか?

私の最初の推測では、ストリームを 8 倍 (7.1) 多重化し、すべての「チャネル」にボリューム レベルを適用してから、Windows ミキサーに送信します。そのようなユースケースをサポートする可能性のあるライブラリを知っていますか?

私の知る限り、ベースと fmod はこれを行うことができませんが、間違っている場合は修正してください。別の方法として、このために XNA をハッキングすることを考えていました: リスナーに関連するストリームの位置を記述するベクトルを使用し、これを使用してボリューム補正を適用します... ただのとりとめのないことです。

(そして、これに関する C++/WinAPI のアイデアを私に指摘しないでください。このプロジェクトは、今すぐ別の言語を学ぶ価値はありません。)

4

1 に答える 1

2

最後にそれを手に入れました:bass.dllは、メソッドを使用して、すべてのスピーカーの音量設定としてマトリックスを個別に適用できますBassMix.BASS_Mixer_ChannelSetMatrix(int streamHandle, float[,] volumeMatrix)ここでサンプルを見ることができます。彼らはこれを使用して、ステレオ ストリームを 4 つのスピーカーにアップミックスしています。私の問題を解決するために作成した完全なクラスの下。

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);
    }
}
于 2009-10-31T17:48:29.733 に答える