我利用delphi语音写的实现语音采集、压缩和传送的一个程序,控件用的是clientsocket和serversocket。
在采集音频信号时,有的不理解,不知道怎么理解,希望知道的帮帮忙。
下面是waveInOpen()函数和参数的解释。
//声明:
waveInOpen(
lphWaveIn: PHWAVEIN; {用于返回设备句柄的指针; 如果 dwFlags=WAVE_FORMAT_QUERY, 这里应是 nil}
uDeviceID: UINT; {设备ID; 可以指定为: WAVE_MAPPER, 这样函数会根据给定的波形格式选择合适的设备}
lpFormatEx: PWaveFormatEx; {TWaveFormat 结构的指针; TWaveFormat 包含要申请的波形格式}
dwCallback: DWORD {回调函数地址或窗口句柄; 若不使用回调机制, 设为 nil}
dwInstance: DWORD {给回调函数的实例数据; 不用于窗口}
dwFlags: DWORD {打开选项}
): MMRESULT; {成功返回 0; 可能的错误值见下:}
MMSYSERR_BADDEVICEID = 2; {设备ID超界}
MMSYSERR_ALLOCATED = 4; {指定的资源已被分配}
MMSYSERR_NODRIVER = 6; {没有安装驱动程序}
MMSYSERR_NOMEM = 7; {不能分配或锁定内存}
WAVERR_BADFORMAT = 32; {设备不支持请求的波形格式}
//TWaveFormatEx 结构:
TWaveFormatEx = packed record
wFormatTag: Word; {指定格式类型; 默认 WAVE_FORMAT_PCM = 1;}
nChannels: Word; {指出波形数据的声道数; 单声道为 1, 立体声为 2}
nSamplesPerSec: DWORD; {指定采样频率(每秒的样本数)}
nAvgBytesPerSec: DWORD; {指定数据传输的传输速率(每秒的字节数)}
nBlockAlign: Word; {指定块对齐(每个样本的字节数), 块对齐是数据的最小单位}
wBitsPerSample: Word; {采样大小(字节), 每个样本的量化位数}
cbSize: Word; {附加信息的字节大小}
end;
{16 位立体声 PCM 的块对齐是 4 字节(每个样本2字节, 2个通道)}
//打开选项 dwFlags 的可选值:
WAVE_FORMAT_QUERY = $0001; {只是判断设备是否支持给定的格式, 并不打开}
WAVE_ALLOWSYNC = $0002; {当是同步设备时必须指定}
CALLBACK_WINDOW = $00010000; {当 dwCallback 是窗口句柄时指定}
CALLBACK_FUNCTION = $00030000; {当 dwCallback 是函数指针时指定}
//如果选择窗口接受回调信息, 可能会发送到窗口的消息有:
MM_WIM_OPEN = $3BE;
MM_WIM_CLOSE = $3BF;
MM_WIM_DATA = $3C0;
//如果选择函数接受回调信息, 可能会发送给函数的消息有:
WIM_OPEN = MM_WIM_OPEN;
WIM_CLOSE = MM_WIM_CLOSE;
WIM_DATA = MM_WIM_DATA;
我的录音代码如下:
var
// fc:PACMFORMATCHOOSEA; //音频格式选择
i, j, MaxSizeFormat : integer ;
memBlock:PmemBlock; // PmemBlock数组类型,缓冲区大小
// Rec : longint; //
Header:pwavehdr;
begin
//-------------------------开始语音通话前音频设备的准备工作--------------------------------------------
//设置音频输入设备采集信号时的格式
with WaveFormat^ do
begin
//设置音频输入设备(如麦克风)以什么样的采样率、通道来采集音频信号
//人耳一般8位,11.025KHZ的采样率就可以很好的还原声音了 。。
WFormatTag :=WAVE_FORMAT_PCM; //PCM format - the only option!
NChannels := 1; //通道 Mono,2:stereo 立体声
NSamplesPerSec := 11025 ; //44.1kHz 采样频率(8.0 kHz, 11.025 kHz, 22.05 kHz)
NBlockAlign := 1; //每个采样点所需总字节数,NBlockAlign表示音频处理时的最小单位,nBlockAlign=wBitsPerSample*nChannels/8 PCM非压缩格式
NAvgBytesPerSec:= 11025 ; //指定数据传输的传输速率,等于nChannels*nSamplesPerSec*wBitsPerSample/8
wBitsPerSample := 8 ; //每个采样值的位数,一般为8或者16 bits in byte
cbSize :=0;
//cbSize表示该MAVEFORMTEX在标准的头部后还有多少字节数,对于PCM格式为0或者不检查,对于其他格式则有特点的参数
end;
//------------------源格式、目标格式的设置 ------------------------
sourceFormat := new(PWAVEFORMATEX) ;
destFormat := new(PWAVEFORMATEX) ;
GetMem(sourceFormat, maxSize);
GetMem(destFormat, maxSize);
sourceFormat.wFormatTag := WAVE_FORMAT_PCM;
sourceFormat.nChannels := 1//声道数
sourceFormat.nSamplesPerSec := 11025; //样频率
sourceFormat.wBitsPerSample := 8;//速率
sourceFormat.cbSize := 0; //PCM格式可忽略,别的格式有指定的形式
sourceFormat.nBlockAlign :=wBitsPerSample*nChannels/8;
sourceFormat.nAvgBytesPerSec :=nChannels*nSamplesPerSec*wBitsPerSample/8 ;
dwSrcSamples:=sourceFormat^.wSamplesPerSec;
destFormat.wFormatTag := 0x0055; //MP3格式
destFormat.nChannels := 2;
destFormat.nSamplesPerSec := 11025;
destFormat.wBitsPerSample := 16;
destFormat.cbSize := 0; //附加信息字节的大小
destFormat.nBlockAlign := 4;
destFormat.nAvgBytesPerSec := 48000 * 4;
mshd := new(PHACMSTREAM);
//波形数据缓存区格式的设置
Header := New(pwavehdr) ; //波形数据缓冲区格式
memBlock := New(PmemBlock) ; //
with Header^ do
begin //数据音频快头的定义
lpData := Pointer(memBlock) ; //指向锁定数据缓冲区的指针
dwBufferLength := memBlockLength ; //数据缓冲区得大小
dwBytesRecorded := 0 ; //录音时指明数据缓冲区的数据量 ,已录音数据的大小
dwUser := 0 ; //用户数据
dwFlags := 0 ; //提供缓冲区信息的标志 ,缓冲区 使用的标志
dwLoops := 0 ; // 音频输出时,数据块循环播放的次数
end ;
//当前音频波形输入、输出设备数量
if WaveInGetNumDevs = 0 then //查看当前系统波形音频输入设备的数量
application.MessageBox('没有音频录入设备','错误',MB_OK ) ;
if WaveOutGetNumDevs = 0 then //查看当前系统波形音频输出设备的数量
application.MessageBox('没有音频输出设备','错误',MB_OK ) ; //application 来自forms
acmMetrics(0, ACM_METRIC_MAX_SIZE_FORMAT, MaxSizeFormat); // 获取缓冲区存置格式信息的大小
GetMem(waveformat,MaxSizeFormat); //waveformat 波形数据格式 getmem申请内存
// 打开声音输出设备 WAVE_MAPPER, 这样函数会根据给定的波形格式选择合适的设备
HwaveIn := new(pHwaveIn) ; //waveInOpen 为录音而打开一个波形输入设备
// waveformat指定以waveformat格式打开音频输入设备
i := WaveInOpen(HwaveIn, WAVE_MAPPER, waveformat, Handle, 0, callback_window) ;
if i <> 0 then
begin
application.MessageBox('声音输入设备打开失败', '错误', MB_OK) ;
exit;
end;
//生成10个缓冲区
for j := 0 to 10 do //缓冲区个数
begin
//装载 waveInPrepareHeader 为波形输入准备一个输入缓冲区
i := waveInPrepareHeader(HwaveIn^, header, sizeof(WaveHdr));
if i <> 0 then application.MessageBox('准备波形数据输入块失败', '错误', MB_OK) ;
i := waveInAddBuffer(HwaveIn^, header, sizeof(WaveHdr)) ; //添加一个输入用的数据缓冲区
if i <> 0 then application.MessageBox('装载波形数据输入块失败', '错误', MB_OK) ;
inc(in_count); //队列数 +1
end;
//最后开始记录 录音开始
i := waveInstart(HwaveIn^) ; //waveInStart 启动在指定的波形输入设备的输入 ,获取的数据流放哪儿了呢???
if i <> 0 then application.MessageBox('开始记录波形失败', '错误', MB_OK) ;
close_invoked:=false; //控制在WM_WIM_DATA事件中,准备缓存数据
close_complete:=false;
//waneInReset()停止录音
end;
在waveInopen()函数中,我指定了callback_window的窗口句柄,他有什么用啊??怎么实现连续录音的呢??