I'm trying to extract the raw audio from a movie using QTKit so I can draw a waveform. I'm using the following code but all of my output frames are zero. Any ideas about what I might be doing wrong? (you can also download the project here: http://richcollins.net/AudioSample.zip)
NSError *error;
QTMovie *movie = [QTMovie movieWithFile:[[NSBundle mainBundle] pathForResource:@"Sosumi" ofType:@"aiff"] error:&error];
if(error)
{
NSLog(@"movieWithFile Error: %@", [error localizedDescription]);
exit(1);
}
OSStatus err = noErr;
MovieAudioExtractionRef extractionSessionRef = nil;
err = MovieAudioExtractionBegin([movie quickTimeMovie], 0, &extractionSessionRef);
AudioStreamBasicDescription asbd;
err = MovieAudioExtractionGetProperty(extractionSessionRef,
kQTPropertyClass_MovieAudioExtraction_Audio,
kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription,
sizeof (asbd), &asbd, nil);
if (err)
{
NSLog(@"MovieAudioExtractionGetProperty Error: %i", err);
exit(1);
}
AudioBufferList *bufferList = calloc(1, sizeof(AudioBufferList) + asbd.mChannelsPerFrame*sizeof(AudioBuffer));
bufferList->mNumberBuffers = asbd.mChannelsPerFrame;
QTTime duration = [[movie attributeForKey:QTMovieDurationAttribute] QTTimeValue];
long long estimatedFrameCount = (long long)ceil(((double)duration.timeValue*asbd.mSampleRate)/duration.timeScale);
int i;
for (i = 0; i < asbd.mChannelsPerFrame; i ++)
{
AudioBuffer audioBuffer = bufferList->mBuffers[i];
audioBuffer.mNumberChannels = 1;
audioBuffer.mDataByteSize = estimatedFrameCount*sizeof(Float32);
audioBuffer.mData = calloc(1, estimatedFrameCount*sizeof(Float32));
bufferList->mBuffers[i] = audioBuffer;
}
UInt32 numFrames;
UInt32 flags;
UInt32 actualFrameCount = 0;
while (true)
{
err = MovieAudioExtractionFillBuffer(extractionSessionRef, &numFrames, bufferList, &flags);
if (err)
{
NSLog(@"MovieAudioExtractionFillBuffer Error: %i", err);
exit(1);
}
actualFrameCount += numFrames;
if (flags & kQTMovieAudioExtractionComplete)
{
NSLog(@"break");
break;
}
}
for (i = 0; i < asbd.mChannelsPerFrame; i ++)
{
printf("channel %i\n", i);
Float32 *frames = (Float32 *)bufferList->mBuffers[i].mData;
int j;
for (j = 0; j < actualFrameCount; j ++)
{
printf("%f,", frames[j]);
}
printf("\n");
}
err = MovieAudioExtractionEnd(extractionSessionRef);
if (err)
{
NSLog(@"MovieAudioExtractionEnd Error: %i", err);
exit(1);
}
It turns out that
numFrames
has to be set before passing a reference to it toMovieAudioExtractionFillBuffer
.