iPhone应用开发中关于PCM播放器源码学习
iPhone应用开发中关于PCM播放器源码学习是本文要介绍的内容,由于原始PCM文件不能容纳任何关于其自身频率或者帧大小之类的信息,本例将不得不对此自行设置。我们会使用一种为经过压缩的PCM数据格式,具体参数喂16位、44KHz、单声道。这些信息通过程序顶部的三个预定义值指定:
[*]#define BYTES_PER_SAMPLE 2
16位等于两个字节
[*]#define SAMPLE_PATE44100
每秒采样率44100次等于44KHz
[*]typedef unsigned short sampleFrame;
[*]一个unsigned short 等于两个字节(每个采样)
[*]#include <stdio.h>
[*]#include <errno.h>
[*]#include <sys/stat.h>
[*]#include <AudioToolbox/AudioQueue.h>
[*]#define BYTES_PER_SAMPLE 2
[*]#define SAMPLE_PATE44100
[*]typedef unsigned short sampleFrame;
[*]#define FRAME_COUNT 735
[*]#define AUDIO_BUFFERS 3
[*]typedef struct AQCallbackStruct{
[*]AudioQueueRef queue;//播放队列
[*]UInt32 FrameCount;
[*]AudioQueueBufferRef mBuffers;
[*]AudioStreamBasicDescription mDataFormat;
[*]UInt32 sampleLen;
[*]UInt32 playPtr;
[*]sampleFrame *pcmBuffer;
[*]}AQCallbackStruct;
[*]void *loadpacm(const char *filename,unsigned long *len);
[*]int playbuffer(void *pcm,unsigned long len);
[*]void AQBufferCallback(void *in,AudioQueueRef inQ,AudioQueueBufferRef outQB);
[*]int main(int argc,char *argv[])
[*]{
[*]char *filename;
[*]unsigned long len;
[*]void *pcmBuffer;
[*]int ret;
[*]if (argc<2)
[*]{
[*]fprintf(stderr, &quot;Syntax: %s \n&quot;, argv);
[*]exit(EXIT_FAILURE);
[*]}
[*]filename = argv;
[*]pcmBuffer = loadpacm(filename, &len);
[*]if (!pcmBuffer)
[*]{
[*]fprintf(stderr, &quot;%s: %s\n&quot;, filename, strerror(errno));
[*]exit(EXIT_FAILURE);
[*]}
[*]ret = playbuffer(pcmBuffer,len);
[*]free(pcmBuffer);
[*]return ret;
[*]}
[*]void *loadpcm(const char *filename,unsigned long *len)
[*]{
[*]FILE*file;
[*]struct stat s;
[*]void *pcm;
[*]if (stat(filename,&s)) {
[*]return NULL;
[*]*len = s.st_size;
[*]}
[*]pcm = (void *) malloc(s.st_size);
[*]if (!pcm) {
[*]return NULL;
[*]file = fopen(filename,&quot;sb&quot;);
[*]}
[*]if(!file)
[*]{
[*]free(pcm);
[*]return NULL;
[*]}
[*]fread(pcm,s.st_size,1,file);
[*]fclose(file);
[*]return pcm;
[*]}
[*]int playbuffer(void *pcmBuffer,unsigned long len)
[*]{
[*]AQCallbackStruct agc;
[*]UInt32 err,bufferSize;
[*]int i;
[*]agc.mDataFormat.mSampleRate = SAMPLE_PATE;
[*]agc.mDataFormat.mFormatID = kAudioFormatLinearPCM;
[*]agc.mDataFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
[*]agc.mDataFormat.mBytesPerPacket = 4;
[*]agc.mDataFormat.mFramesPerPacket = 1;
[*]agc.mDataFormat.mBytesPerFrame = 4;
[*]agc.mDataFormat.mChannelsPerFrame = 2;
[*]agc.mDataFormat.mBitsPerChannel = 16;
[*]agc.FrameCount = FRAME_COUNT;
[*]agc.sampleLen = len/BYTES_PER_SAMPLE;
[*]agc.playPtr = 0;
[*]agc.pcmBuffer = pcmBuffer;
[*]err = AudioQueueNewOutput(&agc.mDataFormat,AQBufferCallback,&agc,NULL,
[*]kCFRunLoopCommonModes,0,&agc.queue);
[*]if(err) return err;
[*]agc.FrameCount = FRAME_COUNT;
[*]bufferSize = agc.FrameCount * agc.mDataFormat.mBytesPerFrame;
[*]for (i=0; i<AUDIO_BUFFERS; i++)
[*]{
[*]err = AudioQueueAllocateBuffer(agc.queue,bufferSize,&agc.mBuffers);
[*]if(err) return err;
[*]AQBufferCallback(&agc,agc.queue,agc.mBuffers);
[*]}
[*]err = AudioQueueStart(agc.queue,NULL);
[*]if(err) return err;
[*]while (agc.playPtr<agc.sampleLen)
[*]{
[*]select(NULL,NULL,NULL,NULL,1.0);
[*]}
[*]sleep(1);
[*]return 0;
[*]}
[*]void AQBufferCallback( void *in, AudioQueueRef inQ, AudioQueueBufferRef outQB)
[*]{
[*]AQCallbackStruct *agc;
[*]short *coreAudiobuffer;
[*]short sample;
[*]int i;
[*]agc=(AQCallbackStruct *) in;
[*]coreAudiobuffer =(short*) outQB->mAudioData;
[*]printf(&quot;Sync:%i / %i \n&quot;,agc->playPtr,agc->sampleLen);
[*]if (agc->FrameCount >0)
[*]{
[*]outQB->mAudioDataByteSize = 4*agc->FrameCount;
[*]for (i=0; i<agc->FrameCount*2; i++)
[*]{
[*]if(agc->playPtr > agc->sampleLen || agc->playPtr<0)
[*]{
[*]sample =0;
[*]}
[*]else
[*]{
[*]sample = (agc->pcmBuffer);
[*]}
[*]coreAudiobuffer = sample;
[*]coreAudiobuffer = sample;
[*]agc->playPtr++;
[*]}
[*]AudioQueueEnqueueBuffer(inQ,outQB,0,NULL);
[*]}
}如果你无法找到一个原始的PCM元数据,你可以用.wav格式文件代替,制药以16位44KHz原始PCM编码的就行。
编译命令:
[*]$ gcc -o playpcm playpcm.c \
[*]-framework AudioToolbox -framework CoreAudio -framework CoreFoundation
小结:iPhone应用开发中关于PCM播放器源码学习的内容介绍完了,希望通过本文的学习能对你有所帮助!
【编辑推荐】
[*]iPhone视频播放器 实现操作
[*]iPhone学习笔记几个实例开发操作
[*]iPhone之ASINetworkQueue异步队列
[*]iPhone动画实现两种表现方法
[*]关于iPhone多线程编程的教程
页:
[1]