Odczyt próbek audio przez AVAssetReader

Jak odczytać próbki audio przez AVAssetReader? Znalazłem przykłady powielania lub miksowania za pomocą AVAssetReader, ale te pętle są zawsze kontrolowane przez pętlę AVAssetWriter. Czy można po prostu utworzyć AVAssetReader i odczytać go, pobierając każdą próbkę i wrzucając int32 każdej próbki audio do tablicy?

Dzięki.
Author: Eric Christensen, 2011-02-11

3 answers

Aby rozwinąć odpowiedź @amrox, możesz uzyskać AudioBufferList z CMBlockBufferRef, np.

CMItemCount numSamplesInBuffer = CMSampleBufferGetNumSamples(buffer);

AudioBufferList audioBufferList;

CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(
      buffer,
      NULL,
      &audioBufferList,
      sizeof(audioBufferList),
      NULL,
      NULL,
      kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment,
      &buffer
    );

for (int bufferCount=0; bufferCount < audioBufferList.mNumberBuffers; bufferCount++) {
  SInt16* samples = (SInt16 *)audioBufferList.mBuffers[bufferCount].mData;
  for (int i=0; i < numSamplesInBuffer; i++) {
    // amplitude for the sample is samples[i], assuming you have linear pcm to start with
  }
}

//Release the buffer when done with the samples 
//(retained by CMSampleBufferGetAudioBufferListWithRetainedblockBuffer)
CFRelease(buffer); 
 26
Author: Roger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-12 13:09:25
AVAssetReader *reader   = [[AVAssetReader alloc] initWithAsset:asset error:&error];
AVAssetTrack  *track    = [[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
NSDictionary  *settings = @{ AVFormatIDKey : [NSNumber numberWithInt:kAudioFormatLinearPCM] };

AVAssetReaderTrackOutput *readerOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:track
                                                                                    outputSettings:settings];

[reader addOutput:readerOutput]; 
[reader startReading];

CMSampleBufferRef sample = [readerOutput copyNextSampleBuffer];

while ( sample )
{
   sample = [readerOutput copyNextSampleBuffer];

    if ( ! sample )
    {
       continue;
    }

    CMBlockBufferRef buffer = CMSampleBufferGetDataBuffer(sample);

    size_t  lengthAtOffset;
    size_t  totalLength;
    char   *data;

    if ( CMBlockBufferGetDataPointer( buffer, 0, &lengthAtOffset, &totalLength, &data ) != noErr )
    {
        NSLog(@"error!");
        break;
    }

    // do something with data...

    CFRelease(sample);
}
 18
Author: amrox,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-13 22:33:04

Odpowiedzi tutaj nie są ogólne. Wywołanie CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer może się nie udać, gdy AudioBufferList musi mieć inny rozmiar. Przy braku intererleaved próbki jako przykład.

Prawidłowym sposobem jest dwukrotne wywołanie CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer. Pierwsze wywołanie zapytuje rozmiar potrzebny dla AudioBufferList, a drugie faktycznie wypełnia AudioBufferList.

size_t bufferSize = 0;
CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(
    sampleBuffer,
    &bufferSize,
    NULL,
    0,
    NULL,
    NULL,
    0,
    NULL
);

AudioBufferList *bufferList = malloc(bufferSize);
CMBlockBufferRef blockBuffer = NULL;
CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(
    sampleBuffer,
    NULL,
    bufferList,
    bufferSize,
    NULL,
    NULL,
    kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment,
    &blockBuffer
);

// handle audio here

free(bufferList);
CFRelease(blockBuffer);

W przykładzie ze świata rzeczywistego musisz wykonać obsługę błędów, a także nie powinieneś mallocować każdej klatki, zamiast tego buforować AudioBufferList.

 5
Author: McZonk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-27 22:23:51