Аудио маршрута VST.NET

Недавно я начал создавать VST-хост, и для этого я использую библиотеку VST.NET для C#. Теперь я пытаюсь создать маршрутизацию между линейным входом, через плагины и линейным выходом. Мой план состоит в том, чтобы записать звук на хост и отправить записанный буфер (живой, когда он записан, не сохраняя временный файл) в первый плагин. Выход первого плагина (который будет плагином эффектов) будет передан следующему плагину. После того, как он прошел через все необходимые плагины, он должен быть направлен на устройство вывода звука.

Для части записи я уже взглянул на NAudio и создал часть записи, например this. Теперь я могу получить аудиобуфер в моем методе isDataAvailable в виде массива байтов. Проблема в том, что VST.NET использует метод ProcessReplacing (я думаю) для обработки звука в плагине, и для этого метода требуется буфер в виде экземпляра массива VstAudioBuffer, а конструктору VstAudioBuffer требуется буфер с плавающей запятой *.

Теперь, как я должен преобразовать эти переменные, чтобы отправить их в плагин? Также, в конце концов, как я могу преобразовать их обратно для отправки в WaveOut?

Другой вопрос: могу ли я после вызова plugin1.processreplacing отправить записанные данные в plugin1, вызвать plugin2.processreplacing с параметрами inputBuffer, являющимися выходным буфером вызова processreplacing для plugin1, чтобы отправить обработанное аудио в plugin2?

Я попытался изменить пример из ссылки и сделал это:

void waveIn_DataAvailable(object sender, WaveInEventArgs e)
    {
        if (waveProvider != null)
            waveProvider.AddSamples(e.Buffer, 0, e.BytesRecorded);
        int bytesRead = waveProvider.Read(naudioBuf,0,e.BytesRecorded);
        naudioBuf = e.Buffer;

        unsafe
        {
            fixed (byte* byteBuf = &naudioBuf[0])
            {
                float* floatBuf = (float*)byteBuf;
                for (int i = 0; i < e.BytesRecorded; i++)
                {
                    vstBufIn[0][i] = *(floatBuf + i);
                }
            }
        }

        cont.PluginCommandStub.MainsChanged(true);
        cont.PluginCommandStub.StartProcess();
        cont.PluginCommandStub.ProcessReplacing(vstBufIn, vstBufOut);
        cont.PluginCommandStub.StopProcess();
        cont.PluginCommandStub.MainsChanged(false);

        unsafe
        {
            float* tmpBufL = ((IDirectBufferAccess32)vstBufOut[0]).Buffer;
            byte[] buffer = BitConverter.GetBytes(*(tmpBufL));
            waveOutProv.AddSamples(buffer, 0, buffer.Length);
        }
    }

Настройка для WaveIn и Out выглядит так:

        WaveIn waveIn = new WaveIn(this.Handle);
        waveIn = new WaveIn(this.Handle);
        waveIn.BufferMilliseconds = 25;
        waveIn.DataAvailable += waveIn_DataAvailable;

        waveProvider = new BufferedWaveProvider(waveIn.WaveFormat);
        waveOutProv = new BufferedWaveProvider(waveIn.WaveFormat);

        waveOut = new WaveOut();
        waveOut.DesiredLatency = 100;
        waveOut.Init(waveOutProv);

        waveIn.StartRecording();
        waveOut.Play();

        this.sampleRate = 44100;
        this.channels = 2;
        this.blockSize = 4410;

        cont.PluginCommandStub.SetBlockSize(blockSize);
        cont.PluginCommandStub.SetSampleRate((float)sampleRate);

        vstBufManIn = new VstAudioBufferManager(channels, blockSize * channels);
        vstBufManOut = new VstAudioBufferManager(channels, blockSize * channels);

        vstBufIn = vstBufManIn.ToArray();
        vstBufOut = vstBufManOut.ToArray();

        naudioBuf = new byte[blockSize * channels * 4];

Я получаю выход, и он также становится громче, когда вход в микрофон громче, но это просто странный «щелчок». Я предполагаю, что сделал что-то не так с преобразованием vstBufOut в массив укусов, но я не совсем понимаю, что не так.


