iOS音频之AudioUnit简单播放音频 -(2)

实现AudioUnit播放音频
demo地址
从配置环境到播放成功的以下步骤详解

一、设置AVAudioSession

该类具有以下作用

  • 此类用来管理多个APP对音频资源的利用,
  • 设置自己的APP是否和其他APP音频同时存在,还是中断其他APP声音
  • 在手机调到静音模式下,自己的APP音频是否可以播放出声音
  • 电话或者其他APP中断自己APP的音频的事件处理
  • 指定音频输入和输出的设备(比如是听筒输出声音,还是扬声器输出声音)
  • 是否支持录音,录音同时是否支持音频播放
    NSError *error = nil;
    AVAudioSession* session = [AVAudioSession sharedInstance];
    [session setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:&error];
    [session setActive:YES error:nil];

类具体的参考资料:iOS 音频-AVAudioSession

二、设置Audiocomponentdescription

音频单元描述

struct AudioComponentDescription {
    OSType              componentType; //一个音频组件通用的独特的四字节码标识
    OSType              componentSubType;//由上面决定,设置相应的类型
    OSType              componentManufacturer;//厂商身份验证
    UInt32              componentFlags;//没有明确的指定,设置0
    UInt32              componentFlagsMask;//没有明确的指定,设置0
}

2.1、得到AudioComponent

AudioComponentFindNext得到AudioComponent :

AudioComponent outputComponent = AudioComponentFindNext(NULL, &outputDesc);

2.2、最后调用AudioComponentInstanceNew(参数, &参数地址);得到audio的实例

三、初始化 AudioBufferList

用到的关键结构体

struct AudioBufferList
{
    UInt32      mNumberBuffers;// audiobuffer的数目
    AudioBuffer mBuffers[1]; // this is a variable length array of mNumberBuffers elements
}
//结构体 Audiobuffer
struct AudioBuffer
{
    UInt32              mNumberChannels;//声道数目
    UInt32              mDataByteSize;//是buffer的大小
    void* __nullable    mData;//音频数据的buffer
}

四、设置输出格式描述

struct AudioStreamBasicDescription
{
    Float64             mSampleRate; //音频频率,也是采样频率
    AudioFormatID       mFormatID;//音频格式
    AudioFormatFlags    mFormatFlags;//格式标签
    UInt32              mBytesPerPacket;//每个数据包的字节数
    UInt32              mFramesPerPacket;//每个数据包的帧数
    UInt32              mBytesPerFrame;//每一帧的字节数
    UInt32              mChannelsPerFrame;//每一帧声道数,单声道和双声道 1/2
    UInt32              mBitsPerChannel;//采样位数/采样精度 8/16
    UInt32              mReserved;//保留
};

AudioUnitSetProperty配置表

//1、 设置的这几个参数的含义
CF_ENUM(AudioUnitScope) {
kAudioUnitScope_Global        = 0,//设置回调函数
kAudioUnitScope_Input        = 1,
kAudioUnitScope_Output        = 2,//设置音频格式描述的时候
kAudioUnitScope_Group        = 3,
kAudioUnitScope_Part        = 4,
kAudioUnitScope_Note        = 5,
kAudioUnitScope_Layer        = 6,
kAudioUnitScope_LayerItem    = 7
};

五、设置应用音频格式描述

OSStatus status = AudioUnitSetProperty(audioUnit,
                                           kAudioUnitProperty_StreamFormat,
                                           kAudioUnitScope_Input,
                                           kOutputBus,
                                           &_outputFormat,
                                           sizeof(_outputFormat));

六、设置回调函数

//播放回调函数
static OSStatus outputCallBackFun(void *                            inRefCon,
                                  AudioUnitRenderActionFlags *    ioActionFlags,
                                  const AudioTimeStamp *            inTimeStamp,
                                  UInt32                            inBusNumber,
                                  UInt32                            inNumberFrames,
                                  AudioBufferList * __nullable    ioData)
{
    
    memset(ioData->mBuffers[0].mData, 0, ioData->mBuffers[0].mDataByteSize);
    
    ViewController *strongSelf = (__bridge ViewController *)(inRefCon);
    __weak typeof(strongSelf) weakSelf = strongSelf;

    strongSelf->_bufferList->mBuffers[0].mDataByteSize = CONST_BUFFER_SIZE;
    OSStatus status = ExtAudioFileRead(strongSelf->_audioFile, &inNumberFrames, strongSelf->_bufferList);
   //把资源内存拷贝到目标内存
    memcpy(ioData->mBuffers[0].mData, strongSelf->_bufferList->mBuffers[0].mData, strongSelf->_bufferList->mBuffers[0].mDataByteSize);
    ioData->mBuffers[0].mDataByteSize = strongSelf->_bufferList->mBuffers[0].mDataByteSize;

    if (ioData->mBuffers[0].mDataByteSize == 0){
        [weakSelf stop];
    }
    strongSelf->_readedFrame += ioData->mBuffers[0].mDataByteSize / strongSelf->_outputFormat.mBytesPerFrame;
    
    CheckError(status, "转换格式失败");
    if (inNumberFrames == 0) NSLog(@"播放结束");
    NSLog(@"%f",[strongSelf getProgress]);
    
    
    return noErr;
}

你可能感兴趣的:(iOS音频之AudioUnit简单播放音频 -(2))