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
发表评语»»»
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 >= Length then
StartPoi := 2;
if DrawLength div 2 > DW then //开始处
DrawLength := DW * 2;
if (StartPoi + DrawLength) > Length then
DrawLength := Length - StartPoi;
if DrawLength <= 0 then
DrawLength := DW * 2;
Max := Max - Min;
for i := 0 to (DrawLength div 2 -1) do
begin
if Max <> 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 >= (DH DIV 2) then
continue;
//画波形
DesBitMap.Canvas.MoveTo(i, DH DIV 2 - Y);
DesBitMap.Canvas.LineTo(i, DH DIV 2 + Y);
if i > 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 > Max then Max := j;
if j < 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 < (Flag - 1) then //如果是在一个周期内
begin
INC(j);
end
else begin
j := 0;
X := X + 1;
lmax := 0;
lmin := 32767;
end;
if Max <> 0 then //取音频数据转换在整数
Y := Abs(PCMInt(PChar(buf) + i * 2)^ - Min) * DH div Max
else
Y := DH div 2;
k := 0;
if Y > lmax then
begin
lmax := Y;
k := 1;
end;
if Y < lmin then
begin
lmin := Y;
k := 1;
end;
if k = 1 then
DesBitMap.Canvas.LineTo(X, Y); //画线
if X > 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;