How do I Extract Raw Audio from movie using QTKit

1.4k views Asked by At

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);
}
1

There are 1 answers

0
richcollins On

It turns out that numFrames has to be set before passing a reference to it to MovieAudioExtractionFillBuffer.