Ios 使用音频队列播放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

我曾提到使用音频队列播放PCM文件。 代码如下:

#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];
...