【发布时间】:2011-12-06 05:48:51
【问题描述】:
我想生成和播放具有随时间变化的特定频率和幅度的连续声音。我不想在声音之间有延迟。如何使用 Delphi 或 C++ Builder 做到这一点?
【问题讨论】:
-
由于您没有接受我的回答,我认为它对您没有帮助。或许您可以解释一下为什么它对您没有帮助?
标签: delphi winapi audio c++builder
我想生成和播放具有随时间变化的特定频率和幅度的连续声音。我不想在声音之间有延迟。如何使用 Delphi 或 C++ Builder 做到这一点?
【问题讨论】:
标签: delphi winapi audio c++builder
这个非常简单的示例应该可以帮助您入门。
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils, Windows, MMSystem;
type
TWaveformSample = integer; // signed 32-bit; -2147483648..2147483647
TWaveformSamples = packed array of TWaveformSample; // one channel
var
Samples: TWaveformSamples;
fmt: TWaveFormatEx;
procedure InitAudioSys;
begin
with fmt do
begin
wFormatTag := WAVE_FORMAT_PCM;
nChannels := 1;
nSamplesPerSec := 44100;
wBitsPerSample := 32;
nAvgBytesPerSec := nChannels * nSamplesPerSec * wBitsPerSample div 8;
nBlockAlign := nChannels * wBitsPerSample div 8;
cbSize := 0;
end;
end;
// Hz // msec
procedure CreatePureSineTone(const AFreq: integer; const ADuration: integer;
const AVolume: double { in [0, 1] });
var
i: Integer;
omega,
dt, t: double;
vol: double;
begin
omega := 2*Pi*AFreq;
dt := 1/fmt.nSamplesPerSec;
t := 0;
vol := MaxInt * AVolume;
SetLength(Samples, Round((ADuration / 1000) * fmt.nSamplesPerSec));
for i := 0 to high(Samples) do
begin
Samples[i] := round(vol*sin(omega*t));
t := t + dt;
end;
end;
procedure PlaySound;
var
wo: integer;
hdr: TWaveHdr;
begin
if Length(samples) = 0 then
begin
Writeln('Error: No audio has been created yet.');
Exit;
end;
if waveOutOpen(@wo, WAVE_MAPPER, @fmt, 0, 0, CALLBACK_NULL) = MMSYSERR_NOERROR then
try
ZeroMemory(@hdr, sizeof(hdr));
with hdr do
begin
lpData := @samples[0];
dwBufferLength := fmt.nChannels * Length(Samples) * sizeof(TWaveformSample);
dwFlags := 0;
end;
waveOutPrepareHeader(wo, @hdr, sizeof(hdr));
waveOutWrite(wo, @hdr, sizeof(hdr));
sleep(500);
while waveOutUnprepareHeader(wo, @hdr, sizeof(hdr)) = WAVERR_STILLPLAYING do
sleep(100);
finally
waveOutClose(wo);
end;
end;
begin
try
InitAudioSys;
CreatePureSineTone(400, 1000, 0.7);
PlaySound;
except
on E: Exception do
begin
Writeln(E.Classname, ': ', E.Message);
Readln;
end;
end;
end.
特别注意你得到的简洁界面:
InitAudioSys;
CreatePureSineTone(400, 1000, 0.7);
PlaySound;
【讨论】:
通过使用 WaveAudio 库,可以生成连续的余弦波。
我打算发布一些代码,但我不知道如何正确执行,所以我不会。
但您需要做的就是使用 TLiveAudioPlayer,然后覆盖 OnData 事件。
如果没有消息泵,也将 Async 设置为 true。
我会推荐 Delphi 的 ASIO 库!
https://sourceforge.net/projects/delphiasiovst/
使用它非常简单,不必包含所有文件,从主要文件开始,然后从那里添加其余文件,另请参阅示例。
最终它就像 OnSomeEvent/OnSomeBuffer 一样简单
然后简单地用浮点值填充一个数组。
不记得 OnEvent 的确切名称,但您可以在示例中轻松找到它。
要做的另一件事是将某些组件设置为 active/true 和瞧。
ASIO 的优点是延迟非常低,甚至可以将其降低到 50 微秒甚至更低。
您的声音芯片确实需要一个 ASIO 驱动程序。
ASIO = 音频流输入输出
由音频工程师设计的 API!
可能没有比这更好的了! ;)
【讨论】: