怎样判断麦克风是否有信号正在输入? (200分)

  • 主题发起人 主题发起人 zhjie
  • 开始时间 开始时间
Z

zhjie

Unregistered / Unconfirmed
GUEST, unregistred user!
怎样实现以下功能:
if 麦克风有声音 then
屏幕显示“录音”
if 麦克风2秒没有声音 then
屏幕显示“等待”
谢谢!!
 
你可以开始录音,如果发现WAVE文件的波形震动不大,并超过2两秒钟,就——if 麦克风2秒没有声音 then
屏幕显示“等待”
 
谢谢。
怎样发现“WAVE文件的波形震动不大”?用什么控件和函数?
 
自己写程序就可以了,给以贴一段程序看看:
//***********************************************************************//
// //
// 开始录音 //
// 参数: 无 //
// 返回值: 无 //
// //
//***********************************************************************//

procedure TCMRecordWave.Start;
var
RecordWaveBuf: PChar;
// 音频数据保存的缓存
RecordHDr: TWAVEHDR;
// 音频信息头
tm: TMMTime;
// 已录音多长时间
Diff: Longint;
// 音频数据的长度
TempFile: Integer;
// 临时文件句柄
// Flag: Integer;
// 波形显示周期
begin

if not ((Self.NowRecord = CRNONE) or (Self.NowRecord = CRSTOPING)) then

Exit;
Self.FNowRecord := CRRECORDING;
// 正在录音
TempFile := FileCreate(Self.TempFileName);
// 创建一个临时文件用于保存录音数据

//设置音频文件头
Self.TRecordHdr.wFormatTag := WAVE_FORM_FORMAT_TAG;
// 格式类型
Self.TRecordHdr.nChannels := WAVE_FORM_CHANNELS;
// 声道数据
Self.TRecordHdr.nSamplesPerSec := WAVE_FORM_SAMPLES_PER_SEC;
// 采样频率
Self.TRecordHdr.nAvgBytesPerSec := WAVE_FORM_AVG_BYTE_PER_SEC;
// 平均数据传输率
Self.TRecordHdr.wBitsPerSample := WAVE_FORM_BITS_PER_SAMPLE;
// 采样数据的大小
Self.TRecordHdr.nBlockAlign := WAVE_FORM_BLOCK_ALIGN;
// 块对齐方式
Self.TRecordHdr.cbSize := WAVE_FORM_CBSIZE;
// 加在本结构后的格式数据的大小

//打开音频输入设备
WaveInOpen(@Self.hwi, WAVE_MAPPER, @Self.TRecordHdr, 0, 0, CALLBACK_NULL);
// 定义要录制的格式
try
//开辟内存
RecordWaveBuf := PChar(GlobalAllocPtr(GMEM_MOVEABLE or GMEM_SHARE,
WAVE_REC_BUFFER_LENGTH));

try // 设置信息头
RecordHDr.lpData := RecordWaveBuf;
RecordHDr.dwBufferLength := WAVE_REC_BUFFER_LENGTH;
RecordHDr.dwFlags := 0;
// 生成信息头(prepares a buffer for waveform-audio input)
WaveInPrepareHeader(Self.hwi, @RecordHDr, SizeOf(TWAVEHDR));
// 增加数据缓冲(sends an input buffer to the given waveform-audio input device)
WaveInAddBuffer(Self.hwi, @RecordHDr, SizeOf(TWAVEHDR));

WaveInStart(Self.hwi);
// 开始录音
Self.FileSize := 0;
// 音频数据长度
while Self.NowRecord <> CRSTOPINGdo

begin
// 没有停止
Application.ProcessMessages;
// 处理消息
if ((RecordHDr.dwFlags and WHDR_DONE) <> 0) then
// 数据缓冲已填满
begin

tm.wType := TIME_BYTES;
WaveInGetPosition(Self.hwi, @tm, SizeOf(TMMTime));
// 取当前播放位置
Diff := Longint(tm.cb) - Self.FileSize;
// 数据长度
Self.FileSize := Longint(tm.cb);
{ Flag := Diff div 2 div Self.FDrawWave.ClientWidth + 1;
// 波形显示周期
if Flag <= 0 then

Flag := 1;
if (Self.DrawWave <> nil) and (Self.DesBMP <> nil) then
// 画波形
DrawPartWave(Flag, RecordWaveBuf, Diff, Self.FDrawWave.Canvas,
Self.FDrawWave.ClientHeight, Self.FDrawWave.ClientWidth,
Self.FDesBMP, Self.FDrawLineColor, Self.FDrawBackColor);
} FileWrite(TempFile, RecordWaveBuf^, Diff);
// 写入临时文件中
waveInAddBuffer(Self.hwi, @RecordHDr, SizeOf(TWAVEHDR));
// 增加一 数据缓冲区
end;

end;

// 再次保存数据
tm.wType := TIME_BYTES;
WaveInGetPosition(Self.hwi, @tm, SizeOf(TMMTime));
// 取当前播放位置
Diff := Longint(tm.cb) - Self.FileSize;
// 数据长度
Self.FileSize := Longint(tm.cb);
FileWrite(TempFile, RecordWaveBuf^, Diff);
// 写入临时文件中
// waveInAddBuffer(Self.hwi, @RecordHDr, SizeOf(TWAVEHDR));
// 增加一 数据缓冲区

WaveInReset(Self.hwi);
// 停止录音
WaveInUnPrepareHeader(Self.hwi, @RecordHDr, SizeOf(TWAVEHDR));
// 清除信息头
finally
GloBalFreePtr(RecordWaveBuf);
// 释放内存
FileClose(TempFile);
// 关闭文件
end;

finally
WaveInClose(Self.hwi);
// 关闭音频输入设备
Self.FNowRecord := CRSTOPING;
end;


if FileExists(Self.FWaveFileName) then

DeleteFile(Self.FWaveFileName);
// 删除临时音频文件

// 保存为音频文件
if Self.FSaveFileName = '' then

Wave_SaveFile(Self.FWaveFileName, Self.TempFileName, Self.FileSize,
Self.TRecordHdr, 0, CS_SAVE_RECORD)
else

Wave_SaveFile(Self.FSaveFileName, Self.TempFileName, Self.FileSize,
Self.TRecordHdr, 0, CS_SAVE_RECORD);
Self.FNowRecord := CRNONE;
end;
 
这一段就是得到波形:
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 DesBitMapdo
//初始化图像参数
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;

 
谢谢!!
请问以上代码需要什么运行环境?
我的系统是delphi5/6的初始环境,没有安装其他控件,运行以上代码,显示找不到 TWAVEHDR 和 TMMTime。
var
RecordHDr: TWAVEHDR;
// 音频信息头
tm: TMMTime;
// 已录音多长时间
 
你USER MMsystem就可以了
DELPHI6平台,没有任何第三方组件。
 
十分谢谢!!
您的效率惊人!!佩服!容我调试看看!
感谢您贴个完整的unit。
谢谢!!
 
:),完整的UNIT并没有贴,我的那两个函数的后一个是将WAVE的波形花在PaintBox上,你可以试一试。
 
procedure TCMRecordWave.Start;
中的 TCMRecordWave属于什么类?
能否贴上完整的单元?我的水平太菜了。谢谢!!
 
后退
顶部