7

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

基本的に、各バッファーに含まれるフレーム数を知る方法がわからないため、それらからデータを確実に抽出することはできません。私は未加工のオーディオ データを扱うのは初めてなので、AudioBuffer 構造体の mData プロパティを最適に読み取る方法についての提案をお待ちしています。また、過去に void ポインターをあまり使用したことがないので、このコンテキストでのヘルプも素晴らしいでしょう!

4

1 に答える 1

14

audioBuffer.mDataByteSize は、バッファのサイズを示します。これをご存じでしたか?念のため、構造体 AudioBuffer の宣言を見ていませんでした。ドキュメントだけでなく、ヘッダー ファイルも常に確認する必要があります。

mDataByteSize を理解するには、データの形式を知っている必要があります。出力値のカウントは、mDataByteSize/sizeof(outputType) です。ただし、フォーマットについて混乱しているようです。どこかで指定したに違いありません。まず、16ビットのsigned intとして扱います

SInt16 *frames = audioBuffer.mData

次に、それを32ビット浮動小数点数として扱います

Float32 currentFrame = frames[i] / 32768.0f

その間に、24000 個の値があると仮定します。もちろん、正確に 24000 個の 16 ビット値がない場合、これはクラッシュします。また、データを「フレーム」と呼んでいますが、実際の意味はサンプルです。「currentFrame」と呼ぶ各値は、オーディオの 1 つのサンプルです。「フレーム」は通常、.mData のようなサンプルのブロックを指します。

したがって、データ形式が 32 ビット Float であると仮定します (注意してください、それが 8 ビット int または 32 ビット Fixed であるかどうかはわかりません)。

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 ですが、明確にするために残しました。

于 2010-11-28T23:07:06.977 に答える