7
A
回答
2
微軟有一個Knowledge Base article告訴你如何使用MCI從內存播放聲音。您可能需要在數組中包含波形文件標頭,否則在第一次讀取時需要複製正確的數據,但除此之外,它應該相當容易移植。
4
Wave Audio Package有TLiveAudioPlayer組件。它從緩衝區播放音頻。
2
Win32 API PlaySound函數可以使用其SND_MEMORY
標誌從存儲器塊播放標準RIFF編碼音頻(如WAV音頻)。或者,如果音頻位於應用的資源中,則可以使用SND_RESOURCE
標誌。
7
我在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;
其中
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, 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;
+0
我想問你更多關於PCM的信息。這是我的E - 添加[email protected]我需要你的幫助。 – XBasic3000 2010-08-13 08:25:45
相關問題
- 1. 播放循環聲音最簡單的方法是什麼?
- 2. 播放單音音頻文件的最佳方法是什麼?
- 3. 在WPF中播放MP3最簡單的方法是什麼?
- 4. 什麼是自動播放聲音最「兼容」的方式?
- 5. 簡單播放iOS中的聲音
- 6. 簡單的方法來播放聲音文件(.aif)
- 7. 在iPhone應用程序中播放聲音剪輯的最簡單方法是什麼?
- 8. 在行上打印數組的最簡單方法是什麼?
- 9. 從wifi攝像頭播放視頻最簡單的方法是什麼?
- 10. 以'snd'資源格式播放聲音數據的現代方式是什麼?
- 11. Java:XML到數據庫中,最簡單的方法是什麼?
- 12. Android:保存少量數據的最簡單方法是什麼?
- 13. MediaPlay無法播放聲音,爲什麼?
- 14. 什麼是最低級別的Windows功能播放聲音?
- 15. 在Android中播放音頻RTMP流最簡單的方法
- 16. 匹配兩組數據的簡單方法是什麼? Laravel 5.3
- 17. 將char數組轉換爲WCHAR數組最簡單的方法是什麼?
- 18. 簡單的聲音播放器函數調用
- 19. 在iOS中以更高音調播放音樂的最簡單方法是什麼?
- 20. 使用C#從RTMP服務器獲取和播放音頻流的最簡單方法是什麼?
- 21. 播放較長聲音片段的標準方式是什麼?
- 22. 在PHP中加載一組文字數據的最簡單方法是什麼?
- 23. 從數組寫入CSV文件最簡單的方法是什麼?
- 24. 從Tuple2數組創建案例類對象的最簡單方法是什麼?
- 25. 比較簡單的聲音 - 什麼是最接近的頻率
- 26. 用C++將數據插入mysql數據庫的最簡單方法是什麼?
- 27. 在Java中獲取數據庫元數據的最簡單方法是什麼?
- 28. 從C++調用Java方法的最簡單方法是什麼?
- 29. 什麼是從Javascript調用C#方法的最簡單方法
- 30. 什麼是從數組集合中獲取數組值的最簡單/最好的方法?
是的,它爲我工作爲好。和它的好處,沒有像bass.dll lame.exe等外部組件 – XBasic3000 2010-08-13 03:56:33
我認爲這個答案應該被標記爲最好的。 – Javid 2014-08-03 10:52:43