.pcm ios

2018-11-22 20:27:46 lyh20133102 阅读数 990

最近做语音对讲功能,查找了不少资料,现就音频pcm文件播放这一块整理出来,以便查看。

期间参考的文章有些已经找不着出处了,只把能找到的记录一下,感谢分享!

iOS语音对讲(三)FFmpeg实时解码AAC并播放PCM

iOS播放PCM,NSData流代码(Audio Queue Services)

把整理结果整理一下,弄成个demo

pcm流播放只需要一句话就可以,demo链接

2016-01-25 17:44:15 xianzufu 阅读数 840

1、 首先需确定PCM数据格式是否正确。

方法是将数据写成文件,然后用Audacity播放原始数据。 这里需要注意的是需要设置好音频参数。

2、使用AudioQueue播放PCM数据。 这里有个很好的播放器,非常感谢作者。

2016-03-23 14:39:14 lvchaman 阅读数 2319
Xcode7后运行以前的项目后出现大量的警告如:(null): warning: /var/folders/p4/z7zy68r92hd3p5ry5g2v3k_8rlwzzr/C/org.llvm.clang.dalmo/ModuleCache/1TXZDLI9N2EMV/Foundation-3DFYNEBRQSXST.pcm: No such file or directory。
作为一个有洁癖的我反正是不能忍,出现警告的大致原因跟我上面提到的开启Bitcode,.dSYM文件不能用来符号化有关,Xcode试图去创建dSYM文件,但是你又不需要。
解决方法:

1、Build Settings ——>Build Options——>Debug Information Format


2、Debug下的DWARF with dsYM File改成DWARF


3、Release下的还是之前默认的DWARF with dsYM File不变


参考链接:https://segmentfault.com/a/1190000003794595



2014-03-28 15:20:37 u012951123 阅读数 2293
今天编译遇到个问题:如下
fatal error: file '/Applications/Xcode 2.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator7.0.sdk/System/Library/Frameworks/UIKit.framework/Headers/UIFontDescriptor.h' has been modified since the precompiled header '/Users/m/Library/Developer/Xcode/DerivedData/ModuleCache/24CDWDK5BTYJE/UIKit.pcm' was built
note: after modifying system headers, please delete the module cache at '/Users/m/Library/Developer/Xcode/DerivedData/ModuleCache/24CDWDK5BTYJE'
1 error generated.


解决办法:

进入相应目录删除那个pcm文件:

rm "/Users/m/Library/Developer/Xcode/DerivedData/ModuleCache/24CDWDK5BTYJE/UIKit.pcm"

然后

Clean Project( Cmd+Shift+K)

清除一下工程,重新编译,问题得到解决。

