En forbedret version der rydder pænt op efter sig og som ikke free'er bufferen før den er færdig spillet:
#include <windows.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#define MY_PI 3.141593
#define SAMPLE_RATE 22050
#define A_NODE 440
#define As_NODE 466
#define B_NODE 494
#define C_NODE 523
#define Cs_NODE 554
#define D_NODE 587
#define Ds_Node 622
#define E_NODE 659
#define F_NODE 698
#define Fs_NODE 740
#define G_NODE 784
#define Gs_NODE 831
/* 440.000 466.163 493.883 523.251 554.365 587.329 622.253 659.255 698.456 739.988 783.991 830.609 */
void CALLBACK CallBackProc(HWAVEOUT hwo, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
if(uMsg == WOM_DONE)
{
MMRESULT MMResult;
WAVEHDR *WaveHeader = (WAVEHDR *)dwParam1;
if((MMResult = waveOutUnprepareHeader(hwo, WaveHeader, sizeof(WAVEHDR))) != MMSYSERR_NOERROR)
{
char Text[256];
waveOutGetErrorText(MMResult, Text, sizeof(Text));
printf("Failed to unprepare: %s\\n", Text);
}
free(WaveHeader->lpData);
}
}
bool PlayTone(int freq, int duration)
{
int x;
char *buffer = (char *)malloc(SAMPLE_RATE*duration/1000);
for (x = 0; x < SAMPLE_RATE*duration/1000; x++)
buffer[x] = (char )(128.0 + (127.0 * sin(2.0 * MY_PI * freq * x / SAMPLE_RATE)));
HWAVEOUT WaveHandle;
WAVEFORMATEX WaveFormat;
WAVEHDR WaveHeader;
MMRESULT MMResult;
WaveFormat.wFormatTag = WAVE_FORMAT_PCM;
WaveFormat.nChannels = 1;
WaveFormat.nSamplesPerSec = SAMPLE_RATE;
WaveFormat.nAvgBytesPerSec = SAMPLE_RATE;
WaveFormat.nBlockAlign = 1;
WaveFormat.wBitsPerSample = 8;
WaveFormat.cbSize = 0;
if(waveOutOpen(&WaveHandle, WAVE_MAPPER, &WaveFormat, (DWORD )CallBackProc, 0, CALLBACK_FUNCTION) != MMSYSERR_NOERROR)
{
printf("Failed to open Wave!\\n");
return false;
}
memset(&WaveHeader, 0, sizeof(WaveHeader));
WaveHeader.lpData = buffer;
WaveHeader.dwBufferLength = duration*SAMPLE_RATE/1000;
WaveHeader.dwBytesRecorded = duration*SAMPLE_RATE/1000;
WaveHeader.dwLoops = 1;
WaveHeader.dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP;
if(waveOutPrepareHeader(WaveHandle, &WaveHeader, sizeof(WaveHeader)) != MMSYSERR_NOERROR)
{
printf("Failed to prepare header!\\n");
return false;
}
if((MMResult = waveOutWrite(WaveHandle, &WaveHeader, sizeof(WaveHeader))) != MMSYSERR_NOERROR)
{
char Text[256];
waveOutGetErrorText(MMResult, Text, sizeof(Text));
printf("Failed to write: %s\\n", Text);
return false;
}
Sleep(duration);
while(!(WaveHeader.dwFlags & WHDR_DONE))
Sleep(10);
if((MMResult = waveOutClose(WaveHandle)) != MMSYSERR_NOERROR)
{
char Text[256];
waveOutGetErrorText(MMResult, Text, sizeof(Text));
printf("Failed to close: %s\\n", Text);
return false;
}
return true;
}
int main(void)
{
PlayTone(A_NODE, 1000);
PlayTone(As_NODE, 1000);
PlayTone(B_NODE, 1000);
PlayTone(C_NODE, 1000);
PlayTone(Cs_NODE, 1000);
PlayTone(D_NODE, 1000);
PlayTone(Ds_Node, 1000);
PlayTone(E_NODE, 1000);
PlayTone(F_NODE, 1000);
PlayTone(Fs_NODE, 1000);
PlayTone(G_NODE, 1000);
PlayTone(Gs_NODE, 1000);
return 0;
}