zoukankan      html  css  js  c++  java
  • 音频队列-音频播放

    //
    //  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
  • 相关阅读:
    返回top写法技巧
    实现页面跳转至本页面的某个地方
    电信项目总结
    Struts2 ---- result
    Oracle定时器
    Oracle序列重置
    struts2---访问WEB
    分析函数
    exists 的简单介绍
    Oracle 部门员工查询
  • 原文地址:https://www.cnblogs.com/-ljj/p/6032995.html
Copyright © 2011-2022 走看看