使用delphi对amr文件解码

我们都知道,现在手机的录音大部分都采用amr格式。对于人声,amr可以做到很高的压缩率(例如:1k bytes/sec),非常方面网络传输。


可是,现在电脑上能解码amr文件的软件不是很多,甚至有些big公司的播放器居然在播放amr文件的时候声音很嘈杂混乱。


利用OpenCore的amr编码解码算法,可以很方便的对amr文件进行解码,既可以把amr转换成wav文件,还可以实现边解码边播放。


首先,下载OpenCore AMR:http://sourceforge.net/projects/opencore-amr/,版本可以选择0.1.3。


然后,用Ming对下载的C语言工程进行编译(很慢,很low,我的机器编译过程花了近2个小时),编译后,找到一个dll文件:libopencore-amrnb.dll


最后,我们用delphi调用这个dll中的三个函数,实现解码:

   function Decoder_Interface_init():pointer;cdecl;external 'libopencore-amrnb.dll';
   procedure Decoder_Interface_exit(state:pointer);cdecl;external 'libopencore-amrnb.dll';
   procedure Decoder_Interface_Decode(state:pointer; DataIn:pbyte; DataOut:pword; bfi:integer);cdecl;external 'libopencore-amrnb.dll'; 

-------------------------------分割线-------------------

procedure TAmrThread.Amr2WavNB();
var
  amr:pointer;
  FileAmr:TFileStream;
  FileWav:TFileStream;
  n,_size,i:integer;
  buffer:array [0..499] of byte;
  littleendian:array [0..319] of byte;
  outbuffer:array[0..159] of Word; 
  ptr:PByte;
  _sizes:array [0..15] of integer = (12, 13, 15, 17, 19, 20, 26, 31, 5, 6, 5, 5, 0, 0, 0, 0 );       
begin
  percent:=0;
  AmrErrorMsg:='';
  FileAmr:=TFileStream.Create(AmrFileName+'.amr',fmOpenRead);
  if FileAmr=nil then begin
    percent:=100;
    AmrErrorMsg:='failed to open amr file.';
    exit;
  end;
  FileAmr.Position:=7;


  FileWav:= CreateWav(1,16,8000,'FromAmr.wav');
  if FileWav=nil then begin
    percent:=100;
    AmrErrorMsg:='failed to create wav file.';
    exit;
  end;
  amr:=Decoder_Interface_init();


  while true do begin
   // Read the mode byte
        while true do begin
           n := FileAmr.Read(buffer, 1);
            if (n <= 0) then break;
            if ((buffer[0] and 4)=4) then break; //bit2=0 means error frame
        end;
        if (n<=0) then break;


   // Find the packet size
   _size := _sizes[(buffer[0] >> 3) and 15];
        if _size<=0 then continue;
   n := FileAmr.Read(buffer[1],  _size);     //@buffer[1]
        if (n <> _size) then break;


   // Decode the packet
   Decoder_Interface_Decode(amr, buffer, outbuffer, 0);


   // Convert to little endian and write to wav
   ptr := littleendian;
   for i := 0 to 159 do begin
   ptr^:= (outbuffer[i] shr 0) and 255;    inc(ptr);  //*ptr++ = (outbuffer[i] >> 0) & 0xff;
   ptr^:= (outbuffer[i] shr 8) and 255;    inc(ptr);  //*ptr++ = (outbuffer[i] >> 8) & 0xff;
   end;
   FileWav.Write(littleendian, 320);


        percent:=100*FileAmr.Position div FileAmr.Size;
        PostMessage(HMainForm,WM_DEAL_AMR,0,0);
  end;

  Decoder_Interface_exit(amr);
  CloseWavFile(FileWav);
  FileAmr.Free;
  percent:=100;
end; 

function CreateWav( channels : word; { 1(单声)或者2(立体声) }
resolution : word; { 8或者16,代表8位或16位声音 }
rate : longint; { 声音频率,如11025,22050, 44100}
fn : string { 对应的文件名称 } ):TFileStream;
var
  wf : TFileStream;
  wh : TWavHeader;
begin
  wh.rId := $46464952;
  wh.rLen := 36;
  wh.wId := $45564157;
  wh.fId := $20746d66;
  wh.fLen := 16;
  wh.wFormatTag := 1;
  wh.nChannels := channels;
  wh.nSamplesPerSec := rate;
  wh.nAvgBytesPerSec := channels*rate*(resolution div 8);
  wh.nBlockAlign := channels*(resolution div 8);
  wh.wBitsPerSample := resolution;
  wh.dId := $61746164;
  wh.wSampleLength := 0;
  Result:=nil;
  try
    wf:=TFileStream.Create(fn,fmCreate or fmShareDenyNone);
    wf.Write(wh,sizeOf(wh));
    Result:=wf;
  except
  end;
end;
procedure CloseWavFile(f:TFileStream);
var
  DataSize:integer;
begin
    DataSize:=f.Size -8;
    f.Seek(4,soFromBeginning); //写RIFF之后的4个字节
    f.Write(DataSize,sizeOf(DataSize));
    DataSize:=DataSize-36;
    f.Seek(40,soFromBeginning);//写data之后的4个字节
    f.Write(DataSize,sizeOf(DataSize));
    f.Free ;
end; 


----------------------------------------------

webliv,西安国咨软件。如要引用请注明出处。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值