现在的位置: 首页 > 综合 > 正文

音频捕捉

2017年12月02日 ⁄ 综合 ⁄ 共 23581字 ⁄ 字号 评论关闭

http://www.delphibbs.com/keylife/iblog_show.asp?xid=21687
KeyLife富翁笔记 
作者: wuchunhua
标题: 音频捕捉
关键字: waveInOpen
分类: 个人专区
密级: 公开
(评分: , 回复: 2, 阅读: 216) »»
unit unit1;

interface

uses
  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  Forms, Dialogs, mmsystem, StdCtrls;

const
  memBlockLength = 500;
type
  Tmemblock = array[0..memblocklength] of byte;
  PmemBlock = ^TmemBlock;

TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  private
  { Private declarations }
    HwaveIn : PHWaveIn ;
    HWaveOut: PHWaveOut ;
    close_invoked, close_complete : boolean ;
    in_count, out_count : integer ;
    procedure MMOutDone(var msg:Tmessage);message MM_WOM_DONE;
    procedure MMInDone(var msg:Tmessage);message MM_WIM_DATA;
  public
  { Public declarations }
end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
var
   WaveFormat:PPCMWaveFormat;
   Header:PWaveHdr;
   memBlock:PmemBlock;
   i,j:integer;
begin
     WaveFormat:=new(PPCMwaveFormat);
     with WaveFormat^.wf do
     begin
          WFormatTag := WAVE_FORMAT_PCM; {PCM format - the only option!}
          NChannels:=1; {mono}
          NSamplesPerSec:=11000; {11kHz sampling}
          NAvgBytesPerSec:=11000; {we aim to use 8 bit sound so only 11k per second}
          NBlockAlign:=1; {only one byte in each sample}
          waveformat^.wBitsPerSample:=8; {8 bits in each sample}
     end;
    
     i:=waveOutOpen(nil,0,PWAVEFORMATEX(WaveFormat),0,0,WAVE_FORMAT_QUERY);
     if i <> 0 then application.messagebox('Error', 'Play format not supported', mb_OK);

     i:=waveInOpen(nil,0,PWAVEFORMATEX(WaveFormat),0,0,WAVE_FORMAT_QUERY);
     if i <> 0 then application.messagebox('Error', 'Record format not supported', mb_OK);

     HwaveOut:=new(PHwaveOut);
     i:=waveOutOpen(HWaveOut,0,PWAVEFORMATEX(WaveFormat),form1.handle,0,CALLBACK_WINDOW);
     if i <> 0 then application.messagebox('Error', 'Problem creating play handle', mb_OK);

     HwaveIn:=new(PHwaveIn);
     i:=waveInOpen(HWaveIn,0,PWAVEFORMATEX(WaveFormat),form1.handle,0,CALLBACK_WINDOW);
     if i <> 0 then application.messagebox('Error', 'Problem creating record handle', mb_OK);

     {these are the count of the number of blocks sent to}
     {the audio device}
     in_count:=0;
     out_count:=0;

     {need to add some buffers to the recording queue}
     {in case the messages that blocks have been recorded}
     {are delayed}
     for j:= 1 to 3 do
     begin
          {make a new block}
          Header:=new(PWaveHdr);
          memBlock:=new(PmemBlock);

          Header:=new(PwaveHdr);
          with header^ do
          begin
               lpdata:=pointer(memBlock);
               dwbufferlength:=memblocklength;
               dwbytesrecorded:=0;
               dwUser:=0;
               dwflags:=0;
               dwloops:=0;
          end;

          i:=waveInPrepareHeader(HWaveIn^,Header,sizeof(TWavehdr));
          if i <> 0 then application.messagebox('In Prepare error','error',mb_ok);

          i:=waveInAddBuffer(HWaveIn^,Header,sizeof(TWaveHdr));
          if i <> 0 then application.messagebox('Add buffer error','error',mb_ok);

          inc(in_count);

     end; {of loop}

     {开始记录}
     i:=waveInStart(HwaveIn^);
     if i <> 0 then application.messagebox('Start error','error',mb_ok);

     close_invoked:=false;
     close_complete:=false;
end;

procedure TForm1.MMOutDone(var msg:Tmessage);
var
   Header:PWaveHdr;
   i:integer;
