Ios 使用音频队列播放PCM数据
我曾提到使用音频队列播放PCM文件。 代码如下:Ios 使用音频队列播放PCM数据,ios,pcm,audioqueueservices,Ios,Pcm,Audioqueueservices,我曾提到使用音频队列播放PCM文件。 代码如下: #import "PlayPCM.h" AudioFileID audioFile; SInt64 inStartingPacket = 0; AudioQueueRef audioQueue; @implementation PlayPCM void AudioOutputCallback( void* inUserData, AudioQ
#import "PlayPCM.h"
AudioFileID audioFile;
SInt64 inStartingPacket = 0;
AudioQueueRef audioQueue;
@implementation PlayPCM
void AudioOutputCallback(
void* inUserData,
AudioQueueRef outAQ,
AudioQueueBufferRef outBuffer)
{
AudioStreamPacketDescription* packetDescs;
UInt32 bytesRead;
UInt32 numPackets = 8000;
OSStatus status;
status = AudioFileReadPackets(audioFile,
false,
&bytesRead,
packetDescs,
inStartingPacket,
&numPackets,
outBuffer->mAudioData);
if(numPackets)
{
outBuffer->mAudioDataByteSize = bytesRead;
status = AudioQueueEnqueueBuffer(audioQueue,
outBuffer,
0,
packetDescs);
inStartingPacket += numPackets;
}
else
{
NSLog(@"number of packets = null ") ;
AudioQueueFreeBuffer(audioQueue, outBuffer);
}
}
-(id)init{
if (self = [super init]) {
}
return self;
}
- (void)setupAudioFormat
{
NSLog(@"setting format");
format.mFormatID = kAudioFormatLinearPCM;
format.mSampleRate = 44100;
format.mFramesPerPacket = 1;
format.mChannelsPerFrame = 1;
format.mBytesPerFrame = 2;
format.mBytesPerPacket = 2;
format.mBitsPerChannel = 16;
format.mFormatFlags = kLinearPCMFormatFlagIsBigEndian |
kLinearPCMFormatFlagIsSignedInteger |
kLinearPCMFormatFlagIsPacked;
}
- (void)startPlayback
{
int counter = 0;
[self setupAudioFormat];
OSStatus status;
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:@ "test1.wav"];
NSLog(@"file path = %@",filePath);
//fUrl = [NSURL URLWithPath:@"file:///Users/Inscripts/Desktop/test1.wav"];
fUrl = [NSURL fileURLWithPath:filePath];
//CFURLRef fileURL = (__bridge CFURLRef)(fUrl);
CFURLRef fileURL = CFURLCreateWithString(NULL, (CFStringRef) filePath, NULL);
status = AudioFileOpenURL(fileURL, kAudioFileReadPermission, 0,&audioFile);
NSLog(@"file opening status = %d",(int)status);
if(status == 0)
{ NSLog(@"file opened");
status = AudioQueueNewOutput(&(format),
AudioOutputCallback,
(__bridge void *)(self),
CFRunLoopGetCurrent(),
kCFRunLoopCommonModes,
0,
&audioQueue);
NSLog(@"audio queue create status = %d",(int)status);
if(status == 0)
{
AudioQueueAllocateBuffer(audioQueue, 1600000, &audioQueueBuffer);
AudioOutputCallback((__bridge void *)(self), audioQueue, audioQueueBuffer);
[self performSelector:@selector(startQueue) withObject:self afterDelay:50];
}
}
if(status != 0)
{
NSLog(@"failed");
// labelStatus.text = @"Play failed";
}
}
-(void)startQueue{
NSLog(@"start queue called");
OSStatus status = AudioQueueStart(audioQueue, NULL);
if(status == 0)
{
NSLog(@"ok");
// labelStatus.text = @"Playing";
}
}
test1.wav文件是PCM编码的,每个样本16位,采样率44100赫兹,立体声。
我可以成功地创建音频队列并读取文件,但我能听到的只是噼啪作响的噪音。
有人能告诉我是什么问题吗?声音真的是大端数据吗?我怀疑WAVE文件 查看您的格式标志,并将其更改为使用小尾端数据,因此:
!kLinearPCMFormatFlagIsBigEndian
也考虑使用<代码> AudioFielOpenURL< /COD>或相关,因为这将读取实际波形格式,并且不必依赖音频流描述。
在准备更多音频队列缓冲器之后,不再有噼啪声。
。。。
/*AudioQueueAllocateBuffer(audioQueue、1600000和audioQueueBuffer);
AudioOutputCallback((uu桥空*)(自)、audioQueue、audioQueueBuffer)*/
/*添加更多音频队列缓冲区,例如:3*/
int kNumberOfBuffers=3;
AudioQueueBufferRef audioQueueBuffer[kNumberOfBuffers];
对于(int i=0;i如果我没有从任何文件读取数据,我会怎么办?我只是在播放传入的音频数据,那么在这种情况下应该做什么更改?如上所述,更改为littleEndian;确保播放时数据可用,并且在播放前可能会清空缓冲区。实际情况是我正在接收speex数据。对于解码此peex数据我已经配置并编译了FFMPEG用于解码speex。但这不起作用。请参考此。因此我尝试使用框架来提供线性PCM数据。对于第一个数据包,我得到零字节作为解码数据,然后得到一些有用的字节。我正在使用音频队列播放此数据,但无法听到任何内容,因此可能是错误不是音频设置,而是介于两者之间的任何地方…我不知道这个框架,所以我不知道使用它时可能会出现什么问题。你能详细说明一下吗?
...
/* AudioQueueAllocateBuffer(audioQueue, 1600000, &audioQueueBuffer);
AudioOutputCallback((__bridge void *)(self), audioQueue, audioQueueBuffer);*/
/* add more audio queue buffers, ex:3 */
int kNumberOfBuffers = 3;
AudioQueueBufferRef audioQueueBuffer[kNumberOfBuffers];
for (int i = 0; i<kNumberOfBuffers; i++) {
AudioQueueAllocateBuffer(audioQueue, 1600000, &audioQueueBuffer[i]);
AudioOutputCallback((__bridge void *)(self), audioQueue, audioQueueBuffer[i]);
}
[self performSelector:@selector(startQueue) withObject:self afterDelay:50];
...