怎么录音?请不吝赐教(yzhshi come!) (100分)

  • 主题发起人 主题发起人 D影子D
  • 开始时间 开始时间
D

D影子D

Unregistered / Unconfirmed
GUEST, unregistred user!
用mediaplayer控件怎么做到?
何时开始录制?何时结束?
能保存为文件吗?
具体怎么做?
有源码吗?
 
为什么在括号里面加上这句话,俺没用过呀。
看来又得努力去看了。
让我研究研究了。。。
★★★等待中★★★
 
哈哈,工夫不负有心人,找到了,jingtao写的!

http://www.5xsoft.com/data/200107/2008152201.htm

如何用Delphi制作录音程序
[ 作者: 陈经韬 添加时间: 2001-7-20 8:16:31 ]

Delphi是Inprise(前Borland)公司的优秀的可视化编程工具,它自带的Mediaplayer控件是开发多媒体的利器。用它
几分钟就可以做出一个象解霸一样可以播放多媒体文件的程序来。但可能很少人知道,用它也可以做一个录音程序。
运行Delphi,在System页拖一个Mediaplayer控件到窗体上,默认名为Mediaplayer1。由于我们的程序是采用自己的
按钮,所以将Mediaplayer1的Visible属性设置为False,其它属性保持默认值。再放两个按钮Button1和Button2。
Button1的属性Name改为BtStart,Caption改为"开始录音", Button2的属性Name改为BtStop,Caption改为"停止录音",
Enabled属性改为False。然后切换窗口到代码窗口,开始书写代码。
程序中,我们定义了一个Wav文件的文件头格式,录音时先创建一个只有文件头的Wav文件,然后将Mediaplayer1录制
下来的声音写进文件。其中CreateWav过程的几个参数意义如下:第一个channels代表声道,取1时代表单声,取2时代表
立体声。resolution也只有两个值可以选择,取8时代表8位声音,取16时代表16位声音,rate则代表声音频率,
如11025,22050, 44100。值越大则声音越清晰,当然,所录制的文件也越大。最后一个参数则代表对应的文件名称了。
所以CreateWav可以有以下形式:
CreateWav(1,8,11025,'C:/abc.wav');//在C盘根目录下创建一个8位单声道频率为11025的名为abc.wav的Wav文件
CreateWav(2,16,44100,'C:/abc.wav');//在C盘根目录下创建一个16位立体声道频率为44100的名为abc.wav的Wav文件

外国一个很出名的用Delphi编写的远程控制软件Netbus有一个声音监听功能,就是用本文的方法写的。它先把对方
的声音录制下来,然后传送回来,达到监听对方的目的。当然,前提是对方必须安装有话筒,否则监听到的是对方播放
的声音(如打开解霸或者Readplay播放,运行本程序,就可以把播放的声音录制下来了)。
实际上,现在的网络声音传播技术已经发展到一定阶段,语音对讲和IP电话等也开始成熟。不过它们采用的是VOX格式
或者ACM格式,具体代码可以在我的主页http://Lovejingtao.126.com下载。但如果对VOX或者ACM格式不熟悉的朋友,也
可以用本文的方法来制作自己的“录音机”。至于如何调用系统自带的avifil32.dll来进行网络视频播放,在有机会时再
跟大家交流吧。
本程序在Pwin98+Delphi5下通过。

unit Unit1;

interface

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

type
TWavHeader = record //定义一个Wav文件头格式
rId : longint;

rLen : longint;

wId : longint;

fId : longint;

fLen : longint;

wFormatTag : word;

nChannels : word;

nSamplesPerSec : longint;

nAvgBytesPerSec : longint;

nBlockAlign : word;

wBitsPerSample : word;

dId : longint;

wSampleLength : longint;

end;

TForm1 = class(TForm)
MediaPlayer1: TMediaPlayer;
BtStart: TButton;
BtStop: TButton;
procedure CreateWav(channels : word;
resolution : word;
rate : longint;
fn : string);//自定义写一个Wav文件头过程
procedure BtStartClick(Sender: TObject);
procedure BtStopClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;


var
Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.CreateWav( channels : word;
{ 1(单声)或者2(立体声) }
resolution : word;
{ 8或者16,代表8位或16位声音 }
rate : longint;
{ 声音频率,如11025,22050, 44100}
fn : string { 对应的文件名称 } );
var
wf : file of TWavHeader;
wh : TWavHeader;
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.BtStartClick(Sender: TObject);
begin

try
//在程序当前目录下创建一个Wav文件Temp.wav
CreateWav(1, 8, 11025, (ExtractFilePath(Application.ExeName)+ 'Temp.wav'));
MediaPlayer1.DeviceType := dtAutoSelect;
MediaPlayer1.FileName := (ExtractFilePath(Application.ExeName)+ 'Temp.wav');
MediaPlayer1.Open;
MediaPlayer1.StartRecording;
BtStart.Enabled:=false;
BtStop.Enabled:=true;
except
BtStart.Enabled:=True;
BtStop.Enabled:=false;
Application.MessageBox('媒体设备初始化失败!','错误',MB_ICONERROR+MB_OK);
end;

end;


procedure TForm1.BtStopClick(Sender: TObject);
begin

try
MediaPlayer1.Stop;
MediaPlayer1.Save;
MediaPlayer1.Close;
Application.MessageBox('声音录制完毕!','信息',MB_ICONINFORMATION+MB_OK);
BtStart.Enabled:=True;
BtStop.Enabled:=false;
except
Application.MessageBox('保存声音文件出错!','错误',MB_ICONERROR+MB_OK);
BtStart.Enabled:=True;
BtStop.Enabled:=false;
end;

end;

end.


补充:1、录制的文件播放时可能要把音频属性的Wav调大。
2、如果系统安装了其它一些音频驱动程序,则可能录制的Wav文件大小为零,但会同时生成一个TMP结尾的
文件,将其扩展名改为Wav就是录制的声音文件。但这种情况很少发生。(机会几乎为零^-^)
3、本程序在运行解霸和Replayer下录制声音通过。
 
我这里给你贴一个我写的程序段,看不明白就算了。

// 全局变量
var
BufferFinished : boolean;
// indicates current record buffer is full
.
UserStopRecord: boolean;

Recording: boolean;


WaveInHandle: HWaveIn;


CurrentUsingBuffer: integer;

WaveInHeader1: TWaveHdr;

WaveInHeader2: TWaveHdr;


RecordBufferSize: integer;

TotalRecordedSize: DWORD;



//进行录音
procedure TDlgRecord.BtnStartClick(Sender: TObject);

var
TempInt, TempCode: integer;

TempFileName: string;


MMR: MMResult;

MyWaveFormat: TWaveFormatEx;


begin

PrgsBarSpace.Position := 0;

Recording := false;

OldDiskFree := DiskFree (RecordDrive);

with RecordWaveFormatdo

begin

if RdoBtnMono.Checked = true then

Channels := 1
else

Channels := 2;

if RdoBtn8Bit.Checked = true then

BitsPerSample := 8
else

BitsPerSample := 16;

Val (EditFrequency.Text, TempInt, TempCode);

if TempCode <> 0 then

begin

Application.MessageBox ('无效数值', '错误', MB_Ok);

exit;

end
else
if TempInt > 48000 then

begin

Application.MessageBox('不能大于48000赫兹', '错误', MB_Ok);

exit;

end
else

begin

SamplesPerSecond := TempInt;

end;


BytesPerSecond := SamplesPerSecond * Channels * BitsPerSample div
8;

BlockAlign := BitsPerSample * Channels div 8

end;



TempFileName := TempFileNameGenerator (Self.TempPath, 'WM_', 'TMP',
5);


AssignFile (RecordFile, TempFileName);

Rewrite (RecordFile, 1);

if IOResult <> 0 then

begin

Application.Messagebox ('无法创建暂时文件,请检查临时目录设定。',
'严重错误', MB_OK);

exit;

end;



RecordFileName := TempFileName;

RecordSuccess := false;
// 由于文件名已经改变,所以在这里修改该变量。


// Preparation jobs here
SttTextElapsedTime.Caption := '00:00:00';

ElapsedHours := 0;

ElapsedMinutes := 0;

ElapsedSeconds := 0;

CurrentUsingBuffer := 1;

TotalRecordedSize := 0;

BufferFinished := false;

UserStopRecord := false;

RecordBufferSize := RecordWaveFormat.BytesPerSecond * 2;
// for 2 se
conds
Buffer1 := nil;

Buffer2 := nil;


try
GetMem (Buffer1, RecordBufferSize);

except
Application.MessageBox ('内存不足,分配第一缓冲区失败。', '错误',
MB_OK);

end;



try
GetMem (Buffer2, RecordBufferSize);

except
Application.MessageBox ('内存不足,分配第二缓冲区失败。', '错误',
MB_OK);

end;



if (Buffer1 = nil) or (Buffer2 = nil) then

begin

CloseFile (RecordFile);

exit;

end;



MyWaveFormat.wFormatTag := WAVE_FORMAT_PCM;

MyWaveFormat.nChannels := RecordWaveFormat.Channels;

MyWaveFormat.nSamplesPerSec := RecordWaveFormat.SamplesPerSecond;

MyWaveFormat.nAvgBytesPerSec := RecordWaveFormat.BytesPerSecond;

MyWaveFormat.nBlockAlign := RecordWaveFormat.BlockAlign;

MyWaveFormat.wBitsPerSample := RecordWaveFormat.BitsPerSample;

MyWaveFormat.cbSize := 0;


MMR := waveInOpen (Addr (waveInHandle),
SelectedDevice,
Addr (MyWaveFormat),
DWORD (Addr (WaveInCallBack)),
0,
CALLBACK_FUNCTION);

if MMR <> MMSYSERR_NOERROR then

begin

FreeMem (Buffer1);
FreeMem (Buffer2);

RecordBufferSize := 0;

CloseFile (RecordFile);

Application.MessageBox ('无法打开输入设备,请检查设定。', '错误',
MB_OK);

exit;

end;



waveInHeader1.lpData := Buffer1;

waveInHeader1.dwBufferLength := RecordBufferSize;

waveInHeader1.dwBytesRecorded := 0;

waveInHeader1.dwUser := 0;
// 32 bits of user data
waveInHeader1.dwFlags := 0;

waveInHeader1.dwLoops := 0;

waveInHeader1.lpNext := nil;
// reserved;
must be zero
waveInHeader1.reserved := 0;
// reserved;
must be zero
MMR := waveInPrepareHeader (waveInHandle, Addr (waveInHeader1),
sizeof (waveInHeader1));

if MMR <> MMSYSERR_NOERROR then

begin

FreeMem (Buffer1);
FreeMem (Buffer2);

RecordBufferSize := 0;

CloseFile (RecordFile);

Application.MessageBox ('第一录音缓冲区准备出错。', '错误', MB_OK)
;

exit;

end;



waveInHeader2.lpData := Buffer2;

waveInHeader2.dwBufferLength := RecordBufferSize;

waveInHeader2.dwBytesRecorded := 0;

waveInHeader2.dwUser := 0;
// 32 bits of user data
waveInHeader2.dwFlags := 0;

waveInHeader2.dwLoops := 0;

waveInHeader2.lpNext := nil;
// reserved;
must be zero
waveInHeader2.reserved := 0;
// reserved;
must be zero

MMR := waveInPrepareHeader (waveInHandle, Addr (waveInHeader2),
sizeof (waveInHeader2));

if MMR <> MMSYSERR_NOERROR then

begin

waveInUnprepareHeader (waveInHandle, Addr (waveInHeader1), sizeof(
waveInHeader1));

FreeMem (Buffer1);
FreeMem (Buffer2);

RecordBufferSize := 0;

CloseFile (RecordFile);

Application.MessageBox ('第二录音缓冲区准备出错。', '错误', MB_OK)
;

exit;

end;



MMR := waveInAddBuffer (WaveInHandle, Addr (waveInHeader1), sizeof (
waveInHeader1));

if MMR <> MMSYSERR_NOERROR then

begin

waveInUnprepareHeader (waveInHandle, Addr (waveInHeader1), sizeof(
waveInHeader1));

waveInUnprepareHeader (waveInHandle, Addr (waveInHeader2), sizeof(
waveInHeader2));

FreeMem (Buffer1);
FreeMem (Buffer2);

RecordBufferSize := 0;

CloseFile (RecordFile);

Application.MessageBox ('添加第一缓冲区出错。', '错误', MB_OK);

exit;

end;



MMR := waveInAddBuffer (WaveInHandle, Addr (waveInHeader2), sizeof (
waveInHeader2));

if MMR <> MMSYSERR_NOERROR then

begin

waveInUnprepareHeader (waveInHandle, Addr (waveInHeader1), sizeof(
waveInHeader1));

waveInUnprepareHeader (waveInHandle, Addr (waveInHeader2), sizeof(
waveInHeader2));

FreeMem (Buffer1);
FreeMem (Buffer2);

RecordBufferSize := 0;

CloseFile (RecordFile);

Application.MessageBox ('添加第二缓冲区出错。', '错误', MB_OK);

exit;

end;




TimerRecording.Enabled := true;

// Record has begun.
Recording := true;


MMR := waveInStart (waveInHandle);

if MMR <> MMSYSERR_NOERROR then

begin

waveInUnprepareHeader (waveInHandle, Addr (waveInHeader1), sizeof(
waveInHeader1));

waveInUnprepareHeader (waveInHandle, Addr (waveInHeader2), sizeof(
waveInHeader2));

FreeMem (Buffer1);
FreeMem (Buffer2);

RecordBufferSize := 0;

CloseFile (RecordFile);

Recording := false;

TimerRecording.Enabled := false;

Application.MessageBox ('未能开始录音。', '错误', MB_OK);

exit;

end;



// 应该在这里开始创建线程.
// 需要传递参数: RecordFile, Buffer1, Buffer2,
with TMediaRecordThread.Create (Addr(RecordFile), Buffer1, Buffer2)
do
OnTerminate := ThreadRecordStop;


// disable/enable controls
BtnCancel.Enabled := false;

BtnStart.Enabled := false;

GrpBoxChannel.Enabled := false;

LBFrequency.Enabled := false;

EditFrequency.Enabled := false;

LstBoxFrequency.Enabled := false;

GrpBoxSample.Enabled := false;


BtnStop.Enabled := true;


end;


 
yzhshi不要介意嘛,又辛苦你了我也不好意思,但我实在没办法了!
minkerui:你发的虽然很怪但没有功劳也有苦劳啊!
谢谢你们![:)]
 
还有也要谢谢jingtao了!
[:)]
 
介意肯定不会,呵呵。只要我会的,我一定知无不言,言无不尽的。
 
后退
顶部