person MariusR    schedule 19.04.2014    source источник
comment
Вы проверили доску обсуждений VST.NET на сайте codeplex? vstnet.codeplex.com/discussions/228692   -  person obiwanjacobi    schedule 19.04.2014
comment
2-й: Да. Для последовательной (цепной) обработки звука требуется только один набор буферов (4 для стерео: 2 входа и 2 выхода). Некоторые хосты даже дают вам один набор (2 для входа и выхода), но я думаю, что это может дать побочные эффекты с плагинами, которые не последовательно читают и записывают буферы...   -  person obiwanjacobi    schedule 19.04.2014
comment
Итак, я попытался изменить код, который вы связали, чтобы его можно было использовать с wavein, но я получаю странный результат. Код добавлен к вопросу.   -  person MariusR    schedule 20.04.2014
comment
У меня также есть 2 других небольших вопроса, для которых не стоит создавать новые вопросы: 1: это единственный (лучший) способ вызвать что-то в плагине с помощью Midi Events (путем создания экземпляра VstMidiEvent и отправки его в плагин)? 2: Мой плагин добавлен в панель в форме Windows, но я не обновляюсь должным образом. Некоторые действия не имеют визуального эффекта, пока не будет выполнено другое действие. Есть ли способ решить эту проблему?   -  person MariusR    schedule 20.04.2014
comment
Я думаю, что сэмплы для NAudio нужно чередовать, а семплы в VST(.NET) — это отдельные каналы. Также вам нужно повторно вызывать (AudioProcessor.)Process, но не методы MainChanged и Start/StopProcessing. Start/StopProcessing указывает, работает ли аудио-движок, а MainChanged включает/выключает питание плагина.   -  person obiwanjacobi    schedule 21.04.2014
comment
1) Помимо обычных методов интерфейса плагина, (Midi)Events и Parameters являются основными способами изменения состояния плагина. Что «что-то» вы пытаетесь вызвать?   -  person obiwanjacobi    schedule 21.04.2014
comment
2) Вы вызываете метод Idle в редакторе?   -  person obiwanjacobi    schedule 21.04.2014
comment
Извините, но я еще не очень хорошо разбираюсь в звуковом программировании, поэтому я действительно не знаю, как это сделать. Я знаю, что могу получить float * для левого и один для правого канала, а затем добавить их в массив float, как в примере в обсуждении, которое вы связали, но не нужен ли мне массив байтов для моего BufferedWaveProvider? Я также попытался воссоздать класс AudioOutput, как в ссылке, с измененным методом Read и изменил wavStream.Read(... на BufferedWaveProvider.Read, заполненный WaveIn. Проблема в том, что либо я получаю исключение ArrayIndexOutofBounds, либо мой аудиодрайвер вылетает...   -  person MariusR    schedule 21.04.2014
comment
1) Хорошо, спасибо. Я пытаюсь запустить MIDI-событие, которое я настраиваю в плагине Mobius Looper, чтобы, например, начать запись. 2) Боюсь, я не знаю (я все еще новичок, когда дело доходит до VST.NET и аудиопрограммирования). Как будет выглядеть вызов этого метода?   -  person MariusR    schedule 21.04.2014
comment
2) Сам разобрался. Теперь я вызываю EditorIdle() для плагина в методе isDataAvailable, и плагин, кажется, обновляется должным образом. Основная проблема, с которой я столкнулся, — это массив байтов для преобразования float* в массив байтов, который я пока не могу понять. и я также не мог найти никакой полезной информации в Интернете....   -  person MariusR    schedule 24.04.2014
comment
VST работает с сэмплами с плавающей запятой в диапазоне [-1, 1]. Вы должны преобразовать это в то, чем вы пытаетесь управлять. Таким образом, вам, возможно, придется преобразовать (отобразить) значение в некоторый целочисленный диапазон, а также чередовать образцы L- и R-каналов, если цель требует этого.   -  person obiwanjacobi    schedule 24.04.2014
comment
Я еще не мог решить эту проблему, хотя я был близок к этому... Я решил опубликовать свой вопрос на форумах codeplex, так как я думаю, что это обсуждение доходит до точки, в которой оно слишком велико для stackoverflow. vstnet.codeplex.com/discussions/544000   -  person MariusR    schedule 02.05.2014