2014-11-15 20:31:51 jinyeweiyang 阅读数 560
  1. //  
  2. //  MainViewController.h  
  3. //  RawAudioDataPlayer  
  4. //  
  5. //  Created by SamYou on 12-8-18.  
  6. //  Copyright (c) 2012年 SamYou. All rights reserved.  
  7. //  
  8.   
  9. #import <UIKit/UIKit.h>  
  10. #import <AudioToolbox/AudioToolbox.h>  
  11.   
  12. #define QUEUE_BUFFER_SIZE 4 //队列缓冲个数  
  13. #define EVERY_READ_LENGTH 1000 //每次从文件读取的长度  
  14. #define MIN_SIZE_PER_FRAME 2000 //每侦最小数据长度  
  15.   
  16. @interface MainViewController : UIViewController  
  17. {  
  18.     AudioStreamBasicDescription audioDescription;///音频参数  
  19.     AudioQueueRef audioQueue;//音频播放队列  
  20.     AudioQueueBufferRef audioQueueBuffers[QUEUE_BUFFER_SIZE];//音频缓存  
  21.     NSLock *synlock ;///同步控制  
  22.     Byte *pcmDataBuffer;//pcm的读文件数据区  
  23.     FILE *file;//pcm源文件  
  24. }  
  25.   
  26. static void AudioPlayerAQInputCallback(void *input, AudioQueueRef inQ, AudioQueueBufferRef outQB);  
  27.   
  28. -(void)onbutton1clicked;  
  29. -(void)onbutton2clicked;  
  30. -(void)initAudio;  
  31. -(void)readPCMAndPlay:(AudioQueueRef)outQ buffer:(AudioQueueBufferRef)outQB;  
  32. -(void)checkUsedQueueBuffer:(AudioQueueBufferRef) qbuf;  
  33.   
  34. @end  



  1. //  
  2. //  MainViewController.m  
  3. //  RawAudioDataPlayer  
  4. //  
  5. //  Created by SamYou on 12-8-18.  
  6. //  Copyright (c) 2012年 SamYou. All rights reserved.  
  7. //  
  8.   
  9. #import "MainViewController.h"  
  10.   
  11. @interface MainViewController ()  
  12.   
  13. @end  
  14.   
  15. @implementation MainViewController  
  16.   
  17. #pragma mark -  
  18. #pragma mark life cycle  
  19.   
  20. - (id)init  
  21. {  
  22.     self = [super init];  
  23.     if (self) {  
  24.         NSString *filepath = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"audio.raw"];  
  25.         NSLog(@"filepath = %@",filepath);  
  26.         NSFileManager *manager = [NSFileManager defaultManager];  
  27.         NSLog(@"file exist = %d",[manager fileExistsAtPath:filepath]);  
  28.         NSLog(@"file size = %lld",[[manager attributesOfItemAtPath:filepath error:nil] fileSize]) ;  
  29.         file  = fopen([filepath UTF8String], "r");  
  30.         if(file)  
  31.         {  
  32.             fseek(file, 0, SEEK_SET);  
  33.             pcmDataBuffer = malloc(EVERY_READ_LENGTH);  
  34.         }  
  35.         else{  
  36.             NSLog(@"!!!!!!!!!!!!!!!!");  
  37.         }  
  38.         synlock = [[NSLock alloc] init];  
  39.     }  
  40.     return self;  
  41. }  
  42.   
  43. -(void)loadView  
  44. {  
  45.     [super loadView];  
  46.     self.view.backgroundColor = [UIColor grayColor];  
  47.       
  48.     UIButton *button1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];  
  49.     button1.frame = CGRectMake(10, 10, 300, 50);  
  50.     [button1 setTitle:@"button1" forState:UIControlStateNormal];  
  51.     [button1 setTitle:@"button1" forState:UIControlStateHighlighted];  
  52.     [button1 addTarget:self action:@selector(onbutton1clicked) forControlEvents:UIControlEventTouchUpInside];  
  53.     [self.view addSubview:button1];  
  54.       
  55.     UIButton *button2 = [UIButton buttonWithType:UIButtonTypeRoundedRect];  
  56.     button2.frame = CGRectMake(10, 70, 300, 50);  
  57.     [button2 setTitle:@"button2" forState:UIControlStateNormal];  
  58.     [button2 setTitle:@"button2" forState:UIControlStateHighlighted];  
  59.     [button2 addTarget:self action:@selector(onbutton2clicked) forControlEvents:UIControlEventTouchUpInside];  
  60.     [self.view addSubview:button2];  
  61.       
  62. }  
  63. - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation  
  64. {  
  65.     return (interfaceOrientation == UIInterfaceOrientationPortrait);  
  66. }  
  67.   
  68. -(void)onbutton1clicked  
  69. {  
  70.     [self initAudio];  
  71.     NSLog(@"onbutton1clicked");  
  72.     AudioQueueStart(audioQueue, NULL);  
  73.     for(int i=0;i<QUEUE_BUFFER_SIZE;i++)  
  74.     {  
  75.         [self readPCMAndPlay:audioQueue buffer:audioQueueBuffers[i]];  
  76.     }  
  77.     /* 
  78.      audioQueue使用的是驱动回调方式,即通过AudioQueueEnqueueBuffer(outQ, outQB, 0, NULL);传入一个buff去播放,播放完buffer区后通过回调通知用户, 
  79.      用户得到通知后再重新初始化buff去播放,周而复始,当然,可以使用多个buff提高效率(测试发现使用单个buff会小卡) 
  80.      */  
  81. }  
  82.   
  83. -(void)onbutton2clicked  
  84. {  
  85.     NSLog(@"onbutton2clicked");  
  86. }  
  87.   
  88. #pragma mark -  
  89. #pragma mark player call back  
  90. /* 
  91.  试了下其实可以不用静态函数,但是c写法的函数内是无法调用[self ***]这种格式的写法,所以还是用静态函数通过void *input来获取原类指针 
  92.  这个回调存在的意义是为了重用缓冲buffer区,当通过AudioQueueEnqueueBuffer(outQ, outQB, 0, NULL);函数放入queue里面的音频文件播放完以后,通过这个函数通知 
  93.  调用者,这样可以重新再使用回调传回的AudioQueueBufferRef 
  94.  */  
  95. static void AudioPlayerAQInputCallback(void *input, AudioQueueRef outQ, AudioQueueBufferRef outQB)  
  96. {  
  97.     NSLog(@"AudioPlayerAQInputCallback");  
  98.     MainViewController *mainviewcontroller = (MainViewController *)input;  
  99.     [mainviewcontroller checkUsedQueueBuffer:outQB];  
  100.     [mainviewcontroller readPCMAndPlay:outQ buffer:outQB];  
  101. }  
  102.   
  103.   
  104.   
  105. -(void)initAudio  
  106. {  
  107.     ///设置音频参数  
  108.     audioDescription.mSampleRate = 8000;//采样率  
  109.     audioDescription.mFormatID = kAudioFormatLinearPCM;  
  110.     audioDescription.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;  
  111.     audioDescription.mChannelsPerFrame = 1;///单声道  
  112.     audioDescription.mFramesPerPacket = 1;//每一个packet一侦数据  
  113.     audioDescription.mBitsPerChannel = 16;//每个采样点16bit量化      
  114.     audioDescription.mBytesPerFrame = (audioDescription.mBitsPerChannel/8) * audioDescription.mChannelsPerFrame;  
  115.     audioDescription.mBytesPerPacket = audioDescription.mBytesPerFrame ;  
  116.     ///创建一个新的从audioqueue到硬件层的通道  
  117. //  AudioQueueNewOutput(&audioDescription, AudioPlayerAQInputCallback, self, CFRunLoopGetCurrent(), kCFRunLoopCommonModes, 0, &audioQueue);///使用当前线程播  
  118.     AudioQueueNewOutput(&audioDescription, AudioPlayerAQInputCallback, self, nil, nil, 0, &audioQueue);//使用player的内部线程播  
  119.     ////添加buffer区  
  120.     for(int i=0;i<QUEUE_BUFFER_SIZE;i++)  
  121.     {  
  122.         int result =  AudioQueueAllocateBuffer(audioQueue, MIN_SIZE_PER_FRAME, &audioQueueBuffers[i]);///创建buffer区,MIN_SIZE_PER_FRAME为每一侦所需要的最小的大小,该大小应该比每次往buffer里写的最大的一次还大  
  123.         NSLog(@"AudioQueueAllocateBuffer i = %d,result = %d",i,result);  
  124.     }  
  125. }  
  126.   
  127. -(void)readPCMAndPlay:(AudioQueueRef)outQ buffer:(AudioQueueBufferRef)outQB  
  128. {  
  129.     [synlock lock];  
  130.     int readLength = fread(pcmDataBuffer, 1, EVERY_READ_LENGTH, file);//读取文件  
  131.     NSLog(@"read raw data size = %d",readLength);  
  132.     outQB->mAudioDataByteSize = readLength;  
  133.     Byte *audiodata = (Byte *)outQB->mAudioData;  
  134.     for(int i=0;i<readLength;i++)  
  135.     {  
  136.         audiodata[i] = pcmDataBuffer[i];  
  137.     }  
  138.     /* 
  139.      将创建的buffer区添加到audioqueue里播放 
  140.      AudioQueueBufferRef用来缓存待播放的数据区,AudioQueueBufferRef有两个比较重要的参数,AudioQueueBufferRef->mAudioDataByteSize用来指示数据区大小,AudioQueueBufferRef->mAudioData用来保存数据区 
  141.      */  
  142.     AudioQueueEnqueueBuffer(outQ, outQB, 0, NULL);  
  143.     [synlock unlock];  
  144. }  
  145.   
  146. -(void)checkUsedQueueBuffer:(AudioQueueBufferRef) qbuf  
  147. {  
  148.     if(qbuf == audioQueueBuffers[0])  
  149.     {  
  150.         NSLog(@"AudioPlayerAQInputCallback,bufferindex = 0");  
  151.     }  
  152.     if(qbuf == audioQueueBuffers[1])  
  153.     {  
  154.         NSLog(@"AudioPlayerAQInputCallback,bufferindex = 1");  
  155.     }  
  156.     if(qbuf == audioQueueBuffers[2])  
  157.     {  
  158.         NSLog(@"AudioPlayerAQInputCallback,bufferindex = 2");  
  159.     }  
  160.     if(qbuf == audioQueueBuffers[3])  
  161.     {  
  162.         NSLog(@"AudioPlayerAQInputCallback,bufferindex = 3");  
  163.     }  
  164. }  
  165.   
  166.   
  167.   
  168.   
  169.   
  170.   
  171. @end  


哥的源代码下载地址      http://download.csdn.net/detail/samguoyi/4509544