amr编程汇总

                                                                          amr编程汇总

 

 

       今年8月我负责研发amr语音的录制和格式转换,现在将经验于大家分享一下。

       amr的特性:

       a静音期间内的存储空间几乎为0,所以amr文件的长度并不与录音时间成正比。

       b压缩比高,连续讲话60秒的录音文件大概20k左右,因此你可以用手机存储传输amr而不用太担心存储空间和gprs流量费。

 

 

  首先说一下格式转换的问题:

提起格式转换建议看看http://xa.bi/mms/

                       .-----------.
                    -->|  MID/MOD  |
                       `-----+-----'
                             |
                          timidity
       |                     |                                                             |
       v                     v                                                             v
  .---------.         .-------------.       .-------.          .-----------.           .-------.
  |         +--mp123->|             |       |       +--encode->|           +--ifs2amr->|       |
  |   MP3   |         |     WAV     |<-sox->|  RAW  |          |  AMR-IF2  |           |  AMR  |
  |         |<--lame--+             |       |       |<-decode--|           |<-amr2ifs--+       |
  `----+----'         `---------+---'       `-------'          `-----------'           `---+---'
       |                  ^     |                                                          |
       v                  |     v                                                          v

这里介绍了一个大致的转换思路,以及需要用到的相应工具。

   主要思路是首先将amr通过一系列转换变成wav然后在转其他格式。

   本文接下来就剖析一下amr转换成wav的过程。

    

       1首先让我们来了解一下amr的文件格式。

       http://www.ietf.org/rfc/rfc3267.txt定义了amr的文件格式。

       amr是一种有损压缩,最初的版本只用来存储单声道的语音文件,比特率为4.75 kbit/s

       后续版本提供了双声道和更多的表现细节的能力,

       主要是采样率的不断的提高一直到最后的比特率12.5 kbit/s

       最终使得amr可以存储高质量的音乐,当然也占用了大量的存储空间。

       2AMR-IF2文件格式。定制AMR-IF2的目的就是用于格式转换的。AMR-IF2相当于一个接口文件格式。

       这样在amr的版本不断变化的情况下,我们无需对先前的转换播放从程序做太多的改变。

       3两者的区别和联系:

       AMR-IF2是没有文件头的。而amr文件有着不同的文件头但所有的文件头有一个共同的特点,

       都包括 {0x23,0x21,0x41,0x4D,0x52,0x 0A}(#!AMR+回车)

       3.1两者都是分贞的每贞都有固定的长度。与比特率相关。

       主要有两种贞,一种是用来记录一小段时间内的声音采样,

       采用了小波变换进行提取压缩,压缩率视比特率而定。

       另外还有一种特殊的贞叫silenc frame,顾名思义就是静音,表示静音的时间长度。

       3.2两者的贞的存储格式是不同的需要进行转换。要了解更多关于amr-if2文件格式请参阅:

http://www.3gpp.org/ftp/tsg_sa/WG4_CODEC/Specs_update_after_SA16/26101-500.zip

 

 

 

Figure A.1: Frame structure for AMR IF2

其中frametype的订阅如下 0-15,注意只占用了4bit,就是为了节省4bit给我们的转换工作带来了许多麻烦。类型中的***SID是指该贞为silence贞。

Table 1a: Interpretation of Frame Type,
Mode Indication and Mode Request fields

Frame Type


Mode Indication

Mode Request

Frame content (AMR mode, comfort noise, or other)

0

0

0

AMR 4,75 kbit/s

1

1

1

AMR 5,15 kbit/s

2

2

2

AMR 5,90 kbit/s

3

3

3

AMR 6,70 kbit/s (PDC-EFR)

4

4

4

AMR 7,40 kbit/s (TDMA-EFR)

5

5

5

AMR 7,95 kbit/s

6

6

6

AMR 10,2 kbit/s

7

7

7

AMR 12,2 kbit/s (GSM-EFR)

8

-

-

AMR SID

9

-

-

GSM-EFR SID

10

-

-

TDMA-EFR SID

11

-

-

PDC-EFR SID

12-14

-

-

For future use

15

-

-

No Data (No transmission/No reception)

 

 

 

那么每个贞到底是多长呢,这与比特率有关。如下:

Table 2: Number of bits in Classes A, B, and C for each AMR codec mode

Frame Type

AMR
codec mode

Total number of bits

Class A

Class B

Class C

0

4,75

95

42

53

0

1

5,15

103

49

54

0

2

5,90

118

55

63

0

3

6,70

134

58

76

0

4

7,40

148

61

87

0

5

7,95

159

75

84

0

6

10,2

204

65

99

40

7

12,2

244

81

103

60

amr475来说

4bitframe type 接下来的95bit放音频数据,其中classA42bitclassB53bit。如下所示:

 

 

由上面两表可见,if2的贞与amr文件的贞相比多了一个4bit的类型,相应的字节也都左移了。

由于去掉了类型,amr文件存储有时会比if2小一些。

http://xa.bi/files/amrconvert中使用了perl的字符串和正则处理,先将二进制bit转换成串

再去掉type,最后转换成二进制。

我们也可以用位操作来完成这两种贞的转换。

我们可以这样转换两种文件:

If2->amr

1取出第一个字节,判断贞的类型。

2根据贞类型生成文件头并写入文件。

3根据贞类型确定贞长度。

4如果有则读取一贞,转换成amr贞执行5,否则结束。

5amr贞写文件 执行4

Amr->if2:

1读取文件头,判断文件类型。

2根据文件类型确定贞长度。

3如果有则读取一贞,转换成if2贞执行5,否则结束。

4amr贞写文件 执行4

26104-500描述了从rawif2的转换

你可以参考里面的26104-500_ANSI-C_source_code

        如果使用特殊的wav文件,从wavraw的转换是非常简单的,所谓的raw是特定wav

(单声道,8KHz16Bit)。如果你使用的文件是单声道16bit8KHz的文件,只需要去掉文件头就可以了。

否则必须用Sox,或者用sox相同的方法。这是一个开源的软件,有兴趣的话你可以参考一下。

http://sox.sourceforge.net/

二接着谈谈amr的录制和播放

如果是pc的话建议录制成wav文件然后转换成amr,手机可不能这么搞,文件太大了转换也麻烦,所以应该直接录制成amr

Java手机的录制和播放:J2ME (MIDP 2.0, CLDC 1.0)

http://www.hcilab.org/documents/tutorials/AudioTest/

录制:

        Player player; 
        ... 
        player=Manager.createPlayer(“capture://audio?encoding=amr”); 

        player.realize();

       RecordControl rc = (RecordControl)player.getControl("RecordControl"); 
       ByteArrayOutputStream output = new ByteArrayOutputStream(); 
       rc.setRecordStream(output); 
       rc.startRecord(); 
       player.start(); 

       Thread.currentThread().sleep(5000); 
       rc.commit(); 

播放:

       ByteArrayInputStream recordedInputStream = new ByteArrayInputStream(recordedSoundArray); 
       Player p2 = Manager.createPlayer(recordedInputStream,"audio/x-wav"); 
       p2.prefetch(); 
       p2.start(); 

Symbian手机的录制和播放:

主要是CMdaAudioRecorderUtility的使用方法的问题。

 

播放:

 TFileName tFullFileName = GetFullFileName(aBarFileName);
 iCurrentFileName=tFullFileName;
 RLog::Log(aBarFileName); 
 RLog::Log(tFullFileName);
 
#ifdef __WINS__ 
  TRAPD(err,
  iMdaAudioRecorderUtility->OpenFileL(
    tFullFileName,
    KMMFExControllerUID,
    KMMFExControllerUID,
    KMMFExDesFormatUID,
    KMMFFourCCCodeAMR
  ));
#else
 TRAPD(err,
 iMdaAudioRecorderUtility->OpenFileL(
  tFullFileName
  ));
#endif
 if(err) 
 {
  RLog::Log(_L("OpenFile err"),err);
  User::Leave(err);  
 }

  CMdaAudioRecorderUtility* iMdaAudioRecorderUtility;
iMdaAudioRecorderUtility= new ...

iMdaAudioRecorderUtility= new ...

 iMdaAudioRecorderUtility->SetAudioDeviceMode(CMdaAudioRecorderUtility::ELocal);
 
    // Set maximum volume for playback
    iMdaAudioRecorderUtility->SetVolume(iMdaAudioRecorderUtility->MaxVolume());
 
    // Set the playback position to the start of the file
    iMdaAudioRecorderUtility->SetPosition(TTimeIntervalMicroSeconds(0));
 
 TRAPD(errp,iMdaAudioRecorderUtility->PlayL());
 if(errp)
 {
  RLog::Log(_L("Play"),errp);
 }

录制:

 if(iMdaAudioRecorderUtility->State()==CMdaAudioClipUtility::ERecording
  ||iMdaAudioRecorderUtility->State()==CMdaAudioClipUtility::EPlaying)
  return;
 RLog::Log(_L("RecordL 1"));
 if(iMdaAudioRecorderUtility->State()==CMdaAudioClipUtility::EOpen)
  iMdaAudioRecorderUtility->Close();
 //TPtrC aFileName(KRecorderFile);
 TRAPD(errc,this->CleanAmrFileL(aBarFileName));
 if(errc)
 {
  RLog::Log(_L("CleanAmrFileL:"),errc);
  User::Leave(errc);
 }
 else{
  RLog::Log(_L("CleanAmrFileL:OK"));
 }
 TRAPD(erro,this->OpenRecordFileL(aBarFileName));
 if(erro)
 {
  RLog::Log(_L("OpenRecordFile:"),erro);
  User::Leave(erro);
 }
 else{
  RLog::Log(_L("OpenRfileOK"));
 }
 // Record from the device microphone
    iMdaAudioRecorderUtility->SetAudioDeviceMode(CMdaAudioRecorderUtility::ELocal);
 
    // Set maximum gain for recording
    iMdaAudioRecorderUtility->SetGain(iMdaAudioRecorderUtility->MaxGain());
   
    // Delete current audio sample from beginning of file
    iMdaAudioRecorderUtility->SetPosition(TTimeIntervalMicroSeconds(0));
    //iMdaAudioRecorderUtility->CropL();
 
    TRAPD(err,iMdaAudioRecorderUtility->RecordL());
 if(err){
  RLog::Log(_L("RecordL Err"),err);
 }
 //iEngineStatus=ERECORDING;

也用CMdaAudioOutputStream可以进行流播放

我用的是syimbian的stream带的sdk
iAudioStreamPlayer = CMdaAudioOutputStream::NewL(*this);
iSettings.iVolume = iAudioStreamPlayer -> MaxVolume()/iVolume;
iSettings.iChannels = TMdaAudioDataSettings::EChannelsMono;
iSettings.iSampleRate =(aMMF4CCode==KMMFFourCCCodeMP3)? TMdaAudioDataSettings::ESampleRate8000Hz: TMdaAudioDataSettings::ESampleRate32000Hz;
#ifndef __WINS__
this->iAudioStreamPlayer->SetDataTypeL(aMMF4CCode);
this->iAudioStreamPlayer->SetPriority(EPriorityNormal, EMdaPriorityPreferenceNone);
#endif
//this->iAudioStreamPlayer->SetDataTypeL(KMMFFourCCCodePCM16);
iAudioStreamPlayer -> Open(&iSettings);

流的播放:

有时候你只能在内存里面播放amr而不是从文件里面打开。这需要你完成转码和流的播放两步工作。

在SDK 1.2中你只能用 CAmrToPcmDecoder 在 amrcodec.h 里面。

如果SDK是 2.0 或者更高的版本中使用 CMMFCodec

       未完待续

AMR在IP域中的编码(rfc3267,4867) 缩写解释 SID Silence Descriptor (Comfort Noise Frame) 1 AMR编码介绍 AMR编码是一种自适应多速率编码,根据传输信道的实际情况,调整编码模式、速率和纠错码位数来保证语音质量,在数据压缩和容错上面取得平衡。一般语音质量越高抗干扰能力越弱。在GSM网络,基站、基站控制器可根据网络质量和信号质量情况动态调整语音编码模式以提高不同网络状况下的语音质量。现在手机终端基本上都支持AMR编码,Nokia从2004年开始提供支持AMR的终端,目前所有的新型号终端都支持AMRAMR在IP域中的编码(rfc3267,4867) AMR算法 参考文档 (1) 3GPP TS26.190, AMR Wideband speech codec; Transcoding functions(Release 5). (2) 3GPP TS 26.194, Voice Activity Detection (VAD). (3) 3GPP TS 26.174, AMR wideband speech codec; Test sequences. (4) 3GPP TS 26.194, Frame Structure. 2 AMR在IP域中的净荷格式 RFC3267/4867协议描述AMR编码在RTP中的载荷格式,是其在IP域的存在形式。 对于每个RTP会话,AMR净荷有两种模式,分别为节省带宽模式和字节对齐模式,具体采用那种模式,由信令协商决定;采用后一模式可以后可以引入鲁棒排序、帧交叉编码和CRC校验等方式提高语音传输的质量。 以下三种场景分别为1IP域的终端进行会话、2非IP域终端通过网关和3IP域终端会话以及非IP域终端之间的通信场景,各个场景的特点见协议描述。 AMRAMR-WB净荷格式 二者格式区别,a.帧类型;b.前者的采样频率为8KHZ,后者为16KH;c.模式不一样 净荷结构如下,包括净荷头,内容表和语音数据: +----------------+-------------------+---------------- | payload header | table of contents | speech data ... +----------------+-------------------+---------------- Payloads containing more than one speech frame-block are called compound payloads. 节省带宽模式Bandwidth-Efficient Mode a. 净荷头格式: 0 1 2 3 +-+-+-+-+ | CMR | +-+-+-+-+ CMR(codec mode request)编码模式请求,由发送者向接受者的请求发送者编码器将来的编码速率模式,保存帧类型索引,如果是AMR,取值范围为0-7,表示8种速率模式,如果为AMR-WB,取值范围为0-8,表示9种速率。取值15意味着当前是没有指定哪个模式的请求。 模式选定后,由于采样频率恒定,具体包的打包时长还是不变,不同速率只是净荷长度不一样,例如对于AMR模式0,其速率是4.75Kbit/s,净荷中包含的语音数据为95bits。 AMR的8种速率索引表,见[1] AMR在IP域中的编码(rfc3267,4867) AMR-WB的9种速率索引表,见[2] AMR在IP域中的编码(rfc3267,4867) b. 净荷内容表ToC(table of contents),第一项表示一个语音帧 0 1 2 3 4 5 +-+-+-+-+-+-+ |F| FT |Q| +-+-+-+-+-+-+ F:用于标志是否最后一个帧,0表示最后1帧.如果是多帧复用才有Toc才会有多项,否则只有1项。 FT:标志对音帧语音编码模式或舒适噪志的模式,取值范围同CMR取值,FT=14 (SPEECH_LOST, only available for AMR-WB) and FT=15 (NO_DATA),FT=15表示没有当前帧没有净荷;取值10-13该帧要丢弃。 Q:指示帧质量,为0表示对应帧被破坏,1表示未被破坏;如果该帧已被破坏,那么可以通过直接丢弃该帧来处理。 净荷内容表就是对帧内容的数据格式说明, c. 语音数据speech data 语音数据即为真正的语音帧或舒适噪声帧的数据,每帧数据的描述和ToC每一项对应起来,数据长度取决于对应模式ToC项中的FT标识的模式。 示例: 单通道单帧 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | CMR=15|0| FT=4 |1|d(0) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | d(147)|P|P| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 单通道多帧 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | CMR=1 |1| FT=0 |1|1| FT=9 |1|1| FT=15 |1|0| FT=1 |1|d(0) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | d(131)| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |g(0) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | g(39)|h(0) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | h(176)|P|P|P|P|P|P|P| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 多通道多帧,见协议 字节对齐模式Octet-aligned Mode a. 净荷头格式 0 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +-+-+-+-+-+-+-+-+- - - - - - - - | CMR |R|R|R|R| ILL | ILP | +-+-+-+-+-+-+-+-+- - - - - - - - CMR:同上; R:保留位,区分节省带宽模式,这些保留位作用之一就是字节对齐; ILL:可选,指示交错长度(取值为L,交错长度即为L+1); ILP:可选,交错块的索引,取值范围为0到ILL,超过这个范围,该帧块应被丢弃。 b. ToC +---------------------+ | list of ToC entries | +---------------------+ | list of frame CRCs | (optional) - - - - - - - - - - - Note, for ToC entries with FT=14 or 15, there will be no corresponding speech frame or frame CRC present in the payload. 组成同节省带宽模式 ToC项:在该模式下,6位ToC也需要2位补齐。 CRC:CRC校验位可选,如果带外信令协商需要校验,则每项对应每个语音数据进行8位长度的校验。 语音数据 同节省带宽模式,只是要求每帧必须补0对齐;对于多帧的净荷,可以和节省模式一样,一帧顺序排,也可以所有帧以字节为单位交错排序,尽量把各个帧错误敏感位排前面。 示例: 单通道多帧 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | CMR=6 |R|R|R|R|1|FT#1=5 |Q|P|P|0|FT#2=5 |Q|P|P| f1(0..7) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | f1(8..15) | f1(16..23) | .... | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ : ... : +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ... |f1(152..158) |P| f2(0..7) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | f2(8..15) | f2(16..23) | .... | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ : ... : +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ... |f2(152..158) |P| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 多通道 3 AMR语音帧结构 AMRAMR-WB的语音数据结构分别详见TS 26.101,26.201描述,这里介绍AMR-NB的语音数据编码结构。 语音数据位根据重要性分成类,A、B、C类,其对错误的敏感性和重要性依次为A>B>C,如下,4.75Kb模式的总的位数为95位,A类42位,B类53位。 AMR在IP域中的编码(rfc3267,4867) AMR净荷数据把重要的数据位放在前面,不重要的放在后面,为了把语音数据中重要的数据位放置A类,需要对编码器编出的比特位进行重排序,26.101把编码后数据位的位置和重排序的位置对应起来形成一张表供查询, - for j = 0 to K-1 //第0位到第K-1位全部重排 - d(j) := s(tablem(j)+1); //查对应模式的表找到重排后相应位置 例如下表6.7kb模式的排序表,共134位,第82位数据位排序后对应18位 AMR在IP域中的编码(rfc3267,4867) 上节节省带宽模式和字节对齐模式,d(i)均是排序后的数据。 下图示例相比上一节还加了8位CRC校验码。 4 AMR NB/WB信令协商参数 AMR常用如下 octet-align,是节省带宽模式还是字节对节模式,一般取值为1表示字节对齐,为0或不带默认表示为节省带宽模式; mode-set,一旦请求带了模式集,之后AMR媒体流只选择属于这个模式集的模式来发送; mode-change-period,模式改变周期; maxptime,最大支持的打包时长(ms); crc,净荷是否进行CRC校验,一般为1表示需要,媒体流会携带校验位; robust-sorting,是否进行鲁棒排序; interleaving,定义交错帧块数; ptime,指包时长; channels,音频通道数,例如采用左右通道数值则为2; AMR-WB常用参数同上 4 多帧复用 为了降低带宽,减少网络传输的RTP包数,把多帧的数据打包在1个RTP包里面进行传输。净荷里面用ToC表来管理多帧数据,说明模式等内容,这样也可根据网络状况灵活改变多帧的速率,例如,多帧中每个帧的速率不一定要一样。 采用多帧复用要注意关注RTP包的大小、时戳是否正确。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值