|
This code should compile fine under any C
compiler, but I used Microsoft Visual C++ 6.0. Make sure to link with libraries
user32.lib (used for message boxes) and winmm.lib (used for multimedia).
This code
is the simplest way to get a chunk of data to
play through the sound card. A great place to start if your just getting
familiar with Window's multimedia API.
A next good tutorial is taking this program and making it stream
multiple packets to your sound card, but I left that for you to discover
and enjoy! /* ** Simple Windows Sound Program **
This program demonstrates how to create and play a simple sound wave
with your default sound card.
Make sure to link into user32.lib and winmm.lib during compile.
Todd Moore
toddmoore@erols.com
*/
#include <windows.h>
#include <math.h>
#define FREQUENCY 440 // 440hz = Musical A Note
#define BUFFERSIZE 4860 // 4k sound buffer
#define PI 3.14159265358979
// A simple way to report Sound Errors
void Message(LPCSTR message)
{
MessageBox(NULL, message, "Sound Error", MB_OK | MB_ICONSTOP);
}
// Main entry point for Win32 Program
int WINAPI WinMain(HINSTANCE hInstance, // handle to current instance
HINSTANCE hPrevInstance, // handle to previous instance
LPSTR lpCmdLine, // pointer to command line
int nCmdShow) // show state of window
{
HWAVEOUT hWaveOut; // Handle to sound card output
WAVEFORMATEX WaveFormat; // The sound format
WAVEHDR WaveHeader; // WAVE header for our sound data
char Data[BUFFERSIZE]; // Sound data buffer
HANDLE Done; // Event Handle that tells us the sound has finished being played.
// This is a real efficient way to put the program to sleep
// while the sound card is processing the sound buffer
double x;
int i;
// ** Initialize the sound format we will request from sound card **
WaveFormat.wFormatTag = WAVE_FORMAT_PCM; // Uncompressed sound format
WaveFormat.nChannels = 1; // 1=Mono 2=Stereo
WaveFormat.wBitsPerSample = 8; // Bits per sample per channel
WaveFormat.nSamplesPerSec = 11025; // Sample Per Second
WaveFormat.nBlockAlign = WaveFormat.nChannels * WaveFormat.wBitsPerSample / 8;
WaveFormat.nAvgBytesPerSec = WaveFormat.nSamplesPerSec * WaveFormat.nBlockAlign;
WaveFormat.cbSize = 0;
// ** Create our "Sound is Done" event **
Done = CreateEvent (0, FALSE, FALSE, 0);
// ** Open the audio device **
if (waveOutOpen(&hWaveOut,0,&WaveFormat,(DWORD) Done,0,CALLBACK_EVENT) != MMSYSERR_NOERROR)
{
Message("Sound card cannot be opened.");
return TRUE;
}
// ** Make the sound buffer **
for (i=0; i < BUFFERSIZE; i++)
{
// ** Generate the sound wave based on FREQUENCY define
// ** x will have a range of -1 to +1
x = sin(i*2.0*PI*(FREQUENCY)/(double)WaveFormat.nSamplesPerSec);
// ** scale x to a range of 0-255 (signed char) for 8 bit sound reproduction **
Data[i] = (char)(127*x+128);
}
// ** Create the wave header for our sound buffer **
WaveHeader.lpData=Data;
WaveHeader.dwBufferLength=BUFFERSIZE;
WaveHeader.dwFlags=0;
WaveHeader.dwLoops=0;
// ** Prepare the header for playback on sound card **
if (waveOutPrepareHeader(hWaveOut,&WaveHeader,sizeof(WaveHeader)) != MMSYSERR_NOERROR)
{
Message("Error preparing Header!");
return TRUE;
}
// ** Play the sound! **
ResetEvent(Done); // Reset our Event so it is non-signaled, it will be signaled again with buffer finished
if (waveOutWrite(hWaveOut,&WaveHeader,sizeof(WaveHeader)) != MMSYSERR_NOERROR)
{
Message("Error writing to sound card!");
return TRUE;
}
// ** Wait until sound finishes playing
if (WaitForSingleObject(Done,INFINITE) != WAIT_OBJECT_0)
{
Message("Error waiting for sound to finish");
return TRUE;
}
// ** Unprepare our wav header **
if (waveOutUnprepareHeader(hWaveOut,&WaveHeader,sizeof(WaveHeader)) != MMSYSERR_NOERROR)
{
Message("Error unpreparing header!");
return TRUE;
}
// ** close the wav device **
if (waveOutClose(hWaveOut) != MMSYSERR_NOERROR)
{
Message("Sound card cannot be closed!");
return TRUE;
}
// ** Release our event handle **
CloseHandle(Done);
return FALSE;
}
|