音频队列-音频播放
// // audioQueuePlayer.m // live // // Created by lujunjie on 2016/11/4. // Copyright © 2016年 lujunjie. All rights reserved. // #import "AudioQueuePlayer.h" #import <AudioToolbox/AudioToolbox.h> #define QUEUE_BUFFER_SIZE 10 //队列缓冲个数 #define MIN_SIZE_PER_FRAME 2000 //每帧最小数据长度 @interface AudioQueuePlayer() { NSLock *synlock ;//同步控制 AudioQueueRef audioQueue;//音频播放队列 BOOL audioQueueUsed[QUEUE_BUFFER_SIZE]; //音频缓存是否在使用中 AudioStreamBasicDescription audioDescription;//音频参数 AudioQueueBufferRef audioQueueBuffers[QUEUE_BUFFER_SIZE];//音频缓冲 } @end @implementation AudioQueuePlayer - (instancetype)init { if (self=[super init]) { [self reset]; } return self; } - (void)reset { [self stop]; synlock = [[NSLock alloc] init]; ///设置音频参数 audioDescription.mSampleRate = 8000; //采样率 audioDescription.mFormatID = kAudioFormatLinearPCM; audioDescription.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; audioDescription.mChannelsPerFrame = 1; ///单声道 audioDescription.mFramesPerPacket = 1; //每一个packet一侦数据 audioDescription.mBitsPerChannel = 16; //每个采样点16bit量化 audioDescription.mBytesPerFrame = (audioDescription.mBitsPerChannel / 8) * audioDescription.mChannelsPerFrame; audioDescription.mBytesPerPacket = audioDescription.mBytesPerFrame; AudioQueueNewOutput(&audioDescription, audioPlayerAQInputCallback, (__bridge void*)self, nil, nil, 0, &audioQueue); //使用player的内部线程播放 //初始化音频缓冲区 for (int i = 0; i < QUEUE_BUFFER_SIZE; i++) { AudioQueueAllocateBuffer(audioQueue, MIN_SIZE_PER_FRAME, &audioQueueBuffers[i]); } } - (void)stop { if (audioQueue) { AudioQueueStop(audioQueue, true); AudioQueueReset(audioQueue); audioQueue = nil; } } - (void)play:(void*)pcmData length:(unsigned int)length { if (audioQueue == nil || ![self checkBufferHasUsed]) { // 第一次使用 [self reset]; AudioQueueStart(audioQueue, NULL); } [synlock lock]; AudioQueueBufferRef audioQueueBuffer = NULL; while (true) { audioQueueBuffer = [self getNotUsedBuffer]; if (audioQueueBuffer != NULL) { break; } } audioQueueBuffer->mAudioDataByteSize = length; Byte* audiodata = (Byte*)audioQueueBuffer->mAudioData; for (int i = 0; i < length; i++) { audiodata[i] = ((Byte*)pcmData)[i]; } AudioQueueEnqueueBuffer(audioQueue, audioQueueBuffer, 0, NULL); [synlock unlock]; } static void audioPlayerAQInputCallback(void *input, AudioQueueRef audioQueue, AudioQueueBufferRef audioQueueBuffers) { AudioQueuePlayer *player = (__bridge AudioQueuePlayer*)input; [player playerCallback:audioQueueBuffers]; } // 是不是有缓冲在使用中 - (BOOL)checkBufferHasUsed { for (int i = 0; i < QUEUE_BUFFER_SIZE; i++) { if (YES == audioQueueUsed[i]) { return YES; } } return NO; } // 获取没有在使用的缓冲 - (AudioQueueBufferRef)getNotUsedBuffer { for (int i = 0; i < QUEUE_BUFFER_SIZE; i++) { if (NO == audioQueueUsed[i]) { audioQueueUsed[i] = YES; return audioQueueBuffers[i]; } } return NULL; } // 标志缓冲空闲中 - (void)playerCallback:(AudioQueueBufferRef)outQB { for (int i = 0; i < QUEUE_BUFFER_SIZE; i++) { if (outQB == audioQueueBuffers[i]) { audioQueueUsed[i] = NO; } } } @end