美文网首页
AudioUnit(二) 录制音频

AudioUnit(二) 录制音频

作者: _RG | 来源:发表于2020-05-27 15:14 被阅读0次
  1. 开启AudioSession
  2. 创建AudioUnitIO,连接麦克风
  3. 设置采集格式
  4. 设置采集回调
image.png

开启AudioSession
如果是录制,只需要开启AVAudioSessionCategoryRecord

 [[RGAudioSession shareInstance] setAudioSessionCategory:AVAudioSessionCategoryRecord];
    [[RGAudioSession shareInstance] setPreferredIOBufferDuration:0.05];
    //激活
    [[RGAudioSession shareInstance] setActive:YES];

创建AudioUnitIO,连接麦克风
kInputElement输入总线的值为1
inData 的值flag在连接麦克风时需要设置为1 (NSInteger flag = 1)
注意是将kAudioUnitScope_InputkInputElement连接 (输入总线与输入部分相连接)

    AudioComponentDescription acd;
    acd.componentType = kAudioUnitType_Output;
    acd.componentSubType = kAudioUnitSubType_RemoteIO; //kAudioUnitSubType_VoiceProcessingIO
    acd.componentManufacturer = kAudioUnitManufacturer_Apple;
    acd.componentFlags = 0;
    acd.componentFlagsMask = 0;

    OSStatus status;
    AudioComponent ioUnitRef = AudioComponentFindNext(NULL, &acd);
    status = AudioComponentInstanceNew(ioUnitRef, &_ioUnit);
    CheckStatus(status, @"创建unit失败", YES);

//连接麦克风
    NSInteger flag = 1;
    AudioUnitSetProperty(_ioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, kInputElement, &flag, sizeof(flag));

设置采集格式,
mFormatFlags 如果选择了kLinearPCMFormatFlagIsPacked,则mBytesPerFrame必须等于mChannelsPerFrame * mBitsPerChannel / 8, 如果没有设置,则可以设置为任意n * mChannelsPerFrame * mBitsPerChannel / 8, 为一个完整声道的整数倍数, n > =1的整数
从图中可以看出,采集数据格式设置时,必须是kAudioUnitScope_OutputkInputElement相连接(输入总线与输入范围连接)

    AudioStreamBasicDescription asbd;
        bzero(&asbd, sizeof(asbd));
        asbd.mSampleRate = 44100;
        asbd.mFormatID = kAudioFormatLinearPCM; //编码格式
      //kAudioFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked
        asbd.mFormatFlags = kAudioFormatFlagIsSignedInteger ; 
        asbd.mBytesPerPacket = 2;
        asbd.mFramesPerPacket = 1;
        asbd.mBytesPerFrame = 2;
        asbd.mChannelsPerFrame = 1;
        asbd.mBitsPerChannel = 2 * 8;

status = AudioUnitSetProperty(_ioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, kInputElement, &asbd, sizeof(asbd));
        CheckStatus(status, @"设置采集格式失败", YES);

设置采集回调
AudioUnitPropertyID为kAudioOutputUnitProperty_SetInputCallback
使用AudioUnitRender函数,将recorder->_ioUnit采集到的数据写入recorder->_buffList

注意,首先先要给recorder->_buffList分配内存

_buffList = malloc(sizeof(AudioBufferList));
_buffList->mNumberBuffers = 1;
_buffList->mBuffers[0].mNumberChannels = 1;
_buffList->mBuffers[0].mDataByteSize = CONST_BUFFER_SIZE;
_buffList->mBuffers[0].mData = malloc(CONST_BUFFER_SIZE);

 //设置采集回调
    AURenderCallbackStruct callBack;
    callBack.inputProc = RecorderCallBack;
    callBack.inputProcRefCon = (__bridge void *)self;
    status = AudioUnitSetProperty(_ioUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Output, kInputElement, &callBack, sizeof(callBack));
    CheckStatus(status, @"设置采集回调失败", YES);

//采集回调
OSStatus RecorderCallBack(    void *         inRefCon,
  AudioUnitRenderActionFlags *    ioActionFlags,
  const AudioTimeStamp *            inTimeStamp,
  UInt32                            inBusNumber,
  UInt32                            inNumberFrames,
AudioBufferList * __nullable    ioData) {
    
    RGAudioBaseRecorder *recorder = (__bridge RGAudioBaseRecorder *)inRefCon;
    AudioUnitRender(recorder->_ioUnit, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, recorder->_buffList);
    NSLog(@"size = %d",recorder->_buffList->mBuffers[0].mDataByteSize);
    [recorder writePCMData:recorder->_buffList->mBuffers[0].mData size:recorder->_buffList->mBuffers[0].mDataByteSize];
    return noErr;
}

写入文件,下次可以直接读取播放

- (void)writePCMData:(Byte *)buffer size:(int)size {
    static FILE *file = NULL;
    NSString *path = [NSTemporaryDirectory() stringByAppendingString:@"/record.pcm"];
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSLog(@"path =  %@",path);
    });
    
    if (!file) {
        file = fopen(path.UTF8String, "w");
    }
    fwrite(buffer, size, 1, file);
}

相关文章

  • AudioUnit(二) 录制音频

    开启AudioSession 创建AudioUnitIO,连接麦克风 设置采集格式 设置采集回调 开启AudioS...

  • iOS AudioQueue实时录音

    在iOS中,AVCaptureSession、AudioUnit、AudioQueue均可以实现实时录制音频。其中...

  • iOS AudioUnit音频录制 -(4)

    解决的问题利用AudioUnit实现音频的录制和播放 一、指定文件路径 1、NSFileManager的使用 1、...

  • 音频采集

    音频采集 音频采集的方式 AudioUnit音频单元 AudioUnit总结 最底层 AVFoundation...

  • iOS AudioUnit实时录音与播放

    AudioUnit是iOS底层音频框架,可以用来进行混音、均衡、格式转换、实时IO录制、回放、离线渲染、语音对讲(...

  • AudioUnit录制音频+耳返(四)

    前言 视频直播,K歌应用等等都会有音频录制的功能,音频录制时还可以带有耳返效果,那这些是如何实现的呢?如果仅仅是录...

  • AudioUnit播放PCM文件(三)

    前言: AudioUnit是什么?在IOS平台下,AudioUnit是一个底层音频处理框架,主要功能如下:1、音频...

  • iOS音频-audioUnit总结

    在看LFLiveKit代码的时候,看到音频部分使用的是audioUnit做的,所以把audioUnit学习了一下。...

  • iOS AudioUnit学习

    AudioUnit是iOS底层音频框架,相比于AudioQueue和AVAudioRecorder,能够对音频数据...

  • AudioUnit 实现录音和播放

    AudioUnit是iOS底层音频框架,相比于AudioQueue和AVAudioRecorder,能够对音频数据...

网友评论

      本文标题:AudioUnit(二) 录制音频

      本文链接:https://www.haomeiwen.com/subject/cjpwahtx.html