Определите количество кадров в базовом аудиобуфере аудио - PullRequest
7 голосов
/ 29 ноября 2010

Я пытаюсь получить доступ к необработанным данным для аудиофайла на iPhone / iPad. У меня есть следующий код, который является основным началом пути, который мне нужен. Однако я не знаю, что делать, если у меня есть AudioBuffer.

AVAssetReader *assetReader = [AVAssetReader assetReaderWithAsset:urlAsset error:nil];
AVAssetReaderTrackOutput *assetReaderOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:[[urlAsset tracks] objectAtIndex:0] outputSettings:nil];
[assetReader addOutput:assetReaderOutput];
[assetReader startReading];

CMSampleBufferRef ref;
NSArray *outputs = assetReader.outputs;
AVAssetReaderOutput *output = [outputs objectAtIndex:0];
int y = 0;
while (ref = [output copyNextSampleBuffer]) {
    AudioBufferList audioBufferList;
    CMBlockBufferRef blockBuffer;
    CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(ref, NULL, &audioBufferList, sizeof(audioBufferList), NULL, NULL, 0, &blockBuffer);
    for (y=0; y<audioBufferList.mNumberBuffers; y++) {
        AudioBuffer audioBuffer = audioBufferList.mBuffers[y];
        SInt16 *frames = audioBuffer.mData;
        for(int i = 0; i < 24000; i++) { // This sometimes crashes
            Float32 currentFrame = frames[i] / 32768.0f;
        }
    }
}

По сути, я не знаю, как определить, сколько кадров содержит каждый буфер, поэтому я не могу надежно извлечь из них данные. Я новичок в работе с необработанными аудиоданными, поэтому я открыт для любых предложений о том, как лучше всего прочитать свойство mData структуры AudioBuffer. Я также мало что делал с указателями на пустоту в прошлом, поэтому помощь с этим в этом контексте была бы очень полезна!

1 Ответ

14 голосов
/ 29 ноября 2010

audioBuffer.mDataByteSize сообщает вам размер буфера.Ты это знал?Только если вы не могли, вы не могли посмотреть на объявление struct AudioBuffer.Вы всегда должны смотреть как на заголовочные файлы, так и на документы.

Чтобы mDataByteSize имел смысл, вы должны знать формат данных.Количество выходных значений mDataByteSize / sizeof (outputType).Тем не менее, вы, кажется, смущены форматом - вы должны были указать его где-то.Прежде всего вы рассматриваете его как 16-битное целое число со знаком

SInt16 *frames = audioBuffer.mData

, затем вы рассматриваете его как 32-битное число с плавающей запятой

Float32 currentFrame = frames[i] / 32768.0f

междувы предполагаете, что существует 24000 значений, конечно, это приведет к сбою, если нет точно 24000 16-битных значений.Кроме того, вы называете данные «кадрами», но на самом деле вы имеете в виду образцы.Каждое значение, которое вы называете currentFrame, представляет собой один образец аудио.«Кадр» обычно относится к блоку сэмплов, например .mData

Итак, предполагая, что формат данных 32-битный Float (и, пожалуйста, обратите внимание, я понятия не имею, если это так, это может быть 8-битный int или32 бита Исправлено для всех, что я знаю)

for( int y=0; y<audioBufferList.mNumberBuffers; y++ )
{
  AudioBuffer audioBuffer = audioBufferList.mBuffers[y];
  int bufferSize = audioBuffer.mDataByteSize / sizeof(Float32);
  Float32 *frame = audioBuffer.mData;
  for( int i=0; i<bufferSize; i++ ) {
    Float32 currentSample = frame[i];
  }
}

Обратите внимание, sizeof (Float32) всегда равен 4, но я оставил это, чтобы было ясно.

...