录音时回调函数中对缓冲区数据的处理,如何使用双缓冲,并将数据写入*.wav格式文件中

delphi_bestguy 2008-05-22 11:16:55
我写了一个用低级波形音频函数进行操作的录音程序,运行时,wav文件只写了文件头,并且进入死循环了.感觉是对双缓冲操作和将缓冲区数据写入wav文件时出了错.
刚开始学delphi,很多问题不懂,请各位高手帮忙看看如何解决!!!!!!!!
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,MMsystem;
type
//定义一个Wave文件头
TWaveHeader=record
rId:longint; //固定标记,值为"RIFF"
rLen:longint; //随后的字节数,值为(wSampleLength+36)
wId:longint; //固定标记,值为"WAVE"
fId:longint; //ckID值为"fmt "
fLen:longint; //nChunkSize Wave文件块的大小 16
wFormatTag:word; //音频数据的编码方式,此值为1,标书PCM方式
nChannels:word; //声道数
nSamplesPerSec:longint; //采样频率
nAvgBytesPerSec:longint; //每秒字节数
nBlockAlign:word; //一次输出的字节数 值为采样位数×声道数/8
wBitsPerSample:word; //采样位数,一般为16和8位
dId:longint; //固定标记,值位"data"
wSampleLength:longint; //采样数据长度,值为文件大小-文件头大小(44)
end;
TRecorder = class
private
{ Private declarations }
public
{ Public declarations }
FWaveFmt:TWaveFormatEx;//指向PCMWAVEFORMAT数据结构的指针,重新封装后包括PCMWAVEFORMAT和WAVEFORMAT
WaveHandle:HWaveIn;//设备句柄
WaveHdr1:PWAVEHDR; // 为采样数据分配缓冲空间 1
WaveHdr2:PWAVEHDR; // 为采样数据分配缓冲空间 2
WaveBuffer1:lpstr; //数据缓冲1
WaveBuffer2:lpstr; //数据缓冲2
Procedure CallBack(uMsg,dwInstance,dwParam1,dwParam2:DWORD);stdcall;
end;

