Audiokit, как воспроизвести измененный буфер в кране? - PullRequest
2 голосов
/ 20 сентября 2019

Я использую Audiokit (в Objective-C) для обработки звука в реальном времени.Я передаю алгоритм C ++ через тап или ленивый тап, где изменяется буфер.Я думал, что это будет очевидно, но ... как я могу воспроизвести измененный буфер в выводе?Краны только для анализа?

[self->microphoneGain.avAudioNode installTapOnBus:0 bufferSize:1024 format:format block:^(AVAudioPCMBuffer * _Nonnull buffer, AVAudioTime * _Nonnull when) {  
    if (buffer.frameLength == 0) {  
        return;
    }
    // Process data -> return modified buffer
    processData(buffer.floatChannelData[0], buffer.floatChannelData[1], buffer.frameLength);
    // -> How to play back buffer?
}];

Более того, я не могу получить размер буфера меток ниже 4800 сэмплов.Какой мой лучший вариант, чтобы получить лучшее время ожидания?Я читал о создании подклассов AUAudioUnit, обратном вызове рендеринга или режиме реального времени для AudioEngine, но я совершенно растерялся, пытаясь реализовать один из них с помощью AudioKit.Спасибо!

РЕДАКТИРОВАТЬ:

Мне удалось установить обратный вызов рендеринга, который, по-видимому, решил обе мои проблемы.

AURenderCallbackStruct processingCallback;
processingCallback.inputProc = processingCalbackProc;
processingCallback.inputProcRefCon = (__bridge void *)(self);
OSStatus status = AudioUnitSetProperty(AudioKit.engine.outputNode.audioUnit,
    kAudioUnitProperty_SetRenderCallback,
    kAudioUnitScope_Input,
    0,
    &processingCallback,
    sizeof(processingCallback));
if(status != noErr) {
    return false;
}

OSStatus processingCalbackProc (void *inRefCon,
                           AudioUnitRenderActionFlags *ioActionFlags,
                           const AudioTimeStamp *inTimeStamp,
                           UInt32 inBusNumber,
                           UInt32 inNumberFrames,
                           AudioBufferList *ioData)
{
    __unsafe_unretained MyClass *self = (__bridge MyClass *)inRefCon;
    printf("%u, ", (unsigned int)inNumberFrames); // -> low latency!

    if (!ioData) ioData = self->audioBufferList;
    OSStatus status = AudioUnitRender(AudioKit.engine.outputNode.audioUnit,
                                      ioActionFlags,
                                      inTimeStamp,
                                      1,
                                      inNumberFrames,
                                      ioData);
    if(status != noErr) { return status; }

    // Get buffers
    unsigned int inputChannels = 2;
    float *buffer[inputChannels];
    for (int i = 0; i < inputChannels; i++) {
        buffer[i] = (float *)ioData->mBuffers[i].mData;
    }

    // Process data
    processData(buffer[0], buffer[1], inNumberFrames);

    return noErr;
}

Теперь я могулегко получить буферы размером до 256 сэмплов (возможно, даже меньше, но в моем случае это не требуется), и когда buffer[n] модифицируется, он выводит модифицированные буферы.Кажется, все хорошо, я просто надеюсь, что это правильный подход.

...