I just want to produce a beep at 1200hz for 1 second.
This unit loads WaveAPI at start, should play a beep for 1 second, and close WaveAPI at end.
But when running, I can only hear a little noise.
Nothing to say in particular, should be stereo channels, and coded as 2 SmallInt
(short
in C++) for Left and Right.
The volume is not integrated but is considered as 100% for both channels.
This is my Delphi 6 code:
unit C4Audio;
interface
uses Windows;
type
TAudioBits = SHORT;
TAudioDelay = WORD;
TAudioHerz = WORD;
TAudioByte = record
Left, Right : TAudioBits;
end;
TAudioStereo = record
Left, Right : 0..100;
end;
implementation
uses Forms,
mmsystem;
var
AudioAPI : hWaveOut;
AudioBuffer : array of TAudioByte;
AudioHeader : TWaveHdr;
AudioStyle : TWaveFormatEx;
var _alpha : Real;
_cursor : Integer;
_high : Integer;
initialization
with AudioStyle
do begin
wFormatTag := WAVE_FORMAT_PCM;
nChannels := 2;
nSamplesPerSec := 44100;
wBitsPerSample := SizeOf(TAudioBits) * 8;
nBlockAlign := (wBitsPerSample div 8) * nChannels;
nAvgBytesPerSec := nBlockAlign * nSamplesPerSec;
cbSize := 0;
end;
if waveOutOpen(@AudioAPI, WAVE_MAPPER, @AudioStyle, 0, 0, CALLBACK_NULL) = MMSYSERR_NOERROR
then begin
SetLength(AudioBuffer, 1000);
with AudioHeader
do begin
dwBufferLength := Length(AudioBuffer) * SizeOf(TAudioByte);
dwFlags := 0;
dwLoops := $FFFF;
lpData := @AudioBuffer;
end;
_alpha := 0;
_high := High(TAudioBits);
for _cursor := Low(AudioBuffer) to High(AudioBuffer)
do begin
AudioBuffer[_cursor].Left := Round(_high * Sin(_alpha));
AudioBuffer[_cursor].Right := Round(_high * Sin(_alpha));
_alpha := _alpha + 2 * PI * 1200 / AudioStyle.nSamplesPerSec;
end;
if (waveOutPrepareHeader(AudioAPI, @AudioHeader, SizeOf(TWaveHdr)) = MMSYSERR_NOERROR)
and
(waveOutWrite(AudioAPI, @AudioHeader, sizeof(TWaveHdr)) = MMSYSERR_NOERROR)
then Sleep(1000);
end
else
AudioAPI := 0;
finalization
if AudioAPI <> 0
then begin
while waveOutUnprepareHeader(AudioAPI, @AudioHeader, SizeOf(TWaveHdr)) = WAVERR_STILLPLAYING
do Application.ProcessMessages;
if waveOutClose(AudioAPI) = MMSYSERR_NOERROR
then begin
end;
end;
end.
You are assigning the wrong pointer value to AudioHeader.lpData
.
AudioBuffer
is a dynamic array, so it is just a pointer to data that is held elsewhere in memory.
When you use @AudioBuffer
, that gives you the address of the array's internal pointer that is pointing at the audio data. It does not give you the address of the audio data itself. This is likely the root of your issue.
You need to instead use either lpData := @AudioBuffer[0]
or lpData := Pointer(AudioBuffer)
to make lpData
point at the actual audio data.