Playing PCM data using Audio Queues

青春壹個敷衍的年華 提交于 2019-12-24 21:50:27

问题


I have reffered to this to play a PCM file using Audio Queues. The code is as follows:

#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 file is PCM encoded 16 bits per sample, sampling rate 44100 Hertz, stereo. I can successfully create audio queue and read the file but all I can hear is crackling noise. Can someone tell me what's the issue?


回答1:


Is the sound really big endian data - i doubt with WAVE files.

See your format flags, and change them to use little endian data, so: !kLinearPCMFormatFlagIsBigEndian

Also consider using AudioFileOpenURLor related since that will read the actual wave format and you don't have to rely on your audio stream description.




回答2:


After preparing more audio queue buffers, no more crackling noise. please refer to apple's doc

...
/*    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];
...


来源:https://stackoverflow.com/questions/23076634/playing-pcm-data-using-audio-queues

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!