在delphi中从数组数据中播放声音的最简单方法是什么?
发布时间:2020-12-15 10:13:13 所属栏目:大数据 来源:网络整理
导读:有什么简单的功能吗?我正在寻找类似的东西 播放(@data,44000,100 {时间}); 解决方法 我在PCM音频操作方面做了很多工作.在播放自定义波形音频数据的短序列时,我总是使用此功能: var PlaySoundStopper: PBoolean; SoundPlayerActive: boolean = false;proced
有什么简单的功能吗?我正在寻找类似的东西
播放(@data,44000,100 {时间}); 解决方法
我在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,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,sizeof(hdr)); sleep(500); while waveOutUnprepareHeader(hWave,sizeof(hdr)) = WAVERR_STILLPLAYING do if PlaySoundStopper^ then begin waveOutPause(hWave); waveOutUnprepareHeader(hWave,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; 哪里 type TASWaveformSample = integer; // signed 32-bit; -2147483648..2147483647 TASWaveformSamples = packed array of TASWaveformSample; // one channel PASSound = ^TASSound; TASSound = record Channels: packed array of TASWaveformSamples; SampleRate: cardinal; 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,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,sizeof(TASWaveformSample)); if waveOutOpen(@hWave,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,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,'TSoundPlayerThread',MB_ICONERROR); end; finally ThreadPlaying := false; end; end; (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |