美文网首页
AudioUnit(一) 播放音频文件

AudioUnit(一) 播放音频文件

作者: _RG | 来源:发表于2020-05-25 14:52 被阅读0次
image.png

黄色部分是APP可以控制的部分
因此,采集麦克风数据时设置格式时,总是element1output scope 相结合,
使用扬声器播放设置格式时,总是element0intput scope 相结合,

由于kAudioOutputUnitProperty_EnableIO 是设置的kAudioUnitScope_Output,表明IO是与扬声器相连接(输出),因此总线标识AudioUnitElement应该设置为0,所以后面与输出相关的AudioUnitElement都是0

代码中使用的是 OUTPUT_BUS
总线:是计算机各种功能部件之间传送信息的公共通信干线

  1. 创建kAudioUnitSubType_RemoteIO类型的AudieUnit
         AudioComponentDescription acd;
        acd.componentType = kAudioUnitType_Output;
        acd.componentSubType = kAudioUnitSubType_RemoteIO;
        acd.componentManufacturer = kAudioUnitManufacturer_Apple;
        acd.componentFlags = 0;
        acd.componentFlagsMask = 0;
  
     AudioComponent ioUnitRef = AudioComponentFindNext(NULL, &acd);
     status = AudioComponentInstanceNew(ioUnitRef, &_ioUnit);

2.连接扬声器,注意AudioUnitScope设置为kAudioUnitScope_Output类型,

UInt32   OUTPUT_BUS = 0;
 UInt32 flag = 1;
        if (flag) {
            status = AudioUnitSetProperty(_ioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, OUTPUT_BUS, &flag, sizeof(flag));
        }
  1. 设置输入格式 ,此处是播放文件,所以需要设置输入格式
          AudioStreamBasicDescription asbd;
          asbd.mSampleRate = 44100;
           asbd.mFormatID         = kAudioFormatLinearPCM; // PCM格式
           asbd.mFormatFlags      = kLinearPCMFormatFlagIsSignedInteger; // 整形
           asbd.mFramesPerPacket  = 1; // 每帧只有1个packet
           asbd.mChannelsPerFrame = 1; // 声道数
           asbd.mBytesPerFrame    = 2; // 每帧只有2个byte 声道*位深*Packet数
           asbd.mBytesPerPacket   = 2; // 每个Packet只有2个byte
           asbd.mBitsPerChannel   = 16; // 位深

UInt32   OUTPUT_BUS = 0;
  status = AudioUnitSetProperty(_ioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, OUTPUT_BUS, &asbd, sizeof(asbd));

4.设置回调

AURenderCallbackStruct callBack;
 callBack.inputProc = PlayCallBack;
callBack.inputProcRefCon = (__bridge void *)self;
status = AudioUnitSetProperty(_ioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Output, OUTPUT_BUS, &callBack, sizeof(callBack));


OSStatus PlayCallBack(    void *                            inRefCon,
                        AudioUnitRenderActionFlags *    ioActionFlags,
                        const AudioTimeStamp *            inTimeStamp,
                        UInt32                            inBusNumber,
                        UInt32                            inNumberFrames,
                      AudioBufferList * __nullable    ioData) {
    
    RGAudioBasePlay *player = (__bridge RGAudioBasePlay *)inRefCon;
      
      ioData->mBuffers[0].mDataByteSize = (UInt32)[player->_inputSteam read:ioData->mBuffers[0].mData maxLength:(NSInteger)ioData->mBuffers[0].mDataByteSize];;
      NSLog(@"out size: %d", ioData->mBuffers[0].mDataByteSize);
      
      if (ioData->mBuffers[0].mDataByteSize <= 0) {
          dispatch_async(dispatch_get_main_queue(), ^{
//              [player stop];
          });
      }
      return noErr;

}

4.播放

AudioOutputUnitStart(_ioUnit);

播放时,需要知道PCM原文件的格式是怎么样的,否走播放很容易就出错
例如一个PMC原文件格式是, 播放格式需要设置对应的格式才容易正确的播放

