1

私は圧縮された(mp3)サウンドを取得し、それをPCMとして保存することについていくらかの進歩を遂げています。さらに、同じプロセス内で、元のファイルを2秒の長さのチャンクに分割したいと思いました。私は成功しているように見えますが、その理由について少し混乱しています。

オーディオのブロックを読み取ってファイルを書き出すときに、ファイルが2秒の制限を超えるようなチャンクを書き込もうとしているかどうかを確認します。もしそうなら、私は2秒に達するのに十分な書き込みを行い、ファイルを閉じてから、新しいファイルを開き、残りを新しいファイルに書き込んでから、さらにデータを読み取ります。このようなもの:

framesInTimedSegment += numFrames;
if ((framesInTimedSegment  > (2.0 * sampleRate)) && (j < 5)) {
    UInt32 newNumFrames = numFrames;
    numFrames = framesInTimedSegment - (2.0 * sampleRate);
    newNumFrames -= numFrames;
// Question A
    UInt32 segmentOffset = newNumFrames * numChannels * 2;
    error = ExtAudioFileWrite(segmentFile, newNumFrames, &fillBufList);
// Question B
       // handle this error!  We might have an interruption
    if (segmentFile) ExtAudioFileDispose(segmentFile);
    XThrowIfError(ExtAudioFileCreateWithURL(urlArray[++j], kAudioFileCAFType, &dstFormat, NULL, kAudioFileFlags_EraseFile, &breakoutFile), "ExtAudioFileCreateWithURL failed! - segmentFile");
    size = sizeof(clientFormat);
    XThrowIfError(ExtAudioFileSetProperty(segmentFile, kExtAudioFileProperty_ClientDataFormat, size, &clientFormat), "couldn't set destination client format"); 
    fillBufList.mBuffers[0].mData = srcBuffer + segmentOffset;
    fillBufList.mBuffers[0].mDataByteSize = numFrames * fillBufList.mBuffers[0].mNumberChannels * 2;
    framesInTimedSegment = numFrames;
}
error = ExtAudioFileWrite(segmentFile, numFrames, &fillBufList);

これが私の質問です(私は関連する行にラベルを付けようとしました):

A:バッファにオフセットを見つけて、そこに値を誤ってハードコーディングしないようにするためのより良い方法はありますか?たとえば、フレーム番号からデータオフセットを取得するための祝福された方法はありますか?

B:ExtAudioFileWriteが圧縮から解凍への変換を行っている場合、書き込んでいるデータはまだ解凍されていないので(右?)、フレーム番号とオフセットを処理するときに心配する必要はありません。圧縮データ?代わりに、最初にファイルをPCMファイルまたはメモリに変換してから、そのPCMを分割する必要がありますか?

ありがとう!

-mahboud

ps。

clientFormatは次のように定義されています。

        clientFormat = dstFormat;

およびdstFormat:

        dstFormat.mFormatID = outputFormat;
        dstFormat.mChannelsPerFrame = srcFormat.NumberChannels();
        dstFormat.mBitsPerChannel = 16;
        dstFormat.mBytesPerPacket = dstFormat.mBytesPerFrame = 2 * dstFormat.mChannelsPerFrame;
        dstFormat.mFramesPerPacket = 1;
        dstFormat.mFormatFlags = kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagIsSignedInteger; // little-endian
4

1 に答える 1

2

もう少しコードを見ずに正しく答えるのは難しいです。ただし、clientFormatがインターリーブされたPCM形式であると仮定すると、次のようになります。

B)ExtAudioFileWriteは、圧縮から解凍への変換を実行しません。ExtAudioFileReadは、設定したクライアント形式に応じて実行します。MP3ソースファイルと「標準」の16ビット44.1KHzPCMクライアント形式を想定すると、ExtAudioFileReadの呼び出しはMP3バイトからPCMデータに変換されます。これは、AudioFileおよびAudioConverterAPIを使用して内部で実行されます。

A)これは、srcBufferがどのように定義されているかを確認せずに答えるのは少し難しいです(私はint16_tの配列を想定しています)。PCMデータを使用している場合、実行していることは問題ないように見えます。newNumFrames * clientFormat.mBytesPerFrame * clientFormat.mChannelsPerFrameを使用することもできますが、16ビットPCMデータを想定すると、mBytesPerFrame == mBytesPerPacket == 2. CBR以外のデータを使用する場合は、パケットの説明に注意する必要がありますが、そうではないようです。

于 2010-01-08T06:59:26.140 に答える