10

iPhone アプリケーションのダウンロード サイズを小さくするために、いくつかのオーディオ ファイルを圧縮しています。具体的には、コマンド ラインで afconvert を使用して、ima4 圧縮を使用して .wav 形式を .caf 形式に変更しています。

この正確なトピックに関するこの(wooji-juice.com) 素晴らしい投稿を読みました。「ima4 パケットのデコード」ステップで問題が発生しています。私は彼らのサンプルコードを見てきましたが、私は立ち往生しています。正しい方向に導くことができる疑似コードまたはサンプルコードで助けてください。

ありがとう!

追加情報: これが私が完了したことであり、問​​題が発生している場所です... シミュレーターと電話の両方で .wav ファイルを再生できます。コマンドラインで afconvert を使用して、.wav ファイルを ima4 圧縮で .caf に圧縮できます。CrashLanding に付属の SoundEngine を使用しています (1 つのメモリ リークを修正しました)。mFormatID 'ima4' を探すように SoundEngine コードを修正しました。

「解凍されたデータのサイズの計算」で始まる上記のリンク先のブログ投稿がわかりません。なぜこれを行う必要があるのですか?また、「パケット」という用語は何を指していますか? 私はあらゆる種類のオーディオプログラミングに非常に慣れていません。

4

2 に答える 2

12

Wooji-JuiceMultimedia Wiki、およびAppleからすべてのデータを収集した後、ここに私の提案があります (実験が必要な場合があります)。

ファイル構造

  • Apple IMA4 ファイルは 34 バイトのパケットで構成されています。これは、ファイルを構築するために使用されるパケット単位です。
  • 各 34 バイト パケットには、次の 2 つの部分があります。
    • 最初の 2 バイトには、プリアンブル (初期予測子とステップ インデックス) が含まれます。
    • 残りの 32 バイトには、サウンド ニブルが含まれます (4 ビットのニブルは、16 ビットのサンプルを取得するために使用されます)。
  • 各パケットには、16 ビットの 64 サンプルを表す 32 バイトの圧縮データがあります。
  • サウンド ファイルがステレオの場合、パケットはインターリーブされます (左に 1 つ、右に 1 つ)。偶数個のパケットが存在する必要があります。

デコード

34 バイトの各パケットは、16 ビットの 64 サンプルの解凍につながります。したがって、圧縮されていないデータのサイズは、パケットあたり 128 バイトです。

デコーディング擬似コードは次のようになります。

int[] ima_index_table = ... // Index table from [Multimedia Wiki][2]
int[] step_table = ... // Step table from [Multimedia Wiki][2]
byte[] packet = ... // A packet of 34 bytes compressed
short[] output = ... // The output buffer of 128 bytes
int preamble = (packet[0] << 8) | packet[1];
int predictor = preamble && 0xFF80; // See [Multimedia Wiki][2]
int step_index = preamble && 0x007F; // See [Multimedia Wiki][2]
int i;
int j = 0;
for(i = 2; i < 34; i++) {
    byte data = packet[i];
    int lower_nibble = data && 0x0F;
    int upper_nibble = (data && 0xF0) >> 4;

    // Decode the lower nibble
    step_index += ima_index_table[lower_nibble];
    diff = ((signed)nibble + 0.5f) * step / 4;
    predictor += diff;
    step = ima_step_table[step index];

    // Clamp the predictor value to stay in range
    if (predictor > 65535)
        output[j++] = 65535;
    else if (predictor < -65536)
        output[j++] = -65536;
    else
        output[j++] = (short) predictor;

    // Decode the uppper nibble
    step_index += ima_index_table[upper_nibble];
    diff = ((signed)nibble + 0.5f) * step / 4;
    predictor += diff;
    step = ima_step_table[step index];

    // Clamp the predictor value to stay in range
    if (predictor > 65535)
        output[j++] = 65535;
    else if (predictor < -65536)
        output[j++] = -65536;
    else
        output[j++] = (short) predictor;
}
于 2010-02-03T17:09:12.643 に答える
1

「パケット」という用語は、ヘッダー付きの圧縮されたオーディオ サンプルのグループを指します。直後のデータをデコードするには、ヘッダーが必要です。ima4 ファイルを本と見なす場合、各パケットはページです。上部には、そのページをデコードするために必要な値があり、その後に圧縮されたオーディオが続きます。

そのため、アンパックされたデータのサイズを計算する (そしてそのためのスペースを確保する) 必要があります。データは圧縮されているため、データを出力する前に、圧縮されたオーディオから非圧縮のオーディオにデータを変換する必要があります。出力バッファを割り当てるには、必要な大きさを知る必要があります (注: 一度に 1 つのパケットよりも大きなチャンクで出力する必要がある場合があります)。

前の「概要」セクションによると、典型的な構造のように見えますが、64 サンプルのセットで、各 16 ビット (つまり 128 バイト) が 2 バイトのヘッダーと 32 バイトの圧縮サンプル セット (34 バイト) に変換されます。全部で)。したがって、一般的なケースでは、入力データ サイズを取得し、34 で割ってパケット数を取得し、128 バイトを乗算してパケットあたりの圧縮されていないオーディオを取得することにより、予想される出力データ サイズを生成できます。

しかし、あなたはそれをすべきではありません。代わりに、kAudioFilePropertyDataFormat をクエリして mBytesPerPacket を取得する必要があるようです -- これは上記の「34」の値であり、mFramesPerPacket -- これは上記の 64 であり、2 を掛けて (16 バイトのサンプルの場合) 128 バイトを作成します。出力の。

次に、パケットごとに、投稿で説明されているデコードを実行する必要があります。ヘッダーを処理するために、バイトの配列を取得していると仮定して、やや長い疑似 C コードで:

packet = GetPacket();
Header = (packet[0] << 8) | packet[1]; //Big-endian 16-bit value
step_index = Header & 0x007f; //Lower seven bits
predictor = Header & 0xff80; //Upper nine bits
for (i = 2; i < mBytesPerPacket; i++)
{
    nibble = packet[i] & 0x0f; //Low Nibble
    process that nibble, per the blogpost -- be careful on sign-extension!
    nibble = (packet[i] & 0xf0) >> 4; //High Nibble
    process that nibble, per the blogpost -- be careful on sign-extension!
}

上記の符号拡張は、ポストが各ニブルを符号なしと符号付きの両方で処理することを含むという事実を指します。ニブルの上位ビット (ビット 3) が 1 の場合、それは負です。さらに、ビットシフトは符号拡張を行う場合があります。これは、上記の擬似コードでは処理されません。

于 2010-02-02T17:35:57.507 に答える