tags:

views:

369

answers:

5

I'm making a game in native vc++ (not .Net)

I'm looking for a way to play a noise (maybe 8 bit or something) through the real speakers (not internal). I know about PlaySound, but I don't want to make my EXE big. I want to program the sound.

Is there an api way (kinda like Beep() ) but that plays through the real speakers?

Thanks

A: 

I found this: http://www.xtremevbtalk.com/showthread.php?p=829281 it could be of some use to you

kennyisaheadbanger
+1  A: 

While there are several possibilities on windows, one of the simplest is sndPlaySound():

  • include mmsystem.h
  • link to winmm.lib
  • ::sndPlaySound("sound.wav", SND_ASYNC|SND_NODEFAULT);
  • to stop playback: ::sndPlaySound(NULL, NULL);

Of course there are other ways like mci and direct sound which might suit your needs better if you see more clearly what you need.

Georg Fritzsche
+4  A: 

You mention that you know about PlaySound. One of the it's flags (SND_MEMORY) will allow you to play a WAVE that is already loaded into memory, i.e. a buffer that you have created yourself. As long as the buffer has the appropriate WAVE header, whatever you you put in there should play through the speakers.

The header is a 44 byte block that is fairly straight forward

struct WaveHeader
{
    DWORD chunkID;       // 0x52494646 "RIFF" in big endian
    DWORD chunkSize;     // 4 + (8 + subChunk1Size) + (8 + subChunk2Size)
    DWORD format;        // 0x57415645 "WAVE" in big endian

    DWORD subChunk1ID;   // 0x666d7420 "fmt " in big endian
    DWORD subChunk1Size; // 16 for PCM
    WORD  audioFormat;   // 1 for PCM
    WORD  numChannels;   // 1 for mono, 2 for stereo
    DWORD sampleRate;    // 8000, 22050, 44100, etc...
    DWORD byteRate;      // sampleRate * numChannels * bitsPerSample/8
    WORD  blockAlign;    // numChannels * bitsPerSample/8
    WORD  bitsPerSample; // number of bits (8 for 8 bits, etc...)

    DWORD subChunk2ID;   // 0x64617461 "data" in big endian
    DWORD subChunk2Size; // numSamples * numChannels * bitsPerSample/8 (this is the actual data size in bytes)
};

You'd set up your buffer with something similar to:

char *myBuffer = new char[sizeof(WaveHeader) + myDataSize];

WaveHeader *header = (WaveHeader*)myBuffer;
// fill out the header...

char *data = myBuffer + sizeof(WavHeader);
// fill out waveform data...

So you use it something like:

PlaySound(myBuffer, NULL, SND_MEMORY | SND_ASYNC);

I'm assuming that you're going to be using you generated sound for the lifetime of you app. If you aren't, be careful with that SND_ASYNC flag. That is, don't go freeing the buffer directly after you call PlaySound (while it is still in use).

MSDN PlaySound Docs
A page with more detail on the WAV header

DirectX also supports playing audio from in-memory buffers and is a much more powerful API, but it maybe overkill for what you need to do :)

Corey Ross
A: 

My answer to another question could be helpfull, check it out here

I talk about an easy to use opensource api (The Synthesis Toolkit) that has classes to read/write wav files, and has easy to use wrapper classes to do realtime output to different drivers (wdm, asio, jack,...)

Imho it is easier to use than the winapi functions

Emile Vrijdags
A: 

Maybe this

Clifford