多媒体小问题赢高分:直接编程让声卡发出PC喇叭那样的声音(300分)

  • 主题发起人 主题发起人 avant
  • 开始时间 开始时间
A

avant

Unregistered / Unconfirmed
GUEST, unregistred user!
就是PC喇叭发出的那种“嘟嘟”“嘀嘀”的简单声音。
不要用wav文件来模拟的哟!
 
用sin(x*i)产生一序列,改变x来改变频率,然后把序列用waveoutbuffer来放出即可
 
老兄,我这方面不熟,能详细点儿吗?给个例子?是waveOutWrite函数吗?谢谢!
 
messagebeep()
 
习习,MessageBeep、Windows.Beep(F, D)发出的是Ding,Ding的声音,虽然Windows.Beep(F, D)
有两个参数,在有声卡的机器上好像没什么效果;无声卡的机器上才使用PC喇叭发声,参数也才
起作用。各位可以试一试。
我认为ghg_qh建议的用waveOut系列的函数可能是正确的解决办法。
 
你是要使PC喇叭强制发出声音吗?可以做到,用内嵌汇编就可以~~~~~~~`,不过要使
音箱发出beep的声音,可能要用WaveOutXXXXX函数了。
 
是让[blue]声卡/音箱[/blue]发声。谢谢各位。[:)]
 
为什么不直接用PC喇叭?声卡模拟发生Beep声音,需要做一个函数序列,通过改变频率来实现。
其实你完全可以做一个Wav资源文件,播放时改变频率即可!
下面给你所需函数,搞定没问题!

PWaveFormatEx = ^TWaveFormatEx;
tWAVEFORMATEX = packed record
wFormatTag: Word;
nChannels: Word;
nSamplesPerSec: DWORD;
nAvgBytesPerSec: DWORD;
nBlockAlign: Word;
wBitsPerSample: Word;
cbSize: Word;
end;



function waveOutOpen(
lphWaveOut: PHWaveOut;

uDeviceID: UINT;
lpFormat: PWaveFormatEx;

dwCallback, dwInstance,
dwFlags: DWORD
): MMRESULT;

function waveOutWrite(
hWaveOut: HWAVEOUT;

lpWaveOutHdr: PWaveHdr;
uSize: UINT
): MMRESULT;
stdcall;

function waveOutUnprepareHeader(
hWaveOut: HWAVEOUT;

lpWaveOutHdr: PWaveHdr;
uSize: UINT
): MMRESULT;
stdcall;

function waveOutClose(
hWaveOut: HWAVEOUT
): MMRESULT;
stdcall;
 
完整调用单元如下:

unit Echo1;

interface

uses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
Forms, Dialogs, mmsystem;

const
{The larger the size of the block the fewer blocks recorded}
{per second and therefore the longer the delay between}
{recording and playback}
memBlockLength = 500;
{500 bytes at 11k/sec = delay of 500/11000 of a second}
{roughly a 20th}

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^.wfdo

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,PWaveFormat(WaveFormat),0,0,WAVE_FORMAT_QUERY);
if i<&amp;gt0 then
application.messagebox('Error', 'Play format not supported', mb_OK);

i:=waveInOpen(nil,0,PWaveFormat(WaveFormat),0,0,WAVE_FORMAT_QUERY);
if i<&amp;gt0 then
application.messagebox('Error', 'Record format not supported', mb_OK);

HwaveOut:=new(PHwaveOut);
i:=waveOutOpen(HWaveOut,0,Pwaveformat(WaveFormat),form1.handle,0,CALLBACK_WINDOW);
if i<&amp;gt0 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<&amp;gt0 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 3do

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;


{prepare the new block}
i:=waveInPrepareHeader(HWaveIn^,Header,sizeof(TWavehdr));
if i<&amp;gt0 then
application.messagebox('In Prepare error','error',mb_ok);

{add it to the buffer}
i:=waveInAddBuffer(HWaveIn^,Header,sizeof(TWaveHdr));
if i<&amp;gt0 then
application.messagebox('Add buffer error','error',mb_ok);

inc(in_count);

end;

{of loop}

{finally start recording}
i:=waveInStart(HwaveIn^);
if i<&amp;gt0 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);
{get the returned header}
Header:=PWaveHdr(msg.lparam);
i:=waveOutUnPrepareHeader(HWaveOut^,Header,sizeof(TWavehdr));
if i<&amp;gt0 then
application.messagebox('Out Un Prepare error','error',mb_ok);


{free the memory}
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 there's nothing more todo
then
close}
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);
{block has been recorded}
Header:=PWaveHdr(msg.lparam);
i:=waveInUnPrepareHeader(HWaveIn^,Header,sizeof(TWavehdr));
if i<&amp;gt0 then
application.messagebox('In Un Prepare error','error',mb_ok);

if not(close_invoked) then

begin

{prepare it for play back}
i:=waveOutPrepareHeader(HWaveOut^,Header,sizeof(TWavehdr));
if i<&amp;gt0 then
application.messagebox('Out Prepare error','error',mb_ok);

{add it to the playback queue}
i:=waveOutWrite(HWaveOut^,Header,sizeof(TWaveHdr));
if i<&amp;gt0 then
application.messagebox('Wave out error','error',mb_ok);

inc(out_count);

{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;


{prepare the new block}
i:=waveInPrepareHeader(HWaveIn^,Header,sizeof(TWavehdr));
if i<&amp;gt0 then
application.messagebox('In Prepare error','error',mb_ok);

{add it to the buffer}
i:=waveInAddBuffer(HWaveIn^,Header,sizeof(TWaveHdr));
if i<&amp;gt0 then
application.messagebox('Add buffer error','error',mb_ok);

inc(in_count);
end;


{if there's no more blocks being recorded}
if (in_count=0) then

begin

WaveInClose(HWaveIn);
HwaveIn:=nil;
end;


{if there's nothing more todo
then
close}
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<&amp;gtnil then
WaveOutReset(HWaveOut^);

{reset the input channel}
if HwaveIn<&amp;gtnil then
WaveInReset(HWaveIn^);
close_invoked:=true;
canclose:=close_complete;
end;


end.


 
[gold]需要做一个函数序列,通过改变频率来实现[/gold],怎么做?上面这个实现好像没有哇[:D]
这个执行起来好像啥效果都没有[:D]YB_unique给解释解释?这段代码哪儿来的?
 
快搞定了...[:D]
 
[^]搞定了[^]
 
后退
顶部