TForm1 = class(TForm)
start: TButton;
stop: TButton;
initial: TButton;
close: TButton;
show: TLabel;
procedure startClick(Sender: TObject);
procedure stopClick(Sender: TObject);
procedure initialClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
//channelse为声道数,resolution为采样位数,rate为采样频率,fn为对应的文件名称
procedure CreateWave(channels:word;resolution:word;rate:longint;fn:string);
procedure closeClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
Recorder:TRecorder;
//定义一个缓冲控制变量
flag:integer;
implementation
{$R *.dfm}
Procedure TRecorder.CallBack(uMsg,dwInstance,dwParam1,dwParam2:DWORD);stdcall;//回调函数声明
var i,k:integer; //循环变量
SPByte:^Byte; //假设在打开设备时采用8位量化
SingleData:Integer;
fd:TFileStream; //保存结果
f:textfile;
begin
//******************************************//
case uMsg of //
MM_WIM_OPEN : //波形输入设备成功打开发回的消息
[b]//感觉是以下部分出了错[/b] MM_WIM_DATA : //一个缓冲区已满发回的消息处理,此处需要修改
begin
if(flag=0) then
begin
WaveInUnprepareHeader(Recorder.WaveHandle,Recorder.WaveHdr1,sizeof(TWAVEHDR));
WaveInPrepareHeader(Recorder.WaveHandle,Recorder.WaveHdr2,Sizeof(WAVEHDR));
WaveInAddBuffer(Recorder.WaveHandle,Recorder.WaveHdr2,Sizeof(WAVEHDR));
flag:=1;
end
else
begin
WaveInUnprepareHeader(Recorder.WaveHandle,Recorder.WaveHdr2,sizeof(TWAVEHDR));
WaveInPrepareHeader(Recorder.WaveHandle,Recorder.WaveHdr1,Sizeof(WAVEHDR));
WaveInAddBuffer(Recorder.WaveHandle,Recorder.WaveHdr1,Sizeof(WAVEHDR));
flag:=0;
end;
SPByte:=Pointer(dwParam1);
//////////////////////////////////////////////////
fd:=TFileStream.Create('C:\test.wav',fmCreate);
for i:=0 to 1023 do // Recorder.DataLength-1
begin
SingleData:=SPByte^;//通过SPByte来访问缓冲区的数据
// application.MessageBox(StrtoInt(SingleData),'');
/////////////////此处有内容省略
fd.Write(SingleData,sizeof(SingleData));
//write(f, SingleData);
Inc(SPByte);//Increments an ordinal value by one or N.
end;
//closefile(f);
fd.Free;
if(flag=1) then
begin
dispose(Recorder.WaveHdr1.lpData);
dispose(Recorder.WaveHdr1);
end
else
begin
dispose(Recorder.WaveHdr2.lpData);
dispose(Recorder.WaveHdr2);
end;
end;
MM_WIM_CLOSE : //波形输入设备关闭成功发回的消息
//释放内存
begin;
WaveInUnprepareHeader(Recorder.WaveHandle,Recorder.WaveHdr1,sizeof(TWAVEHDR));//解除置换保护
WaveInUnprepareHeader(Recorder.WaveHandle,Recorder.WaveHdr2,sizeof(TWAVEHDR));
GlobalFreePtr(Recorder.WaveBuffer1); //释放分配的内存
GlobalFreePtr(Recorder.WaveBuffer2); //释放分配的内存
application.MessageBox('录音结束,语音输入设备已经关闭!!!!!','Congratuations!',mb_OK);
end;
end;
end;
procedure TForm1.CreateWave(channels:word;resolution:word;rate:longint;fn:string);
var
wf : file of TWaveHeader;
wh : TWaveHeader;
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;
assignfile(wf,fn); {打开对应文件 }
rewrite(wf); {移动指针到文件头}
write(wf,wh);{写进文件头}
closefile(wf);{关闭文件}
end;
procedure TForm1.startClick(Sender: TObject);
begin
WaveInStart(Recorder.WaveHandle); //开始录音
//检验
if(WaveInStart(Recorder.WaveHandle)<>0) then application.MessageBox('Strart error/启动波形输入设备错

误','Error',mb_OK);
initial.Enabled:=FALSE;
stop.Enabled:=TRUE;
end;

procedure TForm1.stopClick(Sender: TObject);
begin
WaveInStop(Recorder.WaveHandle); //停止录音
WaveInReset(Recorder.WaveHandle); // 重置语音射入设备
//WaveInClose(Recorder.WaveHandle); // 关闭语音射入设备
initial.Enabled:=TRUE;
start.Enabled:=TRUE;
stop.Enabled:=FALSE;
close.Enabled:=TRUE;
end;

procedure TForm1.initialClick(Sender: TObject);
begin
CreateWave(1,8,11025,'C:\test.wav');// 创建文件头
flag:=0;
//设置我们需要的格式
Recorder:=TRecorder.Create;
Recorder.FWaveFmt.wFormatTag:=WAVE_FORMAT_PCM;
Recorder.FWaveFmt.nChannels:=1;
Recorder.FWaveFmt.wBitsPerSample:=8;
Recorder.FWaveFmt.nSamplesPerSec:=11025;
Recorder.FWaveFmt.nAvgBytesPerSec:=11025;
Recorder.FWaveFmt.nBlockAlign:=2;
WaveInOpen(@Recorder.WaveHandle,Wave_Mapper,(@Recorder.FWaveFmt),DWORD(@TRecorder.CallBack),DWORD
(@Recorder),CALLBACK_FUNCTION + WAVE_ALLOWSYNC); //打开波形输入设备//*********************//
//为采样分配缓冲空间
Recorder.WaveHdr1:=GlobalAllocPtr(GHND or GMEM_SHARE,Sizeof(TWAVEHDR));//开辟一段内存空间
Recorder.WaveBuffer1:=GlobalAllocPtr(GHND or GMEM_SHARE,1024);
Recorder.WaveHdr1.lpData:=Recorder.WaveBuffer1;
Recorder.WaveHdr1.dwBufferLength:=1024;

Recorder.WaveHdr2:=GlobalAllocPtr(GHND or GMEM_SHARE,Sizeof(TWAVEHDR));//开辟一段内存空间
Recorder.WaveBuffer2:=GlobalAllocPtr(GHND or GMEM_SHARE,1024);//为Buffer1分配内存空间
Recorder.WaveHdr2.lpData:=Recorder.WaveBuffer2;//
Recorder.WaveHdr2.dwBufferLength:=1024;

WaveInPrepareHeader(Recorder.WaveHandle,Recorder.WaveHdr1,Sizeof(WAVEHDR));
WaveInPrepareHeader(Recorder.WaveHandle,Recorder.WaveHdr2,Sizeof(WAVEHDR));
WaveInAddBuffer(Recorder.WaveHandle,Recorder.WaveHdr1,Sizeof(WAVEHDR));//将缓冲区送往波形输入设备
WaveInAddBuffer(Recorder.WaveHandle,Recorder.WaveHdr2,Sizeof(WAVEHDR));
start.Enabled:=TRUE;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
//判断是否有声卡
if (WaveInGetNumDevs()=0) then application.MessageBox('There is no recording sound cadd in your
computer!','Error',mb_OK);
end;

procedure TForm1.closeClick(Sender: TObject);
begin
waveInStop(Recorder.WaveHandle);
waveInClose(Recorder.WaveHandle);

end;

end.
...全文
318 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

1,183

社区成员

发帖
与我相关
我的任务
社区描述
Delphi GAME,图形处理/多媒体
社区管理员
  • GAME,图形处理/多媒体社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