【发布时间】:2015-11-25 14:32:48
【问题描述】:
我从互联网上找到代码,首先我播放波形文件并没有问题,然后我播放 wav 更多次并在 48 次出现错误。我知道来自 waveOutOpen 函数的错误。
这是我的代码:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses MMSystem;
{$R *.dfm}
var
buf: Array of byte;
wh: TWaveHdr;
hOut: HWAVEOUT;
fmt: TWaveFormatEx;
count: integer;
function GetWaveFmtData(path: string; var fmt: TWaveFormatEx ): Boolean;
var
hFile: HMMIO;
ckiRIFF,ckiFmt,ckiData: TMMCKInfo;
begin
Result := False;
hFile := mmioOpen(PChar(path), nil, MMIO_READ);
if hFile = 0 then Exit;
ZeroMemory(@ckiRIFF, SizeOf(TMMCKInfo));
ZeroMemory(@ckiFmt, SizeOf(TMMCKInfo));
ZeroMemory(@ckiData, SizeOf(TMMCKInfo));
ckiRIFF.fccType := mmioStringToFOURCC('WAVE', 0);
ckiFmt.ckid := mmioStringToFOURCC('fmt', 0);
ckiData.ckid := mmioStringToFOURCC('data', 0);
ZeroMemory(@fmt, SizeOf(TWaveFormatEx));
mmioDescend(hFile, @ckiRIFF, nil, MMIO_FINDRIFF);
if (ckiRIFF.ckid = FOURCC_RIFF) and (ckiRIFF.fccType = mmioStringToFOURCC('WAVE',0)) and
(mmioDescend(hFile, @ckiFmt, @ckiRIFF, MMIO_FINDCHUNK) = MMSYSERR_NOERROR) and
(mmioRead(hFile, @fmt, ckiFmt.cksize) = ckiFmt.cksize) and
(mmioAscend(hFile, @ckiFmt, 0) = MMSYSERR_NOERROR) and
(mmioDescend(hFile, @ckiData, @ckiRIFF, MMIO_FINDCHUNK) = MMSYSERR_NOERROR) then
begin
SetLength(buf, ckiData.cksize);
Result := (mmioRead(hFile, PAnsiChar(buf), ckiData.cksize) = ckiData.cksize);
end;
mmioClose(hFile, 0);
end;
Procedure CallBack(
hwo :HWAVEOUT;
uMsg :UINT ;
dwInstance :DWORD;
dwParam1 :DWORD;
dwParam2 :DWORD
);stdcall;
begin
{Need check the message here but for now lets just make sure
that we get called }
ShowMessage('WaveOut');
end;
procedure TForm1.Button1Click(Sender: TObject);
const
path = 'fire.wav';
begin
GetWaveFmtData(path, fmt);
wh.lpData := PAnsiChar(buf);
wh.dwBufferLength := Length(buf);
wh.dwBytesRecorded := 0;
wh.dwUser := 0;
wh.dwFlags := 0;
wh.dwLoops := 1;
wh.lpNext := nil;
wh.reserved := 0;
//waveOutClose(hOut);
if waveOutOpen(@hOut, WAVE_MAPPER, @fmt, DWORD(@CallBack),
Handle,WAVE_MAPPED and CALLBACK_FUNCTION) = MMSYSERR_NOERROR then
begin
count:=count+1;
Edit1.Text:=IntToStr(count);
end;
waveOutPrepareHeader(hOut, @wh, SizeOf(TWaveHdr));
waveOutWrite(hOut, @wh, SizeOf(TWaveHdr));
end;
end.
顺便说一下,回调函数不起作用,请任何人帮助我! 这里是Full code. 对不起我的英语。
【问题讨论】:
-
你是说你从波函数中得到错误 42 吗?使用
waveOutGetErrorText()将错误码转换成字符串。 -
我想说的是,当播放音频 48 次时,它将被禁用并且没有声音。虽然我想永远播放声音,直到我想关闭它。
-
我有一些播放wav文件的经验,回拨不可靠。我有回调在某些机器上工作,而不是在其他机器上工作,有时在同一台机器上工作,而不是在其他机器上工作。最后,我不得不求助于安全第一的方法来读取标题,查看它应该播放多长时间,并在稍长一点的时间后触发计时器以确保文件已关闭。可怕而令人沮丧,但 100% 可靠。
-
谢谢。所以用 wavout 播放 wav 对我来说没有效果,因为应用程序可能同时播放多个音频等等。例如:游戏应用程序。我的目的是同时从流或数组中播放多个音频。
标签: delphi winapi delphi-7 delphi-xe