begin
     dec(out_count);
     {得到返回的数据}
     Header:=PWaveHdr(msg.lparam);
     i:=waveOutUnPrepareHeader(HWaveOut^,Header,sizeof(TWavehdr));
     if i<> 0 then application.messagebox('Out Un Prepare error','error',mb_ok);

     {释放}
     dispose(Header^.lpdata);
     dispose(Header);

     {if there's no more blocks being recorded}
     if (out_count=0) then
     begin
          WaveOutClose(HWaveOut^);
          HwaveOut:=nil;
     end;

     {判断是否已经处理完输入和输出队列}
     if (in_count=0) and (out_count=0) then
     begin
          close_complete:=true;
          close;
     end;

end;

procedure TForm1.MMInDone(var msg:Tmessage);
var
   Header:PWaveHdr;
   memBlock:PmemBlock;
   i:integer;
begin
     dec(in_count);
     {得到已经接收的数据块}
     Header:=PWaveHdr(msg.lparam);
     i:=waveInUnPrepareHeader(HWaveIn^,Header,sizeof(TWavehdr));
     if i<>0 then application.messagebox('In Un Prepare error','error',mb_ok);

     if not(close_invoked) then
     begin
          {装入输出缓存}
          i:=waveOutPrepareHeader(HWaveOut^,Header,sizeof(TWavehdr));
          if i<>0 then application.messagebox('Out Prepare error','error',mb_ok);

          {添加到输出队列中}
          i:=waveOutWrite(HWaveOut^,Header,sizeof(TWaveHdr));
          if i<>0 then application.messagebox('Wave out error','error',mb_ok);
          inc(out_count);

          {定义一个新的缓存块}
          Header:=new(PWaveHdr);
          memBlock:=new(PmemBlock);

          Header:=new(PwaveHdr);
          with header^ do
          begin
               lpdata:=pointer(memBlock);
               dwbufferlength:=memblocklength;
               dwbytesrecorded:=0;
               dwUser:=0;
               dwflags:=0;
               dwloops:=0;
          end;

          {准备波形装入块}
          i:=waveInPrepareHeader(HWaveIn^,Header,sizeof(TWavehdr));
          if i<>0 then application.messagebox('In Prepare error','error',mb_ok);

          {将缓存区发送给波形输入设备}
          i:=waveInAddBuffer(HWaveIn^,Header,sizeof(TWaveHdr));
          if i<>0 then application.messagebox('Add buffer error','error',mb_ok);

          inc(in_count);
     end;

     {队列已经为空}
     if (in_count=0) then
     begin
          WaveInClose(HWaveIn^);
          HwaveIn:=nil;
     end;

     {判断是否已经处理完输入和输出队列}
     if (in_count=0) and (out_count=0) then
     begin
          close_complete:=true;
          close;
     end;
end;

 

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
     {reset the output channel}
     if HWaveOut <> nil then WaveOutReset(HWaveOut^);

     {reset the input channel}
     if HwaveIn<>nil then WaveInReset(HWaveIn^);
     close_invoked:=true;
     canclose:=close_complete;
end;

end.

 

2006-4-26 9:42:09   
 发表评语&raquo;&raquo;&raquo;    

 2006-4-26 9:43:09    思路来源文章来源:uddu 97年9月(文章太长,
我没贴全,if you can't find it,you can email me)

UNDU, Sept 1997 article "Playing and Recording Sound in Delphi" by Darryl Gove
你还可以使用控件Audio 4.0(可以从很多地方
download)

1. Do you have a soundcard?

if WaveOutGetNumDevs=0 then
application.messagebox('Error', 'No sound playing card', mb_OK);
if waveInGetNumDevs=0 then
application.messagebox('Error','No recording sound card',mb_ok);

2.Getting a handle on it.

HwaveOut:=new(PHwaveOut);
i:=waveOutOpen(HWaveOut,0,Pwaveformat(WaveFormat),form1.handle,0,CALLBACK_WINDOW);
if i<>0 then
  application.messagebox('Error', 'Problem creating play handle', mb_OK);

HwaveIn:=new(PHwaveIn);
i:=waveInOpen(HWaveIn,0,Pwaveformat(WaveFormat),form1.handle,0,CALLBACK_WINDOW);
if i<>0 then
  application.messagebox('Error', 'Problem creating record handle', mb_OK);

3.Being prepared

The final thing to do is to start either playing sound or recording sound.
To do this we need to send packets of memory to the sound card either to play or to record on.
When you send data out to be played,
the playing starts immediately you add a packet of data,
extra packets of data are added to a queue, and played in sequence.
If youre recording then the blocks of memory are once again added to a queue -
but they are not recorded on until you tell the computer to start recording.
If the computer runs out of packets to record on then the recording stops.

So the first thing to do is to get a block of memory and to set up the data block
that will tell the multimedia subsystem about it.

Tmemblock=array[0..memblocklength] of byte;
memBlock:=new(PmemBlock);

Nows a good time to put your audio data into the memory block - if youre playing audio.

Header:=new(PwaveHdr);
with header^ do
  begin
    lpdata:=pointer(memBlock);
    dwbufferlength:=memblocklength;
    dwbytesrecorded:=0;
    dwUser:=0;
    dwflags:=0;
    dwloops:=0;
  end;

Except for setting the pointer to a block of memory, and the length of the block of memory, all the other fields should be set to zero - unless you want to play the same block of data multiple times.
The next step is to prepare the data, why this is necessary, I dont know!

i:=waveOutPrepareHeader(HWaveOut^,Header,sizeof(TWavehdr));
if i<>0 then
  application.messagebox('Out Prepare error','error',mb_ok);

i:=waveInPrepareHeader(HWaveIn^,Header,sizeof(TWavehdr));
if i<>0 then
  application.messagebox('In Prepare error','error',mb_ok);

Then we need to send the new block of data to the audio device - either to be played or to be recorded on.

i:=waveOutWrite(HWaveOut^,Header,sizeof(TWaveHdr));
if i<>0 then
  application.messagebox('Wave out error','error',mb_ok);

i:=waveInAddBuffer(HWaveIn^,Header,sizeof(TWaveHdr));
if i<>0 then
  application.messagebox('Add buffer error','error',mb_ok);

The final thing to do when recording sound is to start!

i:=waveInStart(HwaveIn^);
if i<>0 then
   application.messagebox('Start error','error',mb_ok);

There are also commands to stop and pause recording.

4.Messages

If youre using messages to control the recording an playback of audio,
then you need to have some handlers for the messages.
The handlers should be something like

procedure MMOutOpen(var msg: Tmessage); message MM_WOM_OPEN;
procedure MMOutClose(var msg: Tmessage); message MM_WOM_CLOSE;
procedure MMOutDone(var msg: Tmessage); message MM_WOM_DONE;
procedure MMInOpen(var msg: Tmessage); message MM_WIM_OPEN;
procedure MMInClose(var msg: Tmessage); message MM_WIM_CLOSE;
procedure MMInDone(var msg: Tmessage); message MM_WIM_DATA

 
 2006-5-12 17:33:28    转载 Delphi中捕获音频函数OnWaveIn的使用小记    说明,并非给别人看,只是为了防止自己忘记,所以没有写说明与注释之类的,不好意思了。
     上次有个朋友叫我帮忙写一个小程序,用处比较怪。显示图片,并开始计时,当测试者说出图像内容的时候(无需识别具体的语音内容),停止计时。这样循环显示一系列图片,并记录从显示图片,到发出声音的这段时间。据说是研究语言学使用的。于是用Delphi写了一个小程序,其中记录声音,过滤噪音,判断是否发出声音的程序如下:

unit SoundCap_Unit;
interface
uses
    Windows, Messages, MMSystem, Classes, SysUtils, Math, Forms, Controls;
Const
  BufferTime : Real = 120;  // 每次0.120秒   0.120 * 1000
type
  TData8 = array [0..127] of byte;
  PData8 = ^TData8;
  TData16 = array [0..127] of smallint;
  PData16 = ^TData16;
  TPointArr = array [0..127] of TPoint;
  PPointArr = ^TPointArr;
  TShowProgressEvent = procedure (Sender: TObject; Position: Integer) of object;
  TCaptureEvent = procedure (Sender: TObject; passTime : Integer) of Object;
  TShowTimeEvent = procedure (Sender : TObject; Time : Integer) of Object;

  TSoundCap = Class(TCustomControl)

  private
    FOnShowTime : TShowTimeEvent;
    FOnShowProgress : TShowProgressEvent;
    FOnCapture : TCaptureEvent;

    function GetMidValue(i : Integer) : Integer;  //计算中值
  protected

    procedure DoShowTime;//(Time : Integer); dynamic;
    procedure DoShowProgress(position : Integer); dynamic;
    procedure DoCapture(passTime : DWORD ); dynamic;

  public

    FilterValve : Integer; //音频过滤的阀值

    isCapture : boolean ;

    //constructor Create(AOwner: TComponent); overload;
    constructor Create(handle : THandle); //overload;
    destructor Destroy; override;

    procedure OpenCapture(handle : THandle);
    procedure CloseCapture;

    procedure OnWaveIn(var Msg: TMessage); message MM_WIM_DATA;
    procedure StartCap;
    procedure StopCap;
    property OnShowTime: TShowTimeEvent read FOnShowTime write FOnShowTime;
    property OnShowProgress: TShowProgressEvent read FOnShowProgress write FOnShowProgress;
    property OnCapture: TCaptureEvent read FOnCapture write FOnCapture;

  end;
implementation

{ TSoundCap }
var
  WaveIn: hWaveIn;
  hBuf: THandle;
  BufHead: TWaveHdr;
  bufsize: integer;
  Bits16: boolean;
  p: PPointArr;
  p2 : PPointArr;
  stop: boolean = false;

  StartTime : DWORD ;
  Count : integer = 0;

constructor TSoundCap.Create(Handle : THandle);//(AOwner: TComponent);
begin
//  ParentWindow := AOwner;
  Inherited Create(nil);
  ParentWindow := handle;
  isCapture := false;
  FilterValve := 3;
end;

destructor TSoundCap.Destroy;
begin

  inherited;
  CloseCapture;
end;

//触发捕获音频事件
procedure TSoundCap.DoCapture(passTime : DWORD );
var
  EndTime : DWORD ;
begin
  EndTime := GetTickCount;
  if Assigned(FOnCapture) then FOnCapture(Self, EndTime - StartTime - passTime);
end;

//显示音频强度
procedure TSoundCap.DoShowProgress(position: Integer);
begin
  if Assigned(FOnShowProgress) then FOnShowProgress(Self, position);
end;

//显示时间
procedure TSoundCap.DoShowTime;//(Time : Integer);
var
  EndTime : DWORD ;
begin
  EndTime := GetTickCount;
  if Assigned(FOnShowTime) then FOnShowTime(Self, EndTime - StartTime);
end;

//中值过滤
function TSoundCap.GetMidValue(i: Integer): Integer;
var
  v0,v1,v2 : integer;
  h : integer;
  mid : integer;
begin
  h := 100;
  v0 := p^[i-2].Y;
  v1 := p^[i-1].Y;
  v2 := p^[i].Y;

  mid := (v0 + v1 + v2) div 3;
  if abs(abs(mid) - v1) > FilterValve  then
    Result := mid
  Else if abs(mid - h/2) < FilterValve then
    Result := 0
  Else
    Result := v1;
end;

//处理Wave数据采集
procedure TSoundCap.OnWaveIn(var Msg: TMessage);
var
  data8 : PData8;
  i, x, y : integer;

  StartPos, EndPos, SCount : integer;
  passTime , MaxValue , tmp : Integer;
  dtime : DWORD;
begin
    //DoCapture(0);

    MaxValue := 0;
    Data8 := PData8(PWaveHdr(Msg.lParam)^.lpData);

    //将Buffer中采集的数据存入 P 中
    for i := 0 to BufSize - 1 do
    Begin

      x := i;
      y := Round(abs(data8^[i] - 128) * 100 / 128); //data8^[i] 为 128 - 256 之间
      p^[i] := Point(x, y);

      //计算滤波后的值 , 滤波之后的数据存入 P2 中
      if (i > 1) and (i < BufSize )  then
      Begin
        p2^[i] := Point(p^[i].X, GetMidValue(i));
      end;

      //p2^[i] := GetMidValue(x,y,i);
      //Inc(count,data8^[i]);
      //count := count + Round(abs(data8^[i] - 128) * 100 / 128);
      //ShowProgress(Round(count / BufSize));

      tmp := Round(abs(data8^[i] - 128) * 100 / 128);
      if tmp > MaxValue Then
        MaxValue := tmp;
      //count := count + tmp;

    End;

    p2^[0] := Point(p^[0].X, GetMidValue(2));
    p2^[1] := Point(p^[0].X, GetMidValue(2));

  //Caption := IntToStr(count div BufSize);

  //不需要绘画音频曲线
  {
  with PaintBox1.Canvas do begin
    Brush.Color := clBlack;
    Pen.Color := clGreen;

    FillRect(ClipRect);
    Polyline(Slice(p^, BufSize));
  end;

  with PaintBox2.Canvas do begin
    Brush.Color := clBlack;
    Pen.Color := clGreen;

    FillRect(ClipRect);
    Polyline(Slice(p2^, BufSize));
  end;
  }

  //判断是否有超出域值的数据
  StartPos := 0;
  EndPos := 0;
  SCount := 0;
  for I := 0 to BufSize - 1 do
  begin
    if abs(p2^[i].Y ) > FilterValve  then
    Begin
      if StartPos = 0 then
        StartPos := i;
      Inc(SCount);
    end Else if StartPos = 0  then
        p^[i].Y :=  0;//h div 2;

    if (SCount > 20) then
      if (EndPos = 0) then
        EndPos := Min((StartPos + BufSize div 2 ) , BufSize - 1)
      Else if EndPos < i then
        p^[i].Y := 0;//h div 2;

  end;

  {
  if (SCount > 20) and isCapture then
  with PaintBox3.Canvas do begin
    Brush.Color := clBlack;
    Pen.Color := clGreen;

    FillRect(ClipRect);
    Polyline(Slice(p^, BufSize));
    isCapture := false;
    Timer1.Enabled := true;
    passTime := Round(StartPos * BufferTime / BufSize);
    RecordTime(passTime);
  end; }

  //Show Time
  If isCapture  Then DoShowTime();

  //SCount := 100;
  //StartPos := 0;
  //如果有音频超出阀值,并且正在捕捉,则记录具体时间
  dtime := GetTickCount - StartTime;
  //如果说 dtime < 120 , 则这个Buffer不是现在的缓冲内容
  if (SCount > 20) and isCapture and (dtime > 120 + 90) then
  Begin
    isCapture := false;
    //Timer1.Enabled := true;
    passTime := Round((BufSize - StartPos) * BufferTime / BufSize) + 90;
    DoCapture(passTime);
  End;

  if stop then WaveInAddBuffer(WaveIn, PWaveHdr(Msg.lParam),
      SizeOf(TWaveHdr))
    else stop := true;

  DoShowProgress(MaxValue);
  //DoCapture(0);
end;

//打开音频捕捉
procedure TSoundCap.OpenCapture(handle : THandle);
var
  header: TWaveFormatEx;
  BufLen: word;
  buf: pointer;
begin
  BufSize := 3 * 500 + 100;//TrackBar1.Position * 500 + 100;
  Bits16 := false;//CheckBox1.Checked;
  with header do begin
    wFormatTag := WAVE_FORMAT_PCM;
    nChannels := 1;
    nSamplesPerSec := 22050;
    wBitsPerSample := integer(Bits16) * 8 + 8;
    nBlockAlign := nChannels * (wBitsPerSample div 8 );
    nAvgBytesPerSec := nSamplesPerSec * nBlockAlign;
    cbSize := 0;
  end;

  WaveInOpen(Addr(WaveIn), WAVE_MAPPER, addr(header),
              self.Handle , 0, CALLBACK_WINDOW);
  BufLen := header.nBlockAlign * BufSize;
  hBuf := GlobalAlloc(GMEM_MOVEABLE and GMEM_SHARE, BufLen);
  Buf := GlobalLock(hBuf);
  with BufHead do begin
    lpData := Buf;
    dwBufferLength := BufLen;
    dwFlags := WHDR_BEGINLOOP;
  end;
  WaveInPrepareHeader(WaveIn, Addr(BufHead), sizeof(BufHead));
  WaveInAddBuffer(WaveIn, addr(BufHead), sizeof(BufHead));
  GetMem(p, BufSize * sizeof(TPoint));
  GetMem(p2, BufSize * sizeof(TPoint));

  stop := true;
  WaveInStart(WaveIn);
  StartTime := GetTickCount;
end;

//关闭音频捕捉
procedure TSoundCap.CloseCapture;
begin
  if stop = false then Exit;
  stop := false;
  while not stop do Application.ProcessMessages;
  //while not stop do sleep
  stop := false;
  WaveInReset(WaveIn);
  WaveInUnPrepareHeader(WaveIn, addr(BufHead), sizeof(BufHead));
  WaveInClose(WaveIn);
  GlobalUnlock(hBuf);
  GlobalFree(hBuf);
  FreeMem(p, BufSize * sizeof(TPoint));
  FreeMem(p2, BufSize * sizeof(TPoint));
end;

//开始监视捕捉, 并显示时间
procedure TSoundCap.StartCap;
begin
  isCapture := true;
  StartTime := GetTickCount;
end;

//停止监视音频捕捉
procedure TSoundCap.StopCap;
begin
  isCapture := false;
end;

end.

具体调用:

  SoundCap := TSoundCap.Create(self.Handle);
  SoundCap.OnShowProgress := OnSoundPosition;
  SoundCap.OnShowTime := OnShowTime;
  SoundCap.OnCapture := OnCapture;
 
 
  SoundCap.OpenCapture(MainForm.Handle);

  ..
  SoundCap.CloseCapture

 
 2006-5-16 9:53:00    G729音频编码,从vc翻译过来,测试通过//------------------------------------------------------
// 功  能: 音频压缩  压缩比 16:1
// 方  法: 采集: PCM(8000kHZ,16-bit,单声道 15kb/s)
//         编码:  G729编码 1K/s
//         播放: PCM(8000kHZ,16-bit,单声道 15kb/s)
// 函  数: 编码: EncodeAudioData
//         解码: DecodeAudioData
// 制作人: 吴春华
// 时  间: 2006-05-15
// 版  本:1.0
//------------------------------------------------------
unit uG729;

interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

const
  L_FRAME_COMPRESSED = 10 ;
  L_FRAME            = 80 ;
  SIZE_AUDIO_FRAME   = 960 ;
  SIZE_AUDIO_PACKED  = 60 ;
  procedure g729a_init_encoder();stdcall external 'G729.dll';
  procedure g729a_encoder(speech: Psmallint; bitstream: PshortInt);stdcall external 'G729.dll';
  procedure g729a_init_decoder();stdcall external 'G729.dll';
  procedure g729a_decoder(bitstream: PshortInt; synth_short: Psmallint; bfi:integer);stdcall external 'G729.dll';
  procedure initCoder ;
  function EncodeAudioData(indata: array of shortInt; len: integer; var outdata: array of shortInt):boolean;
  function DecodeAudioData(indata: array of shortint; len: integer; var outdata: array of shortint): boolean;
implementation

procedure initCoder ;
begin
  g729a_init_encoder ;
  g729a_init_decoder ;
end;

function EncodeAudioData(indata: array of shortInt; len: integer;var outdata: array of shortInt):boolean;
var
  bRet: boolean;
  pin, pOut : PshortInt ;
begin
  bRet := false ;
  pin := PshortInt(@indata);
  pOut := pShortint(@outdata);
 g729a_encoder( Psmallint(pin),PshortInt(pout));
  inc(pin, 160);
  inc(pout, 10);
 g729a_encoder( Psmallint(pin), PshortInt(pout));
  inc(pin, 160);
  inc(pout, 10);
 g729a_encoder( Psmallint(pin), PshortInt(pout));
  inc(pin, 160);
  inc(pout, 10);
 g729a_encoder( Psmallint(pin), PshortInt(pout));
  inc(pin, 160);
  inc(pout, 10);
 g729a_encoder( Psmallint(pin), PshortInt(pout));
  inc(pin, 160);
  inc(pout, 10);
 g729a_encoder( Psmallint(pin), PshortInt(pout));
 bRet :=TRUE;
 result := bRet;
end;

function DecodeAudioData(indata: array of shortint; len:integer;var outdata: array of shortint): boolean;
var
  bRet: Boolean;
  pin, pOut : PshortInt ;
begin
 bRet := FALSE ;
  pIn := PshortInt(@indata) ;
  Pout :=pshortInt(@outData) ;
 g729a_decoder(pshortInt(pin),psmallInt(pout),0);
  inc(pin, 10) ;
  inc(pout, 160);
 g729a_decoder(pshortInt(pin),psmallInt(pout),0);
  inc(pin, 10) ;
  inc(pout, 160);
 g729a_decoder(pshortInt(pin),psmallInt(pout),0);
  inc(pin, 10) ;
  inc(pout, 160);
 g729a_decoder(pshortInt(pin),psmallInt(pout),0);
  inc(pin, 10) ;
  inc(pout, 160);
  g729a_decoder(pshortInt(pin),psmallInt(pout),0);
  inc(pin, 10) ;
  inc(pout, 160);
 g729a_decoder(pshortInt(pin),psmallInt(pout),0);
 bRet := TRUE;
  result := bRet ;
end;

 

end.

 
 2006-5-16 10:59:20    转抄//***********************************************************************//
//                                                                       //
//   画放音时的动态波形                                                  //
//   参数:                                                               //
//       Buf            : 音频数据指针                                   //
//       Length         : 音频数据的长度                                 //
//       DesCanvas      : 用来显示波形的目标画布                         //
//       DH, DW         : 目标画布工作区的高度与宽度                     //
//       Min, Max       : 音频数据的最小值与最大值                       //
//       DrawLineColor  : 画波形的颜色                                   //
//       DrawBackColor  : 画波形的背景颜色                               //
//       StartPoi       : 开始画波形的位置                               //
//       DrawLength     : 要画的波形的数据的长度                         //
//   返回值: 无                                                          //
//                                                                       //
//***********************************************************************//
procedure HawDrawWave(Buf: PChar; Length: LongInt; DesCanvas: TCanvas;
         DH, DW: SmallInt; Min, Max: LongInt; DrawLineColor, DrawBackColor: TColor;
         StartPoi: LongInt = 0; DrawLength: LongInt = 0);
Var
  i: LongInt;
  Y: SmallInt;
  DesBitMap: TBitMap;
begin
 DesBitMap := TBitMap.Create;

 with DesBitMap do     //初始化图像对像
 begin
    Width := DW;
    Height := DH;
    Canvas.Brush.Color := DrawBackColor;
    Canvas.Brush.Style := bsSolid;
    Canvas.Pen.Color := DrawLineColor;
    Canvas.Pen.Mode := pmCopy;
    Canvas.FillRect(Rect(0, 0, DW, DH));
    Canvas.MoveTo(0, DH DIV 2);
    Canvas.LineTo(DW, DH DIV 2);
 end;

 if ((Length = 0) or (Buf = NIL)) then
 begin
    BitBlt(DesCanvas.Handle, 0, 0, DW, DH, DesBitMap.Canvas.Handle, 0, 0, SRCCOPY);
    Exit;
 end;

 if (StartPoi MOD 2) = 1 then
    StartPoi := StartPoi + 1;

 if StartPoi &gt;= Length then
    StartPoi := 2;

 if DrawLength div 2 &gt; DW then         //开始处
    DrawLength := DW * 2;

 if (StartPoi + DrawLength) &gt; Length then
    DrawLength := Length - StartPoi;

 if DrawLength &lt;= 0 then
    DrawLength := DW * 2;
                                           
 Max := Max - Min;
 for i := 0 to (DrawLength div 2 -1) do
 begin
    if Max &lt;&gt; 0 then
       Y := Abs(PCMInt(PChar(Buf) + StartPoi + i * 2)^ - Min) * DH div Max
    else
       Y := 0;

       Y := ABS(DH DIV 2 - Y);

       if Y &gt;= (DH DIV 2) then
          continue;

       //画波形
       DesBitMap.Canvas.MoveTo(i, DH DIV 2 - Y);
       DesBitMap.Canvas.LineTo(i, DH DIV 2 + Y);

    if i &gt; DW then break;
 end;
 //复制图像
 BitBlt(DesCanvas.Handle, 0, 0, DW, DH, DesBitMap.Canvas.Handle, 0, 0, SRCCOPY);
 DesBitMap.Free;
end;

 
来自: yostgxf, 时间: 2005-01-18 21:52:21, ID: 2969407 
录音时的图形

//***********************************************************************//
//                                                                       //
//   画局部音频数据的波形                                                //
//   参数:                                                               //
//       Flag           : 波形显示周期                                   //
//       Buf            : 音频数据                                       //
//       Length         : 音频数据的长度                                 //
//       DesCanvas      : 要显示波形的目标画布                           //
//       DH, DW         : 目标画布的工作区域的高度与宽度                 //
//       DesBitMap      : 画波形时用的非可视源位图对像                   //
//       DrawLineColor  : 画波形的颜色                                   //
//       DrawBackColor  : 画波形的背景颜色                               //
//       Draw           : 是否画波形                                     //
//   返回值: 无                                                          //
//                                                                       //
//***********************************************************************//
procedure DrawPartWave(const Flag: Integer; Buf: PChar; Length: LongInt;
         DesCanvas: TCanvas; DH, DW: SmallInt; DesBitMap: TBitMap;
         DrawLineColor, DrawBackColor: TColor; Draw: Boolean = True);
var
  i, j, k, lmax, lmin: LongInt;
  Max, Min: LongInt;
  X, Y: SmallInt;
begin
 with DesBitMap do     //初始化图像参数
 begin
    Width := DW;
    Height := DH;
    Canvas.Brush.Color := DrawBackColor;
    Canvas.Brush.Style := bsSolid;
    Canvas.Pen.Color := DrawLineColor;
    Canvas.Pen.Mode := pmCopy;
    Canvas.FillRect(Rect(0, 0, DW, DH));
 end;

 if ((Length = 0) Or (Buf = NIL)) then
 begin //清除
    BitBlt(DesCanvas.Handle, 0, 0, DW, DH, DesBitMap.Canvas.Handle, 0, 0, SRCCOPY);
    Exit;
 end;
 Max := -32768;
 Min := 32767;
 for i := 0 to (Length div 2 -1 ) do   //取到最小值与最大值
 begin
    j := PCMInt(PChar(Buf) + i * 2)^;
    if j &gt; Max then Max := j;
    if j &lt; Min then Min := j;
 end;
 DrawMin := Min;
 DrawMax := Max;

 if Not Draw then
 begin
    Exit;
 end;

 Max := Max - Min;     //最大振幅
 DesBitMap.Canvas.MoveTo(0, DH div 2);
 j := 0;
 X := 0;
 lmax := 0;
 lmin := 32767;
 for i := 0 to ((Length) div 2 -1) do
 begin
    if j &lt; (Flag - 1) then     //如果是在一个周期内
    begin
       INC(j);
    end
    else begin
      j := 0;
      X := X + 1;
      lmax := 0;
      lmin := 32767;
    end;
    if Max &lt;&gt; 0 then           //取音频数据转换在整数
       Y := Abs(PCMInt(PChar(buf) + i * 2)^ - Min) * DH div Max
    else
       Y := DH div 2;
    k := 0;
    if Y &gt; lmax then
    begin
       lmax := Y;
       k := 1;
    end;
    if Y &lt; lmin then
    begin
       lmin := Y;
       k := 1;
    end;
    if k = 1 then
       DesBitMap.Canvas.LineTo(X, Y);  //画线
    if X &gt; DW then break;
 end;
 //图像复制                                                             拷贝
 BitBlt(DesCanvas.Handle, 0, 0, DW, DH, DesBitMap.Canvas.Handle, 0, 0, SRCCOPY);
end;

 

 
 2006-5-17 14:56:18    G729编码修改修改两个函数 ,编码输入和解码输出的数组类型改为smallint
function EncodeAudioData(indata: array of smallint; len: integer; var outdata:  
    array of shortInt):boolean;
function DecodeAudioData(indata: array of shortint; len: integer; var outdata:
    array of smallint): boolean;

 

【上篇】
【下篇】

抱歉!评论已关闭.