需求:IOS播放PCM音频流数据

来源:互联网 发布:云杉网络如何 编辑:程序博客网 时间:2024/05/16 02:05

需求:播放PCM流数据,即从sock接收数据,解析出PCM数据后,进行播放。

网上给到资料大多是播放音频文件,而我想要的是播放网络数据,于是参考写下如下PCM播放器。


PCMPlayer.h文件

#import <Foundation/Foundation.h>#import <AudioToolbox/AudioToolbox.h>#define QUEUE_BUFFER_SIZE 4   //队列缓冲个数#define AUDIO_BUFFER_SIZE 640 //数据区大小#define MAX_BUFFER_SIZE 8000 //@interface PCMPlayer : NSObject-(BOOL)start;-(void)play:(NSData *)data;-(void)stop;@end


PCMPlayer.m文件

#import "PCMPlayer.h"const AudioStreamBasicDescription asbd = {MAX_BUFFER_SIZE, kAudioFormatLinearPCM, 12, 2, 1, 2, 1, 16, 0};static void sAudioQueueOutputCallback (                                       void *                  inUserData,                                       AudioQueueRef           inAQ,                                       AudioQueueBufferRef     inBuffer);@interface PCMPlayer(){        NSCondition *mAudioLock;    AudioQueueRef mAudioPlayer;    AudioQueueBufferRef mAudioBufferRef[QUEUE_BUFFER_SIZE];    void *mPCMData;    int mDataLen;    }@end@implementation PCMPlayer-(BOOL)start{        mPCMData = malloc(MAX_BUFFER_SIZE);    mAudioLock = [[NSCondition alloc]init];        AudioQueueNewOutput(&asbd, sAudioQueueOutputCallback, (__bridge void *)(self), nil, nil, 0, &mAudioPlayer);    for(int i=0;i<QUEUE_BUFFER_SIZE;i++)    {                AudioQueueAllocateBuffer(mAudioPlayer, AUDIO_BUFFER_SIZE, &mAudioBufferRef[i]);        memset(mAudioBufferRef[i]->mAudioData, 0, AUDIO_BUFFER_SIZE);        mAudioBufferRef[i]->mAudioDataByteSize = AUDIO_BUFFER_SIZE;        AudioQueueEnqueueBuffer(mAudioPlayer, mAudioBufferRef[i], 0, NULL);    }        AudioQueueSetParameter(mAudioPlayer, kAudioQueueParam_Volume, 1.0);    AudioQueueStart(mAudioPlayer, NULL);    return YES;}-(void)play:(NSData *)data{    [mAudioLock lock];    int len = (int)[data length];    if (len > 0 && len + mDataLen < MAX_BUFFER_SIZE) {        memcpy(mPCMData+mDataLen, [data bytes],[data length]);        mDataLen += AUDIO_BUFFER_SIZE;    }    [mAudioLock unlock];}-(void)stop{        AudioQueueStop(mAudioPlayer, YES);    for (int i = 0; i < QUEUE_BUFFER_SIZE; i++) {        AudioQueueFreeBuffer(mAudioPlayer, mAudioBufferRef[i]);    }    AudioQueueDispose(mAudioPlayer, YES);        free(mPCMData);    mPCMData = nil;    mAudioPlayer = nil;    mAudioLock = nil;    }-(void)handlerOutputAudioQueue:(AudioQueueRef)inAQ inBuffer:(AudioQueueBufferRef)inBuffer{    BOOL isFull = NO;    if( mDataLen >=  AUDIO_BUFFER_SIZE)    {        [mAudioLock lock];        memcpy(inBuffer->mAudioData, mPCMData, AUDIO_BUFFER_SIZE);        mDataLen -= AUDIO_BUFFER_SIZE;        memmove(mPCMData, mPCMData+AUDIO_BUFFER_SIZE, mDataLen);        [mAudioLock unlock];        isFull = YES;    }        if (!isFull) {        memset(inBuffer->mAudioData, 0, AUDIO_BUFFER_SIZE);    }        inBuffer->mAudioDataByteSize = AUDIO_BUFFER_SIZE;    AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL);}@endstatic void sAudioQueueOutputCallback (                                       void *                  inUserData,                                       AudioQueueRef           inAQ,                                       AudioQueueBufferRef     inBuffer) {        PCMPlayer *player = (__bridge PCMPlayer *)(inUserData);    [player handlerOutputAudioQueue:inAQ inBuffer:inBuffer];}


注意事项:

1、仅用于播放16位单声道的PCM数据。





0 0