ios AudioUnit 播放 pcm 数据

ios AudioUnit 播放 pcm 数据

由于公司要做音频播放,配合ffmpeg,把音乐解码承pcm裸数据,然后通过ios AudioUnit播放。

1,如下所示结构图

ios AudioUnit 播放 pcm 数据_第1张图片

需求不需要录制这块,但是网上普遍都是录制跟播放再一起的,根据相关文档总结一下代码

2, AudioUnit 初始化 AudioSession

- (void)initAudioSession {
    NSError *error;
    AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    
    [audioSession setCategory:AVAudioSessionCategoryPlayback error:&error];
    [audioSession setPreferredSampleRate:44100 error:&error];
    [audioSession setPreferredInputNumberOfChannels:1 error:&error];
    [audioSession setPreferredIOBufferDuration:0.022 error:&error];
}

3,  AudioUnit 初始化buf

- (void)initBuffer {
    UInt32 flag = 0;
    AudioUnitSetProperty(audioUnit,
                         kAudioUnitProperty_ShouldAllocateBuffer,
                         kAudioUnitScope_Output,
                         INPUT_BUS,
                         &flag,
                         sizeof(flag));
}

4,AudioUnit 初始化组件

- (void)initAudioComponent {
    AudioComponentDescription audioDesc;
    audioDesc.componentType = kAudioUnitType_Output;
    audioDesc.componentSubType = kAudioUnitSubType_RemoteIO;
    audioDesc.componentManufacturer = kAudioUnitManufacturer_Apple;
    audioDesc.componentFlags = 0;
    audioDesc.componentFlagsMask = 0;
    
    AudioComponent inputComponent = AudioComponentFindNext(NULL, &audioDesc);
    AudioComponentInstanceNew(inputComponent, &audioUnit);
    UInt32 flag = 1;
    AudioUnitSetProperty(audioUnit,
                             kAudioOutputUnitProperty_EnableIO,
                             kAudioUnitScope_Output,
                             OUTPUT_BUS,
                             &flag,
                             sizeof(flag));


}

5, AudioUnit 格式信息

- (void)initFormat {
    int channel = 1;
    AudioStreamBasicDescription audioFormat;
    audioFormat.mSampleRate = 44100;
    audioFormat.mFormatID = kAudioFormatLinearPCM;
    audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
    audioFormat.mFramesPerPacket = 1;
    audioFormat.mChannelsPerFrame = 1 << channel;
    audioFormat.mBitsPerChannel = 16;
    audioFormat.mBytesPerPacket = 2 <<  channel;
    audioFormat.mBytesPerFrame = 2 << channel;
    AudioUnitSetProperty(audioUnit,
                         kAudioUnitProperty_StreamFormat,
                         kAudioUnitScope_Input,
                         OUTPUT_BUS,
                         &audioFormat,
                         sizeof(audioFormat));
}

6,AudioUnit 注册回到函数

- (void)initFormat {
    int channel = 1;
    AudioStreamBasicDescription audioFormat;
    audioFormat.mSampleRate = 44100;
    audioFormat.mFormatID = kAudioFormatLinearPCM;
    audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
    audioFormat.mFramesPerPacket = 1;
    audioFormat.mChannelsPerFrame = 1 << channel;
    audioFormat.mBitsPerChannel = 16;
    audioFormat.mBytesPerPacket = 2 <<  channel;
    audioFormat.mBytesPerFrame = 2 << channel;
    AudioUnitSetProperty(audioUnit,
                         kAudioUnitProperty_StreamFormat,
                         kAudioUnitScope_Input,
                         OUTPUT_BUS,
                         &audioFormat,
                         sizeof(audioFormat));
}

7, 定义回调函数

static OSStatus PlayCallback(void *inRefCon,
                            AudioUnitRenderActionFlags *ioActionFlags,
                            const AudioTimeStamp *inTimeStamp,
                            UInt32 inBusNumber,
                            UInt32 inNumberFrames,
                            AudioBufferList *ioData) {
    memset(ioData->mBuffers[0].mData, 0, ioData->mBuffers[0].mDataByteSize);
    //add 增加回调把数据更改 by chenglong 
    AudioUnitRender(audioUnit, ioActionFlags, inTimeStamp, 1, inNumberFrames, ioData);
    
    return noErr;
}

8,开启播放

- (void)startPlayer {
    AudioOutputUnitStart(audioUnit);
    NSLog(@"Start");
}

9,结束播放

- (void)stopPlayer {
    AudioOutputUnitStop(audioUnit);
    NSLog(@"Stop");
}


你可能感兴趣的:(ios)