views:

73

answers:

5

I've got a Visual C++/CLI app which uses beeps to signify good and bad results (used when the user can't see the screen).

Currently I use low pitched beeps for bad results and high pitched beeps for good results:

if( goodResult == true )
{
    Beep(1000, 40);
}
else
{
    Beep(2000, 20);
}

This works okay on my Vista laptop, but I've tried it on other laptops and some seem to play the sounds for less time (they sound more like clicks than beeps) or the sound doesn't play at all.

So I have two questions here:

  1. Is there a more reliable beep function?
  2. Is there a (simple) way I can play a short .wav file or something similar instead (preferred solution).
A: 

Perhaps speech synthesis might be appropriate, not sure, I am assuming your users are blind.

http://msdn.microsoft.com/en-us/library/system.speech.synthesis.speechsynthesizer.aspx

chibacity
No, not blind, just out of eye-shot of the machine making the beeps so speech isn't so good. It needs to be a short-sharp sound (the beeps are currently 20/40ms long).
Jon Cage
+3  A: 

The Beep function traditionally used the PC speaker, and I guess it is more or less obsolete nowadays. I guess the functionality is handled by the Laptop's BIOS, and thus is hardware dependant. I suggest that you use the PC:s soundcard to play the sound instead.

Create two tones as WAV files in e.g. Audacity, then play them using e.g. PlaySound.

Krumelur
This works although the sounds never play over each other so if one starts before the other, the first is cut off. I guess that's a limitation of the PlaySound implementation?
Jon Cage
Got it: SND_NOWAIT
Jon Cage
From reading the documentation, I would say SND_NOSTOP is the one you want, possibly also with SND_ASYNC (depending on if you want to wait for the sound to finish or not).
Krumelur
You're absolutely right! 'twas a copy/paste error, but well spotted :-)
Jon Cage
A: 

It looks like there might be a solution using the winmm library.

Jon Cage
A: 

The Windows MessageBeep function will play the default error, OK or alert system sounds with the correct parameters. As such, the actual sound played and volume is under the user's control, but should be recognisable as error or OK.

Pete Kirkham
I need two distinct beeps and ideally it'd be the same on all systems so that's probably not the best solution.
Jon Cage
+1  A: 

Based on Krumelur's answer, I got a fairly neat solution which embeds the .wav's in the executable. It uses SoundPlayer instead of the PlaySound function.

For a Visual C++ / CLI project, adding embedded resources seems to work slightly differently to the other languages .net supports:

  1. Right-click on the project and select Properties.
  2. Navigate to Configuration Properties -> Linker -> Input.
  3. Add the paths to the .wav file(s) you want to embed (in my case, $(ProjectDir)\Audio\PingSend.wav).

To play back one of the .wav's simply call:

System::IO::Stream^ s = Assembly::GetExecutingAssembly()->GetManifestResourceStream("PingSend.wav");
System::Media::SoundPlayer^ pingPlayer = gcnew System::Media::SoundPlayer(s);
pingPlayer->Play();

..which should play the sound in a new thread.

Jon Cage