File format:
Sample Rate:              44100
Format ID:                 lpcm
Format Flags:                 kAudioFormatFlagIsSignedInteger
Bytes per Packet:             4
Frames per Packet:            1
Bytes per Frame:              4
Channels per Frame:           2
Bits per Channel:            16

设置输出格式的AudioStreamBasicDescription原则
mBitsPerChannel 每个声道几位表示, 一般为 16位
mSampleRate采样率一般为44100
mFormatFlags为量化的类型,一般的数据都是整型
mFramesPerPacket每个包多少帧,一般音频为1帧
mChannelsPerFrame每帧的声道数(可以为1,也可以为2)
mBytesPerFrame 每帧多少个字节,帧是最小单位,所以最小值可以设置为
n * mChannelsPerFrame * mBitsPerChannel / 8 (n为大于等于1的整数)
mBytesPerPacket 等于mBytesPerFrame

注意mBytesPerFrame设置越大,渲染回调时,所需要读取的字节数越大ioData->mBuffers[0].mDataByteSize值越大,ioData->mBuffers[0].mDataByteSize只跟mBytesPerFrame有关,单位时间里面ioData->mBuffers[0].填充的数据越多,音频播放的越快

OSStatus PlayCallBack(    void *                            inRefCon,
                        AudioUnitRenderActionFlags *    ioActionFlags,
                        const AudioTimeStamp *            inTimeStamp,
                        UInt32                            inBusNumber,
                        UInt32                            inNumberFrames,
                      AudioBufferList * __nullable    ioData) {

 ioData->mBuffers[0].mDataByteSize = (UInt32)[player->_inputSteam read:player->_buffer maxLength:(NSInteger)ioData->mBuffers[0].mDataByteSize] ;
      NSLog(@"out size: %d", ioData->mBuffers[0].mDataByteSize);

      return noErr;

}
    AudioStreamBasicDescription asbd;
        asbd.mSampleRate = 44100;
        asbd.mFormatID = kAudioFormatLinearPCM; //编码格式
        asbd.mFormatFlags = kAudioFormatFlagIsSignedInteger ; //每个样本量化的类型(这里是float)
        asbd.mBytesPerPacket = 8;
        asbd.mFramesPerPacket = 1;
        asbd.mBytesPerFrame = 8;
        asbd.mChannelsPerFrame = 1;
        asbd.mBitsPerChannel = 2 * 8;

相关文章

  • AudioUnit(一) 播放音频文件

    黄色部分是APP可以控制的部分因此,采集麦克风数据时设置格式时,总是element1与output scope 相...

  • 几种播放音频文件的方式

    几种播放音频文件的方式(一) —— 播放本地音乐几种播放音频文件的方式(二) —— 音效播放几种播放音频文件的方式...

  • iOS使用AudioUnit/AudioQueue实现耳返功能

    首先理清思路我这边使用AudioUnit录音,AudioQueue播放1、创建AudioUnit对象,并初始化设置...

  • 2020-07-23

    iOS 支持音视频倍速播放 基于使用ffmpeg+AudioUnit+OpenGL的一个视频播放器实现倍速播放功能...

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

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

  • AudioUnit合并音频文件(七)

    前言 上一篇文章初步了解了音频混合的原理及如何使用Mixer Unit混合音频的流程,学习了如何在录制音频时播放背...

  • 使用AVPlayer播放网络音乐或本地音乐

    首先了解一下音频播放的实现级别: 离线播放:这里并不是指应用不联网,而是指播放本地音频文件,包括先下完完成音频文件...

  • AudioUnit播放PCM问题

    AudioUnit播放音频数据: 是通过一个回调来取音频数据,然后拿送入的数据进行播放。放入的数据过多,会导致播放...

  • ubuntu下C代码播放音频文件

    播放音频文件分两种情况: 一、单纯播放音频文件推荐操作简单使用方便(sox软件、madplay库)。 sox软件播...

  • 音频开发 -- 音频基础

    一、音频播放流程 音乐播放器在播放音频时的流程:1.读入音频文件,使用解码器将各种格式的音频文件解压,还原为原始的...

网友评论

      本文标题:AudioUnit(一) 播放音频文件

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