iOS: Как выполнить повторную выборку аудио (данные PCM) с помощью Audio Unit во время выполнения?

Как я могу ресэмплировать аудио (данные PCM), используя Audio Unit во время выполнения / в реальном времени?

У меня аудиоустройство настроено следующим образом.

- (void) setUpAudioUnit {
OSStatus status;
AudioComponentInstance audioUnit;
AudioComponent inputComponent;
AudioComponentDescription audioComponentDescription;
AudioStreamBasicDescription audioStreamBasicDescription;

// Describe audio component
audioComponentDescription.componentType = kAudioUnitType_Output;
audioComponentDescription.componentSubType = kAudioUnitSubType_VoiceProcessingIO;
audioComponentDescription.componentFlags = 0;
audioComponentDescription.componentFlagsMask = 0;
audioComponentDescription.componentManufacturer = kAudioUnitManufacturer_Apple;

// Get component
inputComponent = AudioComponentFindNext(NULL, &audioComponentDescription);

// Get audio units
status = AudioComponentInstanceNew(inputComponent, &audioUnit);
checkStatus(status);

// Enable IO for recording
UInt32 flag = 1;
status = AudioUnitSetProperty(audioUnit,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Input,
kInputBus,
&flag,
sizeof(flag));
checkStatus(status);

// Enable IO for playback
status = AudioUnitSetProperty(audioUnit,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Output,
kOutputBus,
&flag,
sizeof(flag));
checkStatus(status);

// Describe format
audioStreamBasicDescription.mSampleRate         = AUDIO_SAMPLE_RATE;
audioStreamBasicDescription.mFormatID           = kAudioFormatLinearPCM;
audioStreamBasicDescription.mFormatFlags        = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
audioStreamBasicDescription.mFramesPerPacket    = AUDIO_FRAMES_PER_PACKET;
audioStreamBasicDescription.mChannelsPerFrame   = AUDIO_CHANNELS_PER_FRAME;
audioStreamBasicDescription.mBitsPerChannel     = AUDIO_BITS_PER_CHANNEL;
audioStreamBasicDescription.mBytesPerPacket     = AUDIO_BYTES_PER_PACKET;
audioStreamBasicDescription.mBytesPerFrame      = AUDIO_BYTES_PER_FRAME;

// Apply format
status = AudioUnitSetProperty(audioUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output,
kInputBus,
&audioStreamBasicDescription,
sizeof(audioStreamBasicDescription));
checkStatus(status);/* Make sure we set the correct audio category before restarting */
UInt32 audioCategory = kAudioSessionCategory_PlayAndRecord;
status = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory,
sizeof(audioCategory),
&audioCategory);

checkStatus(status);status = AudioUnitSetProperty(audioUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
kOutputBus,
&audioStreamBasicDescription,
sizeof(audioStreamBasicDescription));
checkStatus(status);// Set input callback
AURenderCallbackStruct callbackStruct;
callbackStruct.inputProc = recordingCallback;
callbackStruct.inputProcRefCon = (__bridge void *)(self);
status = AudioUnitSetProperty(audioUnit,
kAudioOutputUnitProperty_SetInputCallback,
kAudioUnitScope_Global,
kInputBus,
&callbackStruct,
sizeof(callbackStruct));
checkStatus(status);

// Set output callback
callbackStruct.inputProc = playbackCallback;
callbackStruct.inputProcRefCon = (__bridge void *)(self);
status = AudioUnitSetProperty(audioUnit,
kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Global,
kOutputBus,
&callbackStruct,
sizeof(callbackStruct));
checkStatus(status);

// Disable buffer allocation for the recorder (optional - do this if we want to pass in our own)
flag = 0;
status = AudioUnitSetProperty(audioUnit,
kAudioUnitProperty_ShouldAllocateBuffer,
kAudioUnitScope_Output,
kInputBus,
&flag,
sizeof(flag));}

А настройки аудио таковы.

kOutputBus 0
kInputBus 1
AUDIO_SAMPLE_RATE 44100
AUDIO_FRAMES_PER_PACKET 1
AUDIO_CHANNELS_PER_FRAME 1
AUDIO_BITS_PER_CHANNEL 16
AUDIO_BYTES_PER_PACKET 2
AUDIO_BYTES_PER_FRAME 2

Я получаю данные PCM от записи обратного вызова как

audioBufferList->mBuffers[0].mData

Итак, как я могу повторно сэмплировать эти данные PCM с 44,1 кГц до 8 кГц и наоборот?
Я много гуглил, но не нашел ни примера кода, ни прямой инструкции для этого.

Нашел эти темы, но ни одна из них не содержит четких инструкций.

  1. Какой из встроенных AudioUnit может ресэмплировать звук?
  2. Изменение частоты дискретизации AUGraph на iOS

Любой пример кода или информация высоко ценится.

4

Решение

Аудиоустройство конвертера будет обрабатывать ваши преобразования частоты дискретизации. Я считаю, что лучший способ справиться с этим — адаптировать вашу цепочку к тому, что аппаратное обеспечение делает изначально. Это означает, что вы должны получить системную AudioStreamBasicDescription (sysASBD), а затем поместить преобразователи между системой и частями вашей цепочки, которые нуждаются в чем-то другом. Таким образом, для воспроизведения звука с 8K sampleRate вы должны сделать следующее: ReomoteIO (микрофон) -> конвертер -> обработка вашего 8K -> конвертер -> RemoteIO (выход).

Вот описание для конвертера.

AudioComponentDescription convDesc;
convDesc.componentType = kAudioUnitType_FormatConverter;
convDesc.componentSubType = kAudioUnitSubType_AUConverter;
convDesc.componentFlags = 0;
convDesc.componentFlagsMask = 0;
convDesc.componentManufacturer = kAudioUnitManufacturer_Apple;

Вот как вы получаете системы ASBDin и ASBDout

UInt32 sizeASBD = sizeof(AudioStreamBasicDescription);
AudioStreamBasicDescription ioASBDin;
AudioStreamBasicDescription ioASBDout;
AudioUnitGetProperty(remoteIO, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 1, &ioASBDin, &sizeASBD);
AudioUnitGetProperty(remoteIO, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &ioASBDout, &sizeASBD);

Все, что вам нужно сделать, чтобы использовать конвертер, — это установить его входной ASBD и вывести ASBD в желаемые форматы, и он сделает всю работу. Сделайте ваши соединения, и у вас есть 8K играть через.

AudioStreamBasicDescription asbd8K;

AudioComponentInstance converter44To8;
AudioUnitSetProperty(converter44To8,kAudioUnitProperty_StreamFormat,kAudioUnitScope_Input,0,& ioASBDin,sizeof(AudioStreamBasicDescription));
AudioUnitSetProperty(converter44To8,kAudioUnitProperty_StreamFormat,kAudioUnitScope_Output,0,&asbd8K,sizeof(AudioStreamBasicDescription));AudioComponentInstance converter8To44;
AudioUnitSetProperty(converter8To44,kAudioUnitProperty_StreamFormat,kAudioUnitScope_Input,0,&asbd8K,sizeof(AudioStreamBasicDescription));
AudioUnitSetProperty(converter8To44,kAudioUnitProperty_StreamFormat,kAudioUnitScope_Output,0,& ioASBDout,sizeof(AudioStreamBasicDescription));
1

Другие решения


По вопросам рекламы [email protected]