加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – iOS:如何在运行时使用音频单元重新采样音频(PCM数据)?

发布时间:2020-12-16 07:13:38 所属栏目:百科 来源:网络整理
导读:如何在运行时/现场使用音频单元重新采样音频(PCM数据)? 我有一个音频单元设置如下. - (void) setUpAudioUnit { OSStatus status; AudioComponentInstance audioUnit; AudioComponent inputComponent; AudioComponentDescription audioComponentDescription;
如何在运行时/现场使用音频单元重新采样音频(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,kAudioUnitScope_Output,kOutputBus,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,&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,sizeof(audioStreamBasicDescription));
    checkStatus(status);


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

    // Set output callback
    callbackStruct.inputProc = playbackCallback;
    callbackStruct.inputProcRefCon = (__bridge void *)(self);
    status = AudioUnitSetProperty(audioUnit,kAudioUnitProperty_SetRenderCallback,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,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,反之亦然?
我已经google了很多,但没有找到任何代码示例或直接指令.

找到这些线程,但这些都没有提供明确的指示.

> Which built in AudioUnit can resample audio?
> Changing sample rate of an AUGraph on iOS

任何代码示例或信息都非常受欢迎.

解决方法

转换器音频单元将处理您的采样率转换.我发现解决这个问题的最佳方法是让您的链条适应硬件本身的功能.这意味着您应该获得系统AudioStreamBasicDescription(sysASBD),然后将转换器单元放在系统和链的需要不同的部分之间.因此,对于使用8K sampleRate进行音频播放,您可以这样做:ReomoteIO(mic) – >转换器 – > your8Kprocessing – >转换器 – > 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,1,&ioASBDin,&sizeASBD);
AudioUnitGetProperty(remoteIO,&ioASBDout,&sizeASBD);

使用转换器所需要做的就是设置输入ASBD并输出ASBD到所需的格式,它完成所有工作.让你的联系和你的8K游戏.

AudioStreamBasicDescription asbd8K;

AudioComponentInstance converter44To8;
AudioUnitSetProperty(converter44To8,& ioASBDin,sizeof(AudioStreamBasicDescription));
AudioUnitSetProperty(converter44To8,&asbd8K,sizeof(AudioStreamBasicDescription));


AudioComponentInstance converter8To44;
AudioUnitSetProperty(converter8To44,sizeof(AudioStreamBasicDescription));
AudioUnitSetProperty(converter8To44,& ioASBDout,sizeof(AudioStreamBasicDescription));

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读