Выходной буфер AudioUnit и входной буфер

Мой вопрос: что мне делать, когда я использую растяжку в реальном времени? Я понимаю, что изменение скорости изменит количество выборок для вывода. Например, если я растягиваю звук с коэффициентом 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;
    };

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


person Ruslan    schedule 21.09.2018    source источник


Ответы (1)


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

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

person hotpaw2    schedule 23.09.2018
comment
Вот почему SuperpoweredTimeStretch выводит данные в список буферов (outputBuffers в приведенном выше примере). - person Gabor Szanto; 26.09.2018