iPhone应用开发中关于PCM播放器源码学习

移动开发 iOS
本文介绍的是iPhone应用开发中关于PCM播放器源码学习,由于原始PCM文件不能容纳任何关于其自身频率或者帧大小之类的信息,本例将不得不对此自行设置,来看内容详解。

iPhone应用开发中关于PCM播放器源码学习是本文要介绍的内容,由于原始PCM文件不能容纳任何关于其自身频率或者帧大小之类的信息,本例将不得不对此自行设置。

我们会使用一种为经过压缩的PCM数据格式,具体参数喂16位、44KHz、单声道。这些信息通过程序顶部的三个预定义值指定:

  1. #define BYTES_PER_SAMPLE 2 

16位等于两个字节

  1. #define SAMPLE_PATE  44100 

每秒采样率44100次等于44KHz

  1. typedef unsigned short sampleFrame;  
  2. 一个unsigned short 等于两个字节(每个采样)  
  3. #include <stdio.h> 
  4. #include <errno.h> 
  5. #include <sys/stat.h> 
  6. #include <AudioToolbox/AudioQueue.h> 
  7. #define BYTES_PER_SAMPLE 2  
  8. #define SAMPLE_PATE  44100  
  9. typedef unsigned short sampleFrame;  
  10. #define FRAME_COUNT 735  
  11. #define AUDIO_BUFFERS 3  
  12. typedef struct AQCallbackStruct{  
  13. AudioQueueRef queue;//播放队列  
  14. UInt32 FrameCount;  
  15. AudioQueueBufferRef mBuffers[AUDIO_BUFFERS];  
  16. AudioStreamBasicDescription mDataFormat;  
  17. UInt32 sampleLen;  
  18. UInt32 playPtr;  
  19. sampleFrame *pcmBuffer;  
  20. }AQCallbackStruct;  
  21. void *loadpacm(const char *filename,unsigned long *len);  
  22. int playbuffer(void *pcm,unsigned long len);  
  23. void AQBufferCallback(void *in,AudioQueueRef inQ,AudioQueueBufferRef outQB);  
  24. int main(int argc,char *argv[])  
  25. {  
  26. char *filename;  
  27. unsigned long len;  
  28. void *pcmBuffer;  
  29. int ret;  
  30. if (argc<2)  
  31. {  
  32. fprintf(stderr, "Syntax: %s [filename]\n", argv[0]);  
  33. exit(EXIT_FAILURE);  
  34. }  
  35. filename = argv[1];  
  36. pcmBuffer = loadpacm(filename, &len);  
  37. if (!pcmBuffer)   
  38. {  
  39. fprintf(stderr, "%s: %s\n", filename, strerror(errno));  
  40. exit(EXIT_FAILURE);  
  41. }  
  42. ret = playbuffer(pcmBuffer,len);  
  43. free(pcmBuffer);  
  44. return ret;  
  45. }  
  46. void *loadpcm(const char *filename,unsigned long *len)  
  47. {  
  48. FILE  *file;  
  49. struct stat s;  
  50. void *pcm;  
  51. if (stat(filename,&s)) {  
  52. return NULL;  
  53. *len = s.st_size;  
  54. }  
  55. pcm = (void *) malloc(s.st_size);  
  56. if (!pcm) {  
  57. return NULL;  
  58. file = fopen(filename,"sb");  
  59. }  
  60. if(!file)  
  61. {  
  62. free(pcm);  
  63. return NULL;  
  64. }  
  65. fread(pcm,s.st_size,1,file);  
  66. fclose(file);  
  67. return pcm;  
  68. }  
  69. int playbuffer(void *pcmBuffer,unsigned long len)  
  70. {  
  71. AQCallbackStruct agc;  
  72. UInt32 err,bufferSize;  
  73. int i;  
  74. agc.mDataFormat.mSampleRate = SAMPLE_PATE;  
  75. agc.mDataFormat.mFormatID = kAudioFormatLinearPCM;  
  76. agc.mDataFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;  
  77. agc.mDataFormat.mBytesPerPacket = 4;  
  78. agc.mDataFormat.mFramesPerPacket = 1;  
  79. agc.mDataFormat.mBytesPerFrame = 4;  
  80. agc.mDataFormat.mChannelsPerFrame = 2;  
  81. agc.mDataFormat.mBitsPerChannel = 16;  
  82. agc.FrameCount = FRAME_COUNT;  
  83. agc.sampleLen = len/BYTES_PER_SAMPLE;  
  84. agc.playPtr = 0;  
  85. agc.pcmBuffer = pcmBuffer;  
  86. err = AudioQueueNewOutput(&agc.mDataFormat,AQBufferCallback,&agc,NULL,  
  87.   kCFRunLoopCommonModes,0,&agc.queue);  
  88. if(err) return err;  
  89. agc.FrameCount = FRAME_COUNT;  
  90. bufferSize = agc.FrameCount * agc.mDataFormat.mBytesPerFrame;  
  91. for (i=0; i<AUDIO_BUFFERS; i++)  
  92. {  
  93. err = AudioQueueAllocateBuffer(agc.queue,bufferSize,&agc.mBuffers[i]);  
  94. if(err) return err;  
  95. AQBufferCallback(&agc,agc.queue,agc.mBuffers[i]);  
  96. }  
  97. err = AudioQueueStart(agc.queue,NULL);  
  98. if(err) return err;  
  99. while (agc.playPtr<agc.sampleLen)  
  100. {  
  101. select(NULL,NULL,NULL,NULL,1.0);  
  102. }  
  103. sleep(1);  
  104. return 0;  
  105. }  
  106. void AQBufferCallback( void *in, AudioQueueRef inQ, AudioQueueBufferRef outQB)  
  107. {  
  108. AQCallbackStruct *agc;  
  109. short *coreAudiobuffer;  
  110. short sample;  
  111. int i;  
  112. agc=(AQCallbackStruct *) in;  
  113. coreAudiobuffer =(short*) outQB->mAudioData;  
  114. printf("Sync:%i / %i \n",agc->playPtr,agc->sampleLen);  
  115. if (agc->FrameCount >0)   
  116. {  
  117. outQB->mAudioDataByteSize = 4*agc->FrameCount;  
  118. for (i=0; i<agc->FrameCount*2; i++)   
  119. {  
  120. if(agc->playPtr > agc->sampleLen || agc->playPtr<0)  
  121. {  
  122. sample =0;  
  123. }  
  124. else  
  125. {  
  126. sample = (agc->pcmBuffer[agc->playPtr]);  
  127. }  
  128. coreAudiobuffer[i] = sample;  
  129. coreAudiobuffer[i+1] = sample;  
  130. agc->playPtr++;  
  131. }  
  132. AudioQueueEnqueueBuffer(inQ,outQB,0,NULL);  

}如果你无法找到一个原始的PCM元数据,你可以用.wav格式文件代替,制药以16位44KHz原始PCM编码的就行。

编译命令:

  1. $ gcc -o playpcm playpcm.c \  
  2. -framework AudioToolbox -framework CoreAudio -framework CoreFoundation 

小结:iPhone应用开发中关于PCM播放器源码学习的内容介绍完了,希望通过本文的学习能对你有所帮助!

责任编辑:zhaolei 来源: 互联网
相关推荐

2011-08-09 17:12:30

iPhoneCFRunLoop

2011-08-18 10:39:46

iPhone开发界面

2011-07-20 16:21:20

iPhone 视频 播放器

2014-12-31 16:52:53

音乐播放器源码

2011-08-15 13:44:07

iPhone开发UITableView

2011-08-08 18:19:09

iPhone音频播放

2011-08-08 14:07:49

iPhone开发 字体

2011-08-12 09:48:24

iPhoneCoreLocatio定位

2011-08-09 17:29:29

iPhone文件屏幕

2011-08-08 10:10:14

iPhone开发 图片 方法

2011-08-19 10:35:19

iPhone应用Three20

2011-06-13 09:33:04

2022-08-16 17:37:06

视频播放器鸿蒙

2015-01-22 15:44:55

Android源码音乐播放器

2015-09-01 16:48:44

ios暴风视频播放器

2011-08-05 14:48:06

iPhone应用 异步队列

2011-08-08 14:57:46

iPhone Autoreleas Property

2023-03-28 09:44:02

开发应用鸿蒙

2023-03-29 09:37:49

视频播放器应用鸿蒙

2023-03-28 09:38:34

开发应用鸿蒙
点赞
收藏

51CTO技术栈公众号