0

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?

user2955351
  • 273
  • 4
  • 18

2 Answers2

0

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.

Volker
  • 4,640
  • 1
  • 23
  • 31
  • what if I am not reading data from any file? I am just playing incoming audio data, so in that case what changes should be made? – user2955351 Apr 15 '14 at 07:15
  • as outlined above, change to littleEndian; make sure the data is available when playing and maybe zero out your buffers before playing – Volker Apr 15 '14 at 07:16
  • The actual scenario is that I am receiving speex data. For decoding this speex data I had configured and compiled FFMPEG for decoding speex. But that isn't working. Please refer to this [link](http://stackoverflow.com/questions/22935787/compiling-ffmpeg-to-support-speex-decoding). So I tried using [this](https://github.com/iosdevzone/IDZPrecompiledSpeex) framework which gives linear PCM data. For the first packet I get zero bytes as the decoded data and then some usefull bytes.I am playing this data using AudioQueues but unable to hear anything – user2955351 Apr 15 '14 at 07:22
  • so the error is possibly not the audio setup but anywhere in between... i don't know this framework, so I have no idea what might be the problem when using it. – Volker Apr 15 '14 at 07:30
  • Can you please elaborate? – user2955351 Apr 15 '14 at 07:31
  • okay. But I am unable to play this file too. This is not using any framework – user2955351 Apr 15 '14 at 07:35
  • Can you checkout this [link](https://github.com/vecter/Audio-Queue-Services-Example) I am using the same project to play .wav file. But still getting crackling noise. – user2955351 Apr 15 '14 at 07:37
0

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];
...
Roger
  • 1