2013-07-05 3 views
2

AMR 파일에서 각 프레임을 추출하는 알고리즘을 작성했습니다. 파일의 처음 6 바이트를 헤더로 간주하고 다음 정보는 오디오 프레임입니다. 각 오디오 프레임은 프레임 헤더 및 오디오 데이터로 구성됩니다. 프레임 헤더는 프레임의 크기를 바이트 단위로 알려줍니다 (CMR 모드 표 - http://www.developer.nokia.com/Community/Wiki/AMR_format 사용). 프레임 크기는 프레임의 첫 번째 바이트 -> 두 번째 비트 -> 다섯 번째 비트에 저장되어 MSB를 첫 번째 비트로 계산합니다.AMR-NB 파일에서 오디오 프레임 추출

알고리즘이 작동하지 않고 각 바이트를 이진 방식 (0과 1)으로 화면에 표시하기로 결정했으며 언젠가 프레임 크기가 7보다 크고 CMR 테이블에 0 만있는 것으로 나타납니다. 7 값.

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 파일에서 각 바이트)입니다 : 아래

는 CMR 테이블입니다

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 : 10,011,110 -> 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로 표시됩니다. 또한 이진 출력은 동일한 변환을 사용하므로 잘못되었습니다. 전환 방법을 확인하지 않았습니다 (여기서는 게시하지 않았습니다). 방해해서 죄송합니다.

+0

파일을 vim 또는 16 진수 편집기에서 열고 파일 헤더로 표시되는 내용을 볼 수 있습니까? – Rajeev

답변

1

나는이 답변에 너무 늦지 않기를 바랍니다. 첫째

우선 일 : 첫 번째 6 바이트 (파일 헤더) 인 0x23, 0x21, 0x41을,에는 0x4d, 0x52, 0x0A해야 볼 수있는 동일한 reference 에서 . 이것은 상수 값이며 항상 있어야합니다. 파일이 없으면 파일이 손상되어 사용해서는 안됩니다. 따라서 처음 6 바이트를 맹목적으로 건너 뛰어서는 안됩니다.

이제 AMR 코덱은 DTX (불연속 전송)를 지원합니다. DTX는 보코더가 묵음을 감지 할 때 데이터를 적게 생성하여 대역폭을 절약하는 방법 일뿐입니다. 귀하의 amr 파서는 DTX를 기대할 준비가되어 있어야합니다. AMR-NB (AMR 협 대역 또는 단순히 AMR)의 경우 DTX 그래서 당신의 CMR의지도 아래 항목

을 포함해야 모드 (8)를 사용하여 신호됩니다

8 AMR SID 6 (SID는 ... 침묵 지표 침묵 기간을 나타냅니다 만약

15 AMR에 대한 엔트리를 가지고 있어야하므로) SID 후 DATA NO ... 길이 (단지 헤더에 1 바이트 것이다 실제 묵음 프레임이있을 것이다

) 시작 NO_DATA 1

모드 9-11은 폐기해야합니다. 모드 12-14는 향후 사용을 위해 예약되어 있습니다 (일반적으로이 모드도 삭제됩니다).위의 모든 정보는 단일 채널 AMR이 사용되고 있음을 명심했습니다.

은 인쇄에서 당신은 붙여 넣은

6 -> 이것은 AMR 목차 헤더

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

를 들어에게 있어야하는데 1 0 0 1 1 1 1 0

스토리지, F 비트는 0이어야하지만 예제에서는 1입니다. 마지막 두 비트 (패딩 비트)는 0이어야하지만 예에서는 0이 아닙니다. 예를 들어 여기에 전체 내용을 설명하지 않은 것 같습니다.

+0

답변 해 주셔서 감사합니다. 여기에있는 문제는 언급 한 바와 같이 AMR 헤더에 실제로 속하는지 확인하지 않고 처음 6 바이트를 맹목적으로 건너 뜁니다. amr 파일은 대신 3gp 파일이었습니다. 이제 저는 .3gp에서 raw amr을 추출해 냈습니다. 그렇다면 CMR 테이블을 8 -> 6 바이트 및 15 -> 1 바이트로 확장 할 것을 제안합니까? –

+0

및 9-11을 버려야합니까? 내가 9 바이트 값을 가지면 어떤 바이트도 건너 뛰지 않아야합니까? –

+1

예. 당신의 논리는 크기 6 바이트의 모드 8과 크기 1 바이트의 모드 15를 포함해야합니다. 일반적으로 저는 지금까지 4 년 동안 실시간 시나리오에서 AMR을 사용하여 이러한 모드를 가진 단일 프레임을 만나지 못했기 때문에 모든 모드를 9에서 14로 건너 뛰었습니다. – Rajeev

관련 문제