jmasterx
jmasterx

Reputation: 54103

Programably make and play a sound through speakers C++

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

Upvotes: 4

Views: 7386

Answers (4)

Corey Ross
Corey Ross

Reputation: 2015

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;       // 0x46464952 "RIFF" in little endian
    DWORD chunkSize;     // 4 + (8 + subChunk1Size) + (8 + subChunk2Size)
    DWORD format;        // 0x45564157 "WAVE" in little endian

    DWORD subChunk1ID;   // 0x20746d66 "fmt " in little endian
    DWORD subChunk1Size; // 16 for PCM
    WORD  audioFormat;   // 1 for PCM, 3 fot EEE floating point , 7 for μ-law
    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;   // 0x61746164 "data" in little 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(WaveHeader); //jumps to beginning of data
// 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 (OLD - not working now)

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 :)

Upvotes: 11

Emile Vrijdags
Emile Vrijdags

Reputation: 1578

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

Upvotes: 0

Georg Fritzsche
Georg Fritzsche

Reputation: 98984

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.

Upvotes: 1

kennyisaheadbanger
kennyisaheadbanger

Reputation: 488

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

Upvotes: 0

Related Questions