如何在运行时/实时使用音频单元对音频(PCM 数据)进行重新采样?
我有一个音频单元设置如下。
- (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.1KHz 重新采样到 8KHz,反之亦然? 我在谷歌上搜索了很多,但没有找到任何代码示例或直接说明。
找到了这些线程,但没有一个提供明确的说明。
非常感谢任何代码示例或信息。
最佳答案
转换器音频单元将处理您的采样率转换。我发现处理这个问题的最好方法是让你的链适应硬件的 native 功能。这意味着您应该获取系统 AudioStreamBasicDescription (sysASBD),然后将转换器单元放在系统和链中需要不同东西的部分之间。因此,对于使用 8K 采样率播放音频,您可以这样做:ReomoteIO(mic) -> 转换器 -> your8Kprocessing -> 转换器 -> RemoteIO(out)。
这是转换器的描述。
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));
关于c++ - iOS:如何在运行时使用音频单元对音频(PCM 数据)进行重新采样?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32607418/