I'm trying to extract Linear PCM data from a MP3 file. Before iOS 5, I could do it successfully using AudioToolbox framework, specifically ExtAudioFileRead function. However, in iOS 5 the ExtAudioFileRead function gives completely different result from that in iOS 4.
First, it cannot read all the packets in the source MP3 file. For example, it reads only 1637 packets while the source MP3 file has 2212 packets in total.
Second, the PCM values obtained from the function are completely different from those obtained in iOS 4.
I can't figure out what I did wrong :( The same framework, the same function, and the same code... but completely different results? I doubt it is a bug of iOS 5 so I reported the problem to Apple already. But Apple has not answer to my bug reporting for 2 weeks!
Here's the code that causes the problem. After executing the code, I expect to have the correct PCM data in pcmBuffer. In iOS 4, the code gives the result what I expected to. But in iOS 5, the result is completely different and wrong.
Please, somebody help me!
OSStatus status;
ExtAudioFileRef fileRef;
CFURLRef fileURL = (CFURLRef)[NSURL fileURLWithPath:filePath];
status = ExtAudioFileOpenURL((CFURLRef)fileURL, &fileRef);
AudioStreamBasicDescription dataFormat;
dataFormat.mSampleRate = SAMPLE_RATE;
dataFormat.mFormatID = kAudioFormatLinearPCM;
dataFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
dataFormat.mFramesPerPacket = 1;
dataFormat.mChannelsPerFrame = 1;
dataFormat.mBitsPerChannel = 16;
dataFormat.mBytesPerPacket = 2;
dataFormat.mBytesPerFrame = 2;
UInt32 propDataSize;
AudioStreamBasicDescription originalDataFormat;
propDataSize = (UInt32)sizeof(originalDataFormat);
status = ExtAudioFileGetProperty(fileRef, kExtAudioFileProperty_FileDataFormat, &propDataSize, &originalDataFormat);
SInt64 numPackets;
propDataSize = sizeof(numPackets);
status = ExtAudioFileGetProperty(fileRef, kExtAudioFileProperty_FileLengthFrames, &propDataSize, &numPackets);
propDataSize = (UInt32)sizeof(dataFormat);
status = ExtAudioFileSetProperty(fileRef, kExtAudioFileProperty_ClientDataFormat, propDataSize, &dataFormat);
numPackets = (SInt64)numPackets / (SInt64)(originalDataFormat.mSampleRate / SAMPLE_RATE);
size_t bufferSize = (size_t)(numPackets * sizeof(SInt16));
SInt16 *pcmBuffer = (SInt16 *)malloc(bufferSize);
AudioBufferList bufList;
bufList.mNumberBuffers = 1;
bufList.mBuffers[0].mNumberChannels = 1;
bufList.mBuffers[0].mDataByteSize = bufferSize;
bufList.mBuffers[0].mData = pcmBuffer;
ExtAudioFileSeek(fileRef, 0);
UInt32 totalFramesRead = 0;
do {
UInt32 framesRead = numPackets - totalFramesRead;
bufList.mBuffers[0].mData = pcmBuffer + (totalFramesRead * (sizeof(SInt16)));
ExtAudioFileRead(fileRef, &framesRead, &bufList);
totalFramesRead += framesRead;
if(framesRead == 0) {
break;
}
NSLog(@"read %lu frames\n", framesRead);
} while (totalFramesRead < numPackets);
int totalPackets = totalFramesRead;
status = ExtAudioFileDispose(fileRef);
NSLog(@"numPackets : %lld, totalPackets : %d", numPackets, totalPackets);
Ouch. I noted that the number is different if the original sampling rate of the song is different. Back to square 1.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With