I am currently doing a small test project to find out if I can get samples from AVAssetReader for playback using AudioQueue on iOS.
I read this: ( Play unprocessed uncompressed sound using AudioQueue, without sound ) and this: ( How to correctly read decoded PCM samples on iOS using AVAssetReader - currently incorrect decoding ),
Both that and another really helped. Before reading, I had no sound. Now, I get a sound, but the sound plays SUPER fast. This is my first foray into audio programming, so any help is greatly appreciated.
I initialize the reader this way:
NSDictionary * outputSettings = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:kAudioFormatLinearPCM], AVFormatIDKey, [NSNumber numberWithFloat:44100.0], AVSampleRateKey, [NSNumber numberWithInt:2], AVNumberOfChannelsKey, [NSNumber numberWithInt:16], AVLinearPCMBitDepthKey, [NSNumber numberWithBool:NO], AVLinearPCMIsNonInterleaved, [NSNumber numberWithBool:NO], AVLinearPCMIsFloatKey, [NSNumber numberWithBool:NO], AVLinearPCMIsBigEndianKey, nil]; output = [[AVAssetReaderAudioMixOutput alloc] initWithAudioTracks:uasset.tracks audioSettings:outputSettings]; [reader addOutput:output]; ...
And I take the data like this:
CMSampleBufferRef ref= [output copyNextSampleBuffer]; // NSLog(@"%@",ref); if(ref==NULL) return; //copy data to file //read next one AudioBufferList audioBufferList; NSMutableData *data = [NSMutableData data]; CMBlockBufferRef blockBuffer; CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(ref, NULL, &audioBufferList, sizeof(audioBufferList), NULL, NULL, 0, &blockBuffer); // NSLog(@"%@",blockBuffer); if(blockBuffer==NULL) { [data release]; return; } if(&audioBufferList==NULL) { [data release]; return; } //stash data in same object for( int y=0; y<audioBufferList.mNumberBuffers; y++ ) { // NSData* throwData; AudioBuffer audioBuffer = audioBufferList.mBuffers[y]; [self.delegate streamer:self didGetAudioBuffer:audioBuffer]; /* Float32 *frame = (Float32*)audioBuffer.mData; throwData = [NSData dataWithBytes:audioBuffer.mData length:audioBuffer.mDataByteSize]; [self.delegate streamer:self didGetAudioBuffer:throwData]; [data appendBytes:audioBuffer.mData length:audioBuffer.mDataByteSize]; */ }
which ultimately leads us to the audio queue configured in this way:
//Apple own code for canonical PCM audioDesc.mSampleRate = 44100.0; audioDesc.mFormatID = kAudioFormatLinearPCM; audioDesc.mFormatFlags = kAudioFormatFlagsAudioUnitCanonical; audioDesc.mBytesPerPacket = 2 * sizeof (AudioUnitSampleType); // 8 audioDesc.mFramesPerPacket = 1; audioDesc.mBytesPerFrame = 1 * sizeof (AudioUnitSampleType); // 8 audioDesc.mChannelsPerFrame = 2; audioDesc.mBitsPerChannel = 8 * sizeof (AudioUnitSampleType); // 32 err = AudioQueueNewOutput(&audioDesc, handler_OSStreamingAudio_queueOutput, self, NULL, NULL, 0, &audioQueue); if(err){ #pragma warning handle error //never errs, am using breakpoint to check return; }
and we queue
while (inNumberBytes) { size_t bufSpaceRemaining = kAQDefaultBufSize - bytesFilled; if (bufSpaceRemaining < inNumberBytes) { AudioQueueBufferRef fillBuf = audioQueueBuffer[fillBufferIndex]; fillBuf->mAudioDataByteSize = bytesFilled; err = AudioQueueEnqueueBuffer(audioQueue, fillBuf, 0, NULL); } bufSpaceRemaining = kAQDefaultBufSize - bytesFilled; size_t copySize; if (bufSpaceRemaining < inNumberBytes) { copySize = bufSpaceRemaining; } else { copySize = inNumberBytes; } if (bytesFilled > packetBufferSize) { return; } AudioQueueBufferRef fillBuf = audioQueueBuffer[fillBufferIndex]; memcpy((char*)fillBuf->mAudioData + bytesFilled, (const char*)(inInputData + offset), copySize); bytesFilled += copySize; packetsFilled = 0; inNumberBytes -= copySize; offset += copySize; } }
I tried to use the code as fully as possible so that everyone could indicate where I was an idiot. At the same time, it seems to me that my problem arises either in the announcement of the output parameters of the track reader, or in the actual declaration of AudioQueue (where I describe the queue, what sound I'm going to send). The fact is, I really do not know mathematically how to actually generate these numbers (bytes per packet, frames per packet, what you have). An explanation for this would be very helpful, and thanks for the help in advance.