Có chức năng đơn giản nào không? Tôi đang tìm kiếm nội dung nào đó như vậycách đơn giản nhất để phát âm thanh từ dữ liệu mảng trong delphi
Phát (@data, 44000, 100 {time});
Có chức năng đơn giản nào không? Tôi đang tìm kiếm nội dung nào đó như vậycách đơn giản nhất để phát âm thanh từ dữ liệu mảng trong delphi
Phát (@data, 44000, 100 {time});
Microsoft có số Knowledge Base article cho bạn biết cách phát âm thanh từ bộ nhớ bằng MCI. Bạn có thể cần phải có tiêu đề tập tin sóng trong mảng của bạn, hoặc bằng cách khác sao chép vào đúng dữ liệu trong lần đọc đầu tiên, nhưng khác hơn là nó nên được khá dễ dàng để chuyển qua.
Wave Audio Package có thành phần TLiveAudioPlayer. Nó phát âm thanh từ bộ đệm.
Chức năng Win32 API PlaySound có thể phát âm thanh được mã hóa RIFF tiêu chuẩn (chẳng hạn như âm thanh WAV) từ khối bộ nhớ bằng cách sử dụng cờ SND_MEMORY
. Ngoài ra, nếu âm thanh có trong tài nguyên của ứng dụng, bạn có thể sử dụng cờ SND_RESOURCE
để thay thế.
Tôi đã làm việc khá nhiều với thao tác âm thanh PCM. Tôi luôn luôn sử dụng chức năng này khi chơi chuỗi ngắn của dạng sóng tùy chỉnh dữ liệu âm thanh:
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;
nơi
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;
Một cách có lẽ tốt hơn, là sử dụng một sợi cho chơi. Sau đó, tôi làm
var
OwnerForm: HWND; // = 0;
SndSource: PASSound; // = nil;
ThreadPlaying: boolean; // = false;
type
TSoundPlayerThread = class(TThread)
private
{ Private declarations }
protected
procedure Execute; override;
end;
thực hiện như
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;
tôi muốn hỏi thêm về PCM. đây là E-Add [email protected] của tôi, tôi cần sự giúp đỡ của bạn. – XBasic3000
Có nó làm việc cho tôi là tốt. và điều tốt của nó, không có thành phần bên ngoài như bass.dll lame.exe vv. – XBasic3000
Tôi nghĩ rằng câu trả lời này nên đã được đánh dấu là tốt nhất. – Javid