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 で表されます。また、同じ変換を使用するため、バイナリ出力も間違っています。変換方法を確認しませんでした(ここには投稿しませんでした)。迷惑をかけてごめんなさい。