在delphi中,从数组数据播放声音最简单的方法是什么
有什么简单的功能吗?我在找类似的东西在delphi中,从数组数据播放声音最简单的方法是什么,delphi,audio,multimedia,Delphi,Audio,Multimedia,有什么简单的功能吗?我在找类似的东西 播放(@data,44000,100{time}) 微软有一个软件告诉你如何使用MCI从内存播放声音。您可能需要将wave文件头放在阵列中,或者在第一次读取期间复制正确的数据,但除此之外,它应该非常容易移植。具有TLiveAudioPlayer组件。它从缓冲区播放音频 Win32 API函数可以使用其SND_memory标志从内存块播放标准RIFF编码音频(如WAV音频)。或者,如果音频在应用程序的资源中,您可以使用SND_资源标志。我在PCM音频操作方面做
播放(@data,44000,100{time}) 微软有一个软件告诉你如何使用MCI从内存播放声音。您可能需要将wave文件头放在阵列中,或者在第一次读取期间复制正确的数据,但除此之外,它应该非常容易移植。具有TLiveAudioPlayer组件。它从缓冲区播放音频 Win32 API函数可以使用其
SND_memory
标志从内存块播放标准RIFF编码音频(如WAV音频)。或者,如果音频在应用程序的资源中,您可以使用SND_资源
标志。我在PCM音频操作方面做了很多工作。播放自定义波形音频数据的短序列时,我始终使用此功能:
var
PlaySoundStopper: PBoolean;
SoundPlayerActive: boolean = false;
procedure PlaySound(const Sound: TASSound);
var
hWave: HWAVEOUT;
hdr: TWaveHdr;
buf: PAnsiChar;
fmt: TWaveFormatEx;
i: Integer;
n: Integer;
begin
try
with fmt do
begin
wFormatTag := WAVE_FORMAT_PCM;
nChannels := length(Sound.Channels);
nSamplesPerSec := Sound.SampleRate;
wBitsPerSample := 32;
nAvgBytesPerSec := nChannels * nSamplesPerSec * wBitsPerSample div 8;
nBlockAlign := nChannels * wBitsPerSample div 8;
cbSize := 0;
end;
GetMem(buf, fmt.nChannels * length(Sound.Channels[0]) * sizeof(TASWaveformSample));
if length(Sound.Channels) = 1 then
CopyMemory(buf, @(Sound.Channels[0, 0]), length(Sound.Channels[0]) * sizeof(TASWaveformSample))
else
for i := 0 to high(Sound.Channels[0]) do
for n := 0 to high(Sound.Channels) do
CopyMemory(buf + sizeof(TASWaveformSample) * (i * fmt.nChannels + n), @(Sound.Channels[n, i]), sizeof(TASWaveformSample));
if waveOutOpen(@hWave, WAVE_MAPPER, @fmt, 0, 0, CALLBACK_NULL) <> MMSYSERR_NOERROR then
raise Exception.Create('SoundPlayerThread.Execute: waveOutOpen failed: ' + SysErrorMessage(GetLastError));
ZeroMemory(@hdr, sizeof(hdr));
with hdr do
begin
lpData := buf;
dwBufferLength := fmt.nChannels * length(Sound.Channels[0]) * sizeof(TASWaveformSample);
dwFlags := 0;
end;
try
SoundPlayerActive := true;
waveOutPrepareHeader(hWave, @hdr, sizeof(hdr));
waveOutWrite(hWave, @hdr, sizeof(hdr));
sleep(500);
while waveOutUnprepareHeader(hWave, @hdr, sizeof(hdr)) = WAVERR_STILLPLAYING do
if PlaySoundStopper^ then
begin
waveOutPause(hWave);
waveOutUnprepareHeader(hWave, @hdr, sizeof(hdr));
break;
end
else
sleep(100);
finally
SoundPlayerActive := false;
waveOutClose(hWave);
FreeMem(buf);
end;
except
on E: Exception do MessageBox(0, PChar(E.ClassName + ': ' + E.Message), 'Sound Playback Error', MB_ICONERROR);
end;
end;
一个可能更好的方法是使用线程进行播放。那我会的
var
OwnerForm: HWND; // = 0;
SndSource: PASSound; // = nil;
ThreadPlaying: boolean; // = false;
type
TSoundPlayerThread = class(TThread)
private
{ Private declarations }
protected
procedure Execute; override;
end;
实施为
procedure TSoundPlayerThread.Execute;
var
hWave: HWAVEOUT;
hdr: TWaveHdr;
buf: PAnsiChar;
fmt: TWaveFormatEx;
i: Integer;
n: Integer;
begin
ThreadPlaying := true;
try
try
if not Assigned(SndSource) then
Exit;
with fmt do
begin
wFormatTag := WAVE_FORMAT_PCM;
nChannels := length(SndSource^.Channels);
nSamplesPerSec := SndSource^.SampleRate;
wBitsPerSample := 32;
nAvgBytesPerSec := nChannels * nSamplesPerSec * wBitsPerSample div 8;
nBlockAlign := nChannels * wBitsPerSample div 8;
cbSize := 0;
end;
GetMem(buf, fmt.nChannels * length(SndSource^.Channels[0]) * sizeof(TASWaveformSample));
if length(SndSource^.Channels) = 1 then
CopyMemory(buf, @(SndSource^.Channels[0, 0]), length(SndSource^.Channels[0]) * sizeof(TASWaveformSample))
else
for i := 0 to high(SndSource^.Channels[0]) do
for n := 0 to high(SndSource^.Channels) do
CopyMemory(buf + sizeof(TASWaveformSample) * (i * fmt.nChannels + n), @(SndSource^.Channels[n, i]), sizeof(TASWaveformSample));
if waveOutOpen(@hWave, WAVE_MAPPER, @fmt, 0, 0, CALLBACK_NULL) <> MMSYSERR_NOERROR then
raise Exception.Create('SoundPlayerThread.Execute: waveOutOpen failed: ' + SysErrorMessage(GetLastError));
ZeroMemory(@hdr, sizeof(hdr));
with hdr do
begin
lpData := buf;
dwBufferLength := fmt.nChannels * length(SndSource^.Channels[0]) * sizeof(TASWaveformSample);
dwFlags := 0;
end;
waveOutPrepareHeader(hWave, @hdr, sizeof(hdr));
waveOutWrite(hWave, @hdr, sizeof(hdr));
sleep(500);
while waveOutUnprepareHeader(hWave, @hdr, sizeof(hdr)) = WAVERR_STILLPLAYING do
begin
sleep(100);
if Terminated then
waveOutReset(hWave);
end;
waveOutClose(hWave);
FreeMem(buf);
except
on E: Exception do MessageBox(0, PChar(E.ClassName + ': ' + E.Message), 'TSoundPlayerThread', MB_ICONERROR);
end;
finally
ThreadPlaying := false;
end;
end;
过程TSoundPlayerThread.Execute;
变量
hWave:HWAVEOUT;
hdr:TWaveHdr;
buf:潘西卡;
fmt:TWaveFormatEx;
i:整数;
n:整数;
开始
线程播放:=真;
尝试
尝试
如果未分配(SndSource),则
出口
用fmt做
开始
wFormatTag:=波形\u格式\u PCM;
nChannels:=长度(SndSource^.通道);
nSamplesPerSec:=SndSource^.SampleRate;
wBitsPerSample:=32;
nAvgBytesPerSec:=nChannels*nSamplesPerSec*wBitsPerSample div 8;
nBlockAlign:=nChannels*wBitsPerSample div 8;
cbSize:=0;
结束;
GetMem(buf,fmt.nChannels*length(SndSource^.Channels[0])*sizeof(TASWaveformSample));
如果长度(SndSource^.Channels)=1,则
CopyMemory(buf,@(SndSource^.Channels[0,0]),长度(SndSource^.Channels[0])*sizeof(TASWaveformSample))
其他的
对于i:=0到高(SndSource^.Channels[0])do
对于n:=0到高(SndSource^.Channels)do
CopyMemory(buf+sizeof(TASWaveformSample)*(i*fmt.nChannels+n),@(SndSource^.Channels[n,i]),sizeof(TASWaveformSample));
如果waveOutOpen(@hWave,WAVE\u MAPPER,@fmt,0,0,CALLBACK\u NULL)MMSYSERR\u无错误,则
引发异常。创建('SoundPlayerThread.Execute:waveOutOpen失败:'+SysErrorMessage(GetLastError));
零内存(@hdr,sizeof(hdr));
用hdr做
开始
lpData:=buf;
dwBufferLength:=fmt.nChannels*长度(SndSource^.Channels[0])*sizeof(TASWaveformSample);
dwFlags:=0;
结束;
waveoutprepreheader(hWave,@hdr,sizeof(hdr));
waveOutWrite(hWave,@hdr,sizeof(hdr));
睡眠(500);
而WaveOutUnpareHeader(hWave,@hdr,sizeof(hdr))=WAVERR_
开始
睡眠(100);
如果终止,则
waveOutReset(hWave);
结束;
waveOutClose(hWave);
FreeMem(buf);
除了
在E:Exception do MessageBox(0,PChar(E.ClassName+':'+E.Message),'TSoundPlayerThread',MB_ICONERROR);
结束;
最后
线程播放:=错误;
结束;
结束;
我找不到一个不基于过时的sndPlaySound的完整解决方案,因此这里有两个函数可以从TMemoryStream和文件中播放“.wav”文件:
uses mmsystem;
procedure PlaySoundFromFile(FileName : String);
var
mStream : TMemoryStream;
begin
mStream := TMemoryStream.Create;
Try mStream.LoadFromFile(FileName); Except End;
If mStream.Size > 0 then PlaySoundFromStream(mStream);
mStream.Free;
end;
procedure PlaySoundFromStream(mStream : TMemoryStream);
begin
PlaySound(mStream.Memory,0,SND_MEMORY or SND_SYNC);
end;
声音是同步播放的,从内存中,您可以在Remy答案的链接中找到其他播放声音标志。如果切换到异步播放,请确保在播放结束前不清除声音存储器。是,这对我也适用。好的是,没有像bass.dll lame.exe这样的外部组件。我认为这个答案应该被标记为最好的答案。我想问你更多关于PCMs的问题。这是我的电子邮箱xbasic300@yahoo.com我需要你的帮助。
uses mmsystem;
procedure PlaySoundFromFile(FileName : String);
var
mStream : TMemoryStream;
begin
mStream := TMemoryStream.Create;
Try mStream.LoadFromFile(FileName); Except End;
If mStream.Size > 0 then PlaySoundFromStream(mStream);
mStream.Free;
end;
procedure PlaySoundFromStream(mStream : TMemoryStream);
begin
PlaySound(mStream.Memory,0,SND_MEMORY or SND_SYNC);
end;