Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ExtAudioFileRead gives different result in iOS 5

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);
like image 369
celestarry Avatar asked Nov 13 '22 14:11

celestarry


1 Answers

Ouch. I noted that the number is different if the original sampling rate of the song is different. Back to square 1.

like image 107
Totoro Avatar answered Jan 17 '23 03:01

Totoro