SharpDX XAudio2: 6 SourceVoice предел - PullRequest
       47

SharpDX XAudio2: 6 SourceVoice предел

0 голосов
/ 02 декабря 2018

Я играю с SharpDX.XAudio2 уже несколько дней, и хотя в целом ситуация была в значительной степени положительной (странные странности программного обеспечения здесь и там), следующая проблема застряла у меня:

Яработа в C # .NET с использованием VS2015.
Я пытаюсь воспроизводить несколько звуков одновременно.

Для этого я сделал:
- Test.cs: содержит основной метод
- cSoundEngine.cs: содержит XAudio2, MasteringVoice и методы управления звуком.
- VoiceChannel.cs: Содержит SourceVoice и в будущем любые sfx / связанные данные.

cSoundEngine:

    List<VoiceChannel> sourceVoices;
    XAudio2 engine;
    MasteringVoice master;

public cSoundEngine()
    {
        engine = new XAudio2();
        master = new MasteringVoice(engine);
        sourceVoices = new List<VoiceChannel>();
    }

public VoiceChannel AddAndPlaySFX(string filepath, double vol, float pan)
    {
        /**
         * Set up and start SourceVoice
         */
        NativeFileStream fileStream = new NativeFileStream(filepath, NativeFileMode.Open, NativeFileAccess.Read);
        SoundStream soundStream = new SoundStream(fileStream);
        SourceVoice source = new SourceVoice(engine, soundStream.Format);
        AudioBuffer audioBuffer = new AudioBuffer()
        {
            Stream = soundStream.ToDataStream(),
            AudioBytes = (int)soundStream.Length,
            Flags = SharpDX.XAudio2.BufferFlags.EndOfStream
        };

        //Make voice wrapper
        VoiceChannel voice = new VoiceChannel(source);
        sourceVoices.Add(voice);

        //Volume
        source.SetVolume((float)vol);

        //Play sound
        source.SubmitSourceBuffer(audioBuffer, soundStream.DecodedPacketsInfo);
        source.Start();

        return voice;
    }

Test.cs:

            cSoundEngine engine = new cSoundEngine();
            total = 6;

            for (int i = 0; i < total; i++)
            {
                string filepath = System.IO.Directory.GetParent(System.IO.Directory.GetCurrentDirectory()).Parent.FullName + @"\Assets\Planet.wav";
                VoiceChannel sfx = engine.AddAndPlaySFX(filepath, 0.1, 0);
            }
            Console.Read(); //Input anything to end play.

В настоящее время ничего не стоит показыватьв VoiceChannel.cs - он содержит «SourceVoice source», который является единственным параметром, отправляемым в конструкторе!

Все в порядке и работает до 5 звуков (всего = 5).Все, что вы слышите, - это блаженный дрон Planet.wav.Однако, если значение больше 5, консоль зависает на ~ 5 секунд, а затем закрывается (вероятно, это ошибка c ++, которую отладчик не может обработать).К сожалению, нет сообщения об ошибке, чтобы мы могли что-то посмотреть.
Из тестирования:
- Не будет сбой, если у вас не более 5 запущенных исходных голосов.
- Изменение частоты выборки, похоже, не помогает.
- Установка inputChannels для главного объекта на другое число не имеет значения.
- MasteringVoice, кажется, говорит, что максимальное количество inputvoices составляет 64.
- Создание каждой игры sfx из другого файла wav не имеет значения.
- Настройка громкости для исходных голосов и / или мастера не имеет значения.

Из документации API XAudio2 Я нашел эту цитату: 'XAudio2 удаляет 6-канальныйограничение многоканальных звуков и поддержка многоканального звука на любой многоканальной звуковой плате.Карта не требует аппаратного ускорения. '.Это самое близкое к тому, что я нашел, чтобы упомянуть эту проблему.

Я не очень хорошо разбираюсь в программировании на sfx, и многое из этого является для меня совсем новым, так что не стесняйтесь называть меня идиотом, когда это уместно, но, пожалуйста, попробуйте объяснить это с точки зрения непрофессионала.

Пожалуйста, если у вас есть идеи или ответы, они будут очень благодарны!
-Джош

1 Ответ

0 голосов
/ 04 декабря 2018

Как предложил Чак, я создал банк данных, в котором хранятся данные .wav, и я просто ссылаюсь на одно хранилище данных с каждым буфером.Это улучшило предел звука до 20 - однако это не решило проблему в целом, вероятно, потому что я не реализовал это должным образом.Реализация:

class SoundDataBank
{
    /**
     * Holds a single byte array for each sound
     */

    Dictionary<eSFX, Byte[]> bank;
    string curdir => Directory.GetParent(Directory.GetCurrentDirectory()).Parent.FullName;

    public SoundDataBank()
    {
        bank = new Dictionary<eSFX, byte[]>();
        bank.Add(eSFX.planet, NativeFile.ReadAllBytes(curdir + @"\Assets\Planet.wav"));
        bank.Add(eSFX.base1, NativeFile.ReadAllBytes(curdir + @"\Assets\Base.wav"));
    }

    public Byte[] GetSoundData(eSFX sfx)
    {
        byte[] output = bank[sfx];
        return output;
    }

}

В SoundEngine мы создаем объект SoundBank (инициализированный в конструкторе SoundEngine):

    SoundDataBank soundBank;

    public VoiceChannel AddAndPlaySFXFromStore(eSFX sfx, double vol)
    {
        /**
         * sourcevoice will be automatically added to MasteringVoice and engine in the constructor.
         */
        byte[] buffer = soundBank.GetSoundData(sfx);
        MemoryStream memoryStream = new MemoryStream(buffer);
        SoundStream soundStream = new SoundStream(memoryStream);
        SourceVoice source = new SourceVoice(engine, soundStream.Format);
        AudioBuffer audioBuffer = new AudioBuffer()
        {
            Stream = soundStream.ToDataStream(),
            AudioBytes = (int)soundStream.Length,
            Flags = SharpDX.XAudio2.BufferFlags.EndOfStream
        };


        //Make voice wrapper
        VoiceChannel voice = new VoiceChannel(source, engine, MakeOutputMatrix());

        //Volume
        source.SetVolume((float)vol);

        //Play sound
        source.SubmitSourceBuffer(audioBuffer, soundStream.DecodedPacketsInfo);
        source.Start();

        sourceVoices.Add(voice);

        return voice;
    }

Следуя этой реализации, теперь я могу воспроизводить до 20 звуковых эффектов - но не потому, чтомы играем со звукового банка.Фактически, даже при запуске старого метода для звуковых эффектов теперь получается до 20 экземпляров SFX.

Это улучшилось до 20, потому что мы сделали NativeFile.ReadAllBytes (curdir + @ "\ Assets \ Base.wav") в конструкторе для SoundBank.

Я подозреваю, что NativeFile содержит хранилище данных загруженных файлов, так что вы независимо от того, запускаете ли вы исходный SoundEngine.AddAndPlaySFX () или SoundEngine.AddAndPlaySFXFromStore (), они оба запускаются из памяти?

В любом случае, это увеличило лимит в четыре раза по сравнению с предыдущим, так что это было невероятно полезно - но требует дальнейшей работы.

...