Выходной буфер AudioUnit и входной буфер - PullRequest
0 голосов
/ 21 сентября 2018

Мой вопрос: что мне делать, когда я использую растяжку в реальном времени?Я понимаю, что изменение скорости изменит количество отсчетов для вывода.Например, если я растягиваю звук с коэффициентом 2.0, выходной буфер будет больше (в два раза).

Итак, что мне делать, если я создаю реверберацию, задержку или растяжение в реальном времени?

Например, мой входной буфер составляет 1024 семпла.Затем я растягиваю звук с коэффициентом 2.0.Теперь у меня в буфере 2048 сэмплов.

В этом коде со сверхмощным растяжением звука все работает.Но если я не изменяю скорость ... Когда я меняю скорость - она ​​звучит с искажением без фактического изменения скорости.

return ^AUAudioUnitStatus(AudioUnitRenderActionFlags    *actionFlags,
                              const AudioTimeStamp      *timestamp,
                              AVAudioFrameCount         frameCount,
                              NSInteger             outputBusNumber,
                              AudioBufferList           *outputBufferListPtr,
                              const AURenderEvent       *realtimeEventListHead,
                              AURenderPullInputBlock        pullInputBlock ) {

        pullInputBlock(actionFlags, timestamp, frameCount, 0, renderABLCapture);

        Float32 *sampleDataInLeft = (Float32*) renderABLCapture->mBuffers[0].mData;
        Float32 *sampleDataInRight = (Float32*) renderABLCapture->mBuffers[1].mData;

        Float32 *sampleDataOutLeft  = (Float32*)outputBufferListPtr->mBuffers[0].mData;
        Float32 *sampleDataOutRight = (Float32*)outputBufferListPtr->mBuffers[1].mData;


        SuperpoweredAudiobufferlistElement inputBuffer;
        inputBuffer.samplePosition = 0;
        inputBuffer.startSample = 0;
        inputBuffer.samplesUsed = 0;
        inputBuffer.endSample = frameCount;
        inputBuffer.buffers[0] = SuperpoweredAudiobufferPool::getBuffer(frameCount * 8 + 64);
        inputBuffer.buffers[1] = inputBuffer.buffers[2] = inputBuffer.buffers[3] = NULL;

        SuperpoweredInterleave(sampleDataInLeft, sampleDataInRight, (Float32*)inputBuffer.buffers[0], frameCount);

        timeStretch->setRateAndPitchShift(1.0f, -2);
        timeStretch->setSampleRate(48000);
        timeStretch->process(&inputBuffer, outputBuffers);

        if (outputBuffers->makeSlice(0, outputBuffers->sampleLength)) {

            int numSamples = 0;
            int samplesOffset =0;

            while (true) {

                Float32 *timeStretchedAudio = (Float32 *)outputBuffers->nextSliceItem(&numSamples);
                if (!timeStretchedAudio) break;

                  SuperpoweredDeInterleave(timeStretchedAudio, sampleDataOutLeft + samplesOffset, sampleDataOutRight + samplesOffset, numSamples);

                samplesOffset += numSamples;

            };

            outputBuffers->clear();

        }

        return noErr;
    };

Итак, как я могу создать свой блок рендеринга аудиоустройства, когда мой вводи выходные буферы имеют различное количество сэмплов (реверберация, задержка или растяжение времени)?

1 Ответ

0 голосов
/ 23 сентября 2018

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

Часто циклические буферы используются для разделения входной, обрабатывающей и выходной частот выборки или размеров буфера.

...