// Linear PCM, stereo, noninterleaved stream at 44.1k AudioStreamBasicDescription targetAudioDescription; memset(&targetAudioDescription, 0, sizeof(targetAudioDescription)); targetAudioDescription.mFormatID = kAudioFormatLinearPCM; targetAudioDescription.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked | kAudioFormatFlagsNativeEndian; targetAudioDescription.mChannelsPerFrame = 2; targetAudioDescription.mBytesPerPacket = sizeof(SInt16)*targetAudioDescription.mChannelsPerFrame; targetAudioDescription.mFramesPerPacket = 1; targetAudioDescription.mBytesPerFrame = sizeof(SInt16)*targetAudioDescription.mChannelsPerFrame; targetAudioDescription.mBitsPerChannel = 8 * sizeof(SInt16); targetAudioDescription.mSampleRate = 44100.; NSURL *url = [[NSBundle mainBundle] URLForResource:@"test48k" withExtension:@"mp3"]; //NSURL *url = [[NSBundle mainBundle] URLForResource:@"test44.1k" withExtension:@"mp3"]; // -- Use this to see it working properly ExtAudioFileRef audioFile; OSStatus status; // Open file status = ExtAudioFileOpenURL((CFURLRef)url, &audioFile); checkStatus(status); if ( status != noErr ) { return; } // Determine data format AudioStreamBasicDescription fileAudioDescription; UInt32 size = sizeof(fileAudioDescription); status = ExtAudioFileGetProperty(audioFile, kExtAudioFileProperty_FileDataFormat, &size, &fileAudioDescription); if ( status != noErr ) { ExtAudioFileDispose(audioFile); return; } // Adjust client format to match number of channels targetAudioDescription.mChannelsPerFrame = fileAudioDescription.mChannelsPerFrame; targetAudioDescription.mBytesPerPacket = sizeof(SInt16)*fileAudioDescription.mChannelsPerFrame; targetAudioDescription.mBytesPerFrame = sizeof(SInt16)*fileAudioDescription.mChannelsPerFrame; // Set client format status = ExtAudioFileSetProperty(audioFile, kExtAudioFileProperty_ClientDataFormat, sizeof(targetAudioDescription), &targetAudioDescription); if ( status != noErr ) { ExtAudioFileDispose(audioFile); return; } // Get length of file (in the original format's sample rate) UInt64 fileLengthInFrames; size = sizeof(fileLengthInFrames); status = ExtAudioFileGetProperty(audioFile, kExtAudioFileProperty_FileLengthFrames, &size, &fileLengthInFrames); if ( status != noErr ) { ExtAudioFileDispose(audioFile); return; } // Calculate the final length in frames, given the original and target sample rates fileLengthInFrames = ceil(fileLengthInFrames * (targetAudioDescription.mSampleRate / fileAudioDescription.mSampleRate)); // Allocate space to load into memory SInt16* audioData = (SInt16*)malloc(fileLengthInFrames * targetAudioDescription.mBytesPerFrame); if ( !audioData ) { ExtAudioFileDispose(audioFile); return; } // Perform read in multiple small chunks (otherwise ExtAudioFileRead crashes when performing sample rate conversion) UInt64 remainingFrames = fileLengthInFrames; SInt16* audioDataPtr = audioData; fileLengthInFrames = 0; while ( 1 ) { // Set up buffers AudioBufferList bufferList; bufferList.mNumberBuffers = 1; bufferList.mBuffers[0].mData = audioDataPtr; bufferList.mBuffers[0].mDataByteSize = MIN(16384, remainingFrames * targetAudioDescription.mBytesPerFrame); // Perform read UInt32 numberOfPackets = (UInt32)(bufferList.mBuffers[0].mDataByteSize / targetAudioDescription.mBytesPerFrame); status = ExtAudioFileRead(audioFile, &numberOfPackets, &bufferList); if ( numberOfPackets == 0 ) { // Termination condition break; } if ( status != noErr ) { ExtAudioFileDispose(audioFile); free(audioData); return; } audioDataPtr += (numberOfPackets * targetAudioDescription.mChannelsPerFrame); remainingFrames -= numberOfPackets; fileLengthInFrames += numberOfPackets; } // Cleanup ExtAudioFileDispose(audioFile); // ...In real life, now do something with audioData (which is *numberOfPackets* packets long)