转载自:http://blog.sina.com.cn/s/blog_59aee7ed010142ih.html
//
//
//
//
//
//使用AudioQueue来实现音频播放功能时最主要的步骤:
//
//1. 打开播放音频文件
//2. 取得或设置播放音频文件的数据格式
//3. 建立播放用的队列
//4. 将缓冲中的数据填充到队列中
//5. 开始播放
//6. 在回调函数中进行队列处理
//
//
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
#import <AudioToolbox/AudioFile.h>
#define NUM_BUFFERS 3
@interface AMRPlayer : NSObject {
int * _destate;
int _hasReadSize;
FILE* _amrFile;
}
//定义队列为实例属性
@property AudioQueueRef queue;
//播放方法定义
- (void) startPlay:(const char*) path;//CFURLRef
//定义缓存数据读取方法
- (void) audioQueueOutputWithQueu
//定义回调(Callback)函数
static void BufferCallback(void *inUserData, AudioQueueRef inAQ,
//定义包数据的读取方法
- (UInt32)readPacketsIntoBuffer:(AudioQueueBufferRef)buffer;
@end
//
//
//
//
//
//
#import "AMRPlayer.h"
#include "interf_dec.h"
const unsigned int PACKETNUM =
const float KSECONDSPERBUFFER = 0.2; //每秒播放0.2个缓冲
const unsigned int AMRFRAMELEN = 32; //帧长
const unsigned int PERREADFRAME =
static unsigned int gBufferSizeBytes = 0x10000;
@implementation AMRPlayer
@synthesize queue;
// 回调(Callback)函数的实现
static void BufferCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef buffer) {
}
//初始化方法(为NSObject中定义的初始化方法)
- (id) init {
//
//
_destate = Decoder_Interface_init();
}
//- (id) initWithFileName:(char*)fileName {
//
//
// _destate = Decoder_Interface_init();
// [self initFile:fileName];
//
//}
-(void)initFile:(char*) amrFileName
{
#ifdef IF2
//short block_size[16]={ 12, 13, 15, 17, 18, 20, 25, 30, 5, 0, 0, 0, 0, 0, 0, 0 };
#else
char magic[8];
//short block_size[16]={ 12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0 };
#endif
_hasReadSize=0;
_amrFile = fopen(amrFileName, "rb");
int rCout=fread( magic, sizeof( char ), strlen( "#!AMR\n" ), _amrFile );
_hasReadSize=rCout;
if ( strncmp( magic, "#!AMR\n", strlen( "#!AMR\n" ) ) ) {
fclose( _amrFile );
}
}
//缓存数据读取方法的实现
- (void) audioQueueOutputWithQueu
//-----
short pcmBuf[1600]={0};//KSECONDSPERBUFFER * 160 * 50;
int readAMRFrame = 0;
const short block_size[16]={ 12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0 };
char analysis[32]={0};
int rCout=0;
// while (fread(analysis, sizeof (unsigned char), 1, file_analysis ) > 0)
while (readAMRFrame < PERREADFRAME && (rCout=fread(analysis, sizeof (unsigned char), 1,_amrFile)))
{
int dec_mode = (analysis[0] >> 3) & 0x000F;
int read_size = block_size[dec_mode];
_hasReadSize += rCout;
rCout=fread(&analysis[1], sizeof (char), read_size, _amrFile);
_hasReadSize += rCout;
Decoder_Interface_Decode(_destate,(unsigned char *)analysis,&pcmBuf[readAMRFrame*160],0);
readAMRFrame ++;
}
NSLog(@"readCount:%d",_hasReadSize);
if (readAMRFrame > 0) {
audioQueueBuffer ->mAudioDataByteSize = readAMRFrame * 2 * 160;
audioQueueBuffer ->mPacketDescriptionCount = readAMRFrame*160;
memcpy(audioQueueBuffer ->mAudioData, pcmBuf, readAMRFrame * 160 *2);
AudioQueueEnqueueBuffer(audioQueue, audioQueueBuffer, 0, NULL);
}
//---
}
//音频播放方法的实现
-(void) startPlay:(const char*) path
{//CFURLRef
[self initFile:path];
//
//
//
//
//--设置音频数据格式
memset(&dataFormat, 0, sizeof(dataFormat));
dataFormat.mFormatID = kAudioFormatLinearPCM;
dataFormat.mSampleRate = 8000.0;
dataFormat.mFormatFlags = kLinearPCMFormatFlagIsSi
dataFormat.mBitsPerChannel = 16;
dataFormat.mChannelsPerFrame = 1;
dataFormat.mFramesPerPacket = 1;
dataFormat.mBytesPerFrame = (dataFormat.mBitsPerChannel/8) * dataFormat.mChannelsPerFrame;
dataFormat.mBytesPerPacket = dataFormat.mBytesPerFrame ;
//---
//==独立线程的模式
//AudioQueueNewOutput(&dataFormat, BufferCallback, self, CFRunLoopGetCurrent(), kCFRunLoopCommonModes, 0, &queue);
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
gBufferSizeBytes = KSECONDSPERBUFFER *
//
//
//
//AudioQueueAddPropertyLis
//static void isRunningProc(void * inUserData,AudioQueueRef queue,AudioQueuePropertyID
[self StartQueue];
}
- (UInt32)readPacketsIntoBuffer:(AudioQueueBufferRef)buffer {
//
//
//
//
//
//
//
//
//
//
short pcmBuf[1600]={0};; //KSECONDSPERBUFFER * 160 * 50
int readAMRFrame = 0;
const short block_size[16]={ 12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0 };
char analysis[32]={0};
int rCout=0;
while (readAMRFrame < PERREADFRAME && (rCout=fread(analysis, sizeof (unsigned char), 1,_amrFile)))
{
_hasReadSize += rCout;
int dec_mode = (analysis[0] >> 3) & 0x000F;
int read_size = block_size[dec_mode];
rCout=fread(&analysis[1], sizeof (char), read_size, _amrFile);
_hasReadSize += rCout;
Decoder_Interface_Decode(_destate,(unsigned char *)analysis,&pcmBuf[readAMRFrame*160],0);
readAMRFrame ++;
}
NSLog(@"readCount:%d",_hasReadSize);
if (readAMRFrame > 0) {
buffer ->mAudioDataByteSize = readAMRFrame * 2 * 160;
buffer ->mPacketDescriptionCount = readAMRFrame*160;
memcpy(buffer ->mAudioData, pcmBuf, readAMRFrame * 160 *2);
AudioQueueEnqueueBuffer(queue, buffer, 0, NULL);
}
}
- (void)dealloc {
AudioQueueDispose(queue, TRUE);
Decoder_Interface_exit(_destate);
if (_amrFile) {
fclose( _amrFile );
}
}
-(OSStatus)StartQueue
{
}
-(OSStatus)StopQueue
{
printf("ERROR STOPPING QUEUE!\n");
}
-(OSStatus)PauseQueue
{
}
@end