2009-10-26 7 views
3

Я бы хотел использовать C# для реализации приложения, которое может воспроизводить несколько аудиопотоков одновременно. Peanuts - теперь интересная часть: если каждый поток является одноканальным (моно), я хочу настроить громкость для каждого динамика (5.1 или даже 7.1) для каждого потока отдельно. Я могу использовать микшер Windows для этого, но проблема в том, что есть только один микшер, и я хочу настроить его для каждого потока отдельно. Есть идеи, как это реализовать?Как реализовать многоканальный предварительный микшер в .net

Мое первое предположение состояло в том, чтобы мультиплексировать поток восемь раз (7.1), применить уровень громкости для каждого «канала», а затем отправить его в микшер, который выравнивается для всех каналов с 80%, например. Знаете ли вы какие-либо библиотеки, которые могут поддерживать такой вариант использования?

AFAIK бас и fmod не могут этого сделать, но исправьте меня, если я ошибаюсь. В качестве альтернативы я думал о том, чтобы взломать XNA для этого: используя вектор, который описывает положение потока, связанного с слушателем, и используя это, чтобы применить компенсацию объема ... просто проветривание.

(и, пожалуйста, не указывают мне на некоторые C++/WinAPI идеи по этому вопросу, этот проект не стоит изучать другой язык в настоящее время.)

+0

Возможно, одна идея, которая только что прибыла в мой мозг: вполне нормально требовать, чтобы доступные звуковые файлы были импортированы и транскодированы изначально в своего рода звуковой банк. Формат vorbis поддерживает до 255 каналов, и есть (возможно, оставленная) библиотека lib: http://vorbisdotnet.sourceforge.net/ –

+0

Немного натыкается: я нашел библиотеку NAudio на Codeplex. Хороший материал ... –

ответ

1

Наконец получил его: bass.dll позволяет применить матрицу в качестве громкости для каждого громкоговорителя отдельно с использованием метода BassMix.BASS_Mixer_ChannelSetMatrix(int streamHandle, float[,] volumeMatrix). Вы можете увидеть образец here, они используют это для увеличения стереопотока до четырех динамиков. Ниже полного класса, который я создал для решения моей проблемы.

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); 
    } 
}