Я использую 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]
модифицируется, он выводит модифицированные буферы.Кажется, все хорошо, я просто надеюсь, что это правильный подход.