音频队列-音频播放

//
//  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

 

posted @ 2016-11-05 13:46  陆俊杰_iOS  阅读(557)  评论(0编辑  收藏  举报

版权信息:©Copyright © 2010-2050 陆俊杰的博客