2

AMR ファイルから各フレームを抽出するアルゴリズムを作成しました。ファイルの最初の 6 バイトがヘッダーであり、次の情報がオーディオ フレームであると考えました。各オーディオ フレームは、フレーム ヘッダーとオーディオ データで構成されます。フレーム ヘッダーは、フレームのサイズをバイト単位で示します (CMR モード テーブルを使用 - http://www.developer.nokia.com/Community/Wiki/AMR_format )。フレーム サイズは、フレームの 1 バイト目 -> 2 ビット目から 5 ビット目に格納され、MSB を 1 ビット目として数えます。

アルゴリズムが機能せず、各バイトを 2 進数 (0 と 1) で画面に表示することにしました。フレーム サイズの数値が 7 よりも大きく、CMR テーブルに 0...7 の値しかない場合があります。

以下は CMR テーブルです。

CMR      MODE        FRAME SIZE( in bytes )
0 AMR    4.75        13
1 AMR    5.15        14
2 AMR    5.9         16
3 AMR    6.7         18
4 AMR    7.4         20
5 AMR    7.95        21
6 AMR    10.2        27
7 AMR    12.2        32

私の出力(amrファイルからの各バイト)は次のとおりです。

0 -> 0 0 0 0 0 0 0 0 
1 -> 0 0 0 0 0 0 0 0 
2 -> 0 0 0 0 0 0 0 0 
3 -> 0 0 0 1 1 0 0 0 
4 -> 0 1 1 0 0 1 1 0 
5 -> 0 0 1 0 1 1 1 0 
6 -> 1 0 0 1 1 1 1 0 
7 -> 0 0 0 0 1 1 1 0 
8 -> 1 1 0 0 1 1 0 0 
9 -> 1 1 1 0 0 1 1 0 
10 -> 0 0 0 0 1 1 1 0 
11 -> 0 0 1 0 1 1 0 0 
12 -> 0 0 0 0 0 0 0 0 
13 -> 0 0 0 0 0 0 0 0 
14 -> 0 0 0 0 0 0 0 0 
15 -> 0 0 0 0 0 0 0 0 
16 -> 1 0 0 1 0 1 1 0 
17 -> 1 1 0 0 1 1 1 0 
18 -> 1 1 1 1 0 1 1 0 
19 -> 1 0 1 1 0 1 1 0 
20 -> 1 1 0 0 1 1 0 0 
21 -> 1 1 1 0 0 1 1 0 
22 -> 0 0 0 0 1 1 1 0 
23 -> 0 0 1 0 1 1 0 0 
24 -> 0 0 0 0 0 0 0 0 
25 -> 0 0 0 0 0 0 0 0 
26 -> 0 1 0 0 0 0 0 0 
27 -> 1 0 0 1 1 0 0 0 
28 -> 1 0 1 1 0 1 1 0 
29 -> 1 1 1 1 0 1 1 0 
30 -> 1 1 1 1 0 1 1 0 
31 -> 0 1 1 0 1 1 1 0 
32 -> 0 0 0 0 0 0 0 0 
33 -> 0 0 0 0 0 0 0 0 
34 -> 0 0 0 0 0 0 0 0 
35 -> 0 0 1 1 0 1 1 0 
36 -> 1 0 1 1 0 1 1 0 
37 -> 0 1 1 0 1 1 1 0 
38 -> 0 0 0 1 0 1 1 0 
39 -> 0 0 1 0 0 1 1 0 
40 -> 0 0 0 0 0 0 0 0 

バイト番号 6 を取得しました: 10011110 -> 0011 は番号 3 で、対応する 3 の CMR 値は 18 です。18 バイトをスキップし、バイト番号に到達します。6+18 = 24: 00000000 - 0 の CMR 値は 13 で、別の 13 バイトをスキップします -> 24+13=37: 01101110 -> 1101is 13 WHICH ISN'T IN CMR table

私が間違っていることは何ですか?バイナリ形式での印刷は正しいと思います。以下は、各フレームを読み取るためのアルゴリズムです (バイナリの方法を表示するためではありません)。

private void displayNrOfFrames() throws Exception{
        FileInputStream fis = null;

        try {
            fis = new FileInputStream(mFile);
            long result = fis.skip(6);
            if(result != 6){
                throw new Exception("Could not skip first 6 bytes(header) of AMR.");
            }

            int number = 0;
            int bit = 0;
            byte b;
            BitSet bs;
            while((b = Integer.valueOf(fis.read()).byteValue()) != -1){     
                bs = Util.fromByte(b);          
                number = 0;
                //convert bits [1..4] to number
                for (int i = 1; i <= 4; i++) {
                    bit = bs.get(i)? 1:0;
                    number += bit*Math.pow(2, 4 - i);                   
                }
                System.out.println(number);
                if(!CMR_MAP.containsKey(number)){
                    throw new Exception("Could not parse AMR file.");
                }
                //skip the number of bytes of this frame.
                fis.skip(CMR_MAP.get(number));

            }       

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

[EDIT]

byte から BitSet への変換が間違っているため、アルゴリズムが失敗するようです。バイト番号 6 では、数値 121 で表されるはずですが、誤って番号 158 で表されます。また、同じ変換を使用するため、バイナリ出力も間違っています。変換方法を確認しませんでした(ここには投稿しませんでした)。迷惑をかけてごめんなさい。

4

1 に答える 1

1

この返事が遅すぎないことを願っています。

まず最初に、同じ参照から 、最初の 6 バイト (ファイル ヘッダー) が 0x23、0x21、0x41、0x4D、0x52、0x0A であることがわかります。これは定数値であり、常に存在する必要があります。存在しない場合は、ファイルが破損している可能性があり、使用しないでください。したがって、最初の 6 バイトをやみくもにスキップするべきではありません。

現在、AMR コーデックは DTX (不連続伝送) をサポートしています。DTX は、ボコーダーが無音を検出したときに少ないデータを生成することで、帯域幅を節約する方法に他なりません。amr パーサーは、DTX を予期する準備ができている必要があります。AMR-NB (amr 狭帯域または単に amr) の場合、DTX はモード 8 を使用してシグナリングされます。したがって、CMR マップには以下のエントリが含まれている必要があります。

8 AMR SID 6 (SID はサイレンス インジケータです...サイレンス期間が開始していることを示します)

SID の後に、長さが 1 バイトの実際の無音フレーム (ヘッダーだけ...データなし) があるため、次のエントリが必要です。

15 AMR NO_DATA 1

モード 9 ~ 11 は破棄する必要があります。また、モード 12 ~ 14 は将来の使用のために予約されています (通常、これらも破棄されます)。上記のすべての情報は、単一チャネル AMR が使用されていることを念頭に置いて提供されています。

貼り付けた版画に

6 -> 1 0 0 1 1 1 1 0

これは AMR Toc ヘッダーであるはずです

    0 1 2 3 4 5 6 7
   +-+-+-+-+-+-+-+-+
   |F|  FT   |Q|P|P|
   +-+-+-+-+-+-+-+-+

ストレージの場合、F ビットは 0 である必要がありますが、あなたの例では 1 です。最後の 2 ビット (パディング ビット) はゼロでなければなりませんが、あなたの例ではこれらは 0 ではありません。

于 2013-07-11T06:29:55.807 に答える