我編寫了一個算法來從AMR文件中提取每個幀。我認爲文件的前6個字節是標題,以下信息是音頻幀。每個音頻幀由幀頭和音頻數據組成。幀頭以字節爲單位指示幀的大小(使用CMR模式表 - http://www.developer.nokia.com/Community/Wiki/AMR_format)。幀大小存儲在幀的第一個字節中 - >第二位至第5位,將MSB計爲第一位。從AMR-NB文件中提取音頻幀
算法不起作用,我決定以二進制方式(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
我把字節NR 6:10011110 - > 0011 NR 3, 3的CMR值相當於18.我跳過18個字節,然後到達字節nr。 6 + 18 = 24:00000000 - 0的CMR值是13,我跳過另一個13字節 - > 24 + 13 = 37:01101110 - > 1101 is 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]
看來,我做錯了從字節位集合的轉換,然後導致算法失敗。在字節nr.6中,它應該表示爲數字121,但由錯誤的nr 158表示。由於它使用相同的轉換,二進制輸出也是錯誤的。我沒有檢查轉換方法(我沒有在這裏發佈)。對不起打擾。
你可以在vim或任何十六進制編輯器中打開你的文件,看看它顯示爲文件頭嗎? – Rajeev