Click here to Skip to main content
Click here to Skip to main content

Managed MessageBeep() in C#

, 10 Apr 2003
Rate this:
Please Sign up or sign in to vote.
Managed MessageBeep() and Beep() classes in C#
<!-- Download Links --> <!-- Article image -->

Sample Image - mbwinform.jpg

Introduction

The code submitted presents two managed .NET C# classes, MessageBeep() and Beep(), which emulate the Win32 platform calls of the same names. Installation of Microsoft DirectX 9.0 is required. The code has been tested on Windows XP and Win2K using standard AC97 onboard sound cards.

The .NET Window Forms test application, MessageBeepTest, plays the six MessageBeep sounds using both managed DirectX and unmanaged PInvoke versions. If successful, the six sounds will sound the same using the two techniques (the sounds can be changed or turned off using the Windows Control Panel). 

Additionally, the Beep function will play a sine or square wave of a specified frequency and duration using both methods.

Background

Ever since the Beta 2 days, one of the questions asked most frequently in the C# newsgroups is "Where is the MessageBeep?", "Where is the MessageBeep?", and again "Where is the MessageBeep?" Until the DirectX 9.0 SDK was released last month, the answer has always been either:

  1. Drop into unmanaged code with PInvoke  or
  2. Add a reference to the Microsoft Visual Basic .NET runtime dll.

The former solution is of course unmanaged and the latter solution is of course, for a C# programmer, an abomination. Tacit admission that your chosen .NET language is somehow--incomplete. With the release of DirectX 9.0 and some time made free over the recent holiday season, I was allowed to investigate if indeed the MessageBeep question could be answered once and for all.

Implementation

If I've done it correctly, the MessageBeep code was actually very easy. Some research on the web was required to find where in the Windows Registry the sounds are mapped to the six sound types: System Asterisk, System Exclamation, System Hand, System Question, System Default and Simple Beep.

// From winuser.h<BR>#define MB_OK 0x00000000L<BR>#define MB_ICONHAND 0x00000010L<BR>#define MB_ICONQUESTION 0x00000020L<BR>#define MB_ICONEXCLAMATION 0x00000030L<BR>#define MB_ICONASTERISK 0x00000040L<BR>#define Simple Beep 0xffffffffL<BR>

becomes:

public enumBeepTypes : long<BR>{<BR>	MB_OK = 0x0,<BR>	MB_ICONHAND = 0x00000010,<BR>	MB_ICONQUESTION = 0x00000020,<BR>	MB_ICONEXCLAMATION = 0x00000030,<BR>	MB_ICONASTERISK = 0x00000040,<BR>	SIMPLE_BEEP = 0xffffffff<BR>};

Then just cause the DirectX DirectSound function to be run on a background thread and as quick as "Bob's your Uncle**" you're finished. One difference between the techniques is that if no sound card is available, the SimpleBeep sound is generated using an internal speaker in the unmanaged version. I found no way to access the internal speaker using DirectX. An AC97 hardware independent way of accessing the speaker using unsafe pointers and a managed wrapper might be possible but I'm not sure how widespread the use of the AC97 standard is.

**This CP phrase is becomming popular in general use and I have no idea what it means.

Implementing the Beep() class was more difficult. The concept is simple enough, use a DirectX secondary buffer in the "looping" mode and write the tone samples to an area in the buffer DirectX isn't using at the moment.

The problem was with playing the sound the second time. A small portion of the last tone is heard at the beginning of the new tone. But it is also heard when a different secondary buffer is played! For instance when a buffer created for a MessageBeep sound is played after Beep. The problem seems to be fixed by filling the Beep buffer with zeros when finished and playing the buffer one last time with looping disabled.

I've limited the sample rate to 8K samples per second (sps) with a maximum tone of 4KHz. But I've run the code at 32K sps on a 1 GHz PIII without problems. A sixteen bit PCM word is written out in stereo.

But as with MessageBeep the implementation isn't quite the same as the unmanaged version. The unmanaged Beep puts out a square wave. I create a sine wave and drive the signal to the rails when zero is crossed to generate a square wave. It doesn't sound the same at all frequencies. Some work needs to be done to create the same sound but I like the sine wave myself.

A necessary tool for any development work with pc sound is Cool Edit 2000 from Syntrillium (and for this plug, I fully expect my free version of Cool Edit Pro to be in the mail). An improvement in the sine wave could be made by stopping the sound when it is at zero or by using a low pass filter. The little bit at the end, as shown below, can be heard as a pop.

Sample Image - maximum width is 600 pixels 

Using the code

The only method in the MessageBeep() class is MessageBeep(BeepTypes mbType).

Beep() is called as:  void Beep() or void Beep(double frequency, System.Int32 duration) other methods set frequency, volume, tone duration and turn the square wave mode off and on.

The MessageBeep() function returns immediately and the Beep() function returns when the tone is complete as do the Win32 functions.
The two classes are in the Win32Emu namespace (Emu for emulation).
 

I'm not sure if I've answered the question "Where is the MessageBeep?" to everyone's satisfaction but it's a start.

History<!------------------------------- That's it! --------------------------->

Version 1.1.0.0/030128 -- Initial release.

Ooops. I may have left the crypto key on in the build. Turn it off in your assembly. I'll update later. The frequency for C# in the key of C is 277Hz. I'll put that as the default.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Robert Hinrichs

United States United States
No Biography provided

Comments and Discussions

 
QuestionWhats wrong with System.Media.SystemSounds? Pinmemberblocks10-Aug-10 4:27 
AnswerRe: Whats wrong with System.Media.SystemSounds? [modified] PinmemberRobert Hinrichs16-Sep-10 4:46 
GeneralRe: Whats wrong with System.Media.SystemSounds? Pinmemberblocks16-Sep-10 21:25 
GeneralWin32Emu Pinmemberleishao8724-Oct-09 18:33 
GeneralASUS Eee-PC 904 has no pc-speaker inside Pinmemberbokler18-Mar-09 1:57 
GeneralWindows xp64 Pinmemberzitun24-Sep-08 3:32 
QuestionHow tTo generate(produce) sound in C# using Frequency and intensity PinmemberSharjeelHKhan11-Mar-08 20:33 
GeneralBob's not *my* uncle PinmemberSharpmike21-Nov-05 4:36 
GeneralRe: Bob's not *my* uncle Pinmemberjoelperez31-Mar-09 8:22 
QuestionWhy no sound when run in a thread? PinmemberCPfx3000se30-Jul-05 6:33 
AnswerRe: Why no sound when run in a thread? PinmemberCPfx3000se3-Aug-05 6:28 
GeneralRe: Why no sound when run in a thread? Pinmemberzitun25-Sep-08 22:20 
Generalhelp Pinmembertom_dx7-Nov-04 8:20 
GeneralSimple Interop Alternative PinmemberVictor Boctor21-Aug-04 3:52 
GeneralRe: Simple Interop Alternative Pinsussbob_h21-Aug-04 12:49 
GeneralOverkill PinmemberSledgeHammer11-Apr-03 9:38 
GeneralRe: Overkill PinmemberRobert Hinrichs11-Apr-03 10:23 
GeneralRe: Overkill PinmemberSledgeHammer11-Apr-03 21:37 
GeneralSuggest Statics PineditorHeath Stewart11-Apr-03 2:44 
GeneralRe: Suggest Statics PinmemberRobert Hinrichs11-Apr-03 10:35 
GeneralRe: Suggest Statics PineditorHeath Stewart11-Apr-03 15:49 
GeneralRe: Suggest Statics Pinmemberspratic7-May-04 14:04 
GeneralRe: Suggest Statics PineditorHeath Stewart8-May-04 19:13 
Um, no they don't. Almost every single instance method in the entire .NET FCL documentation states that they are not gauranteed to be thread-safe. Static members are. The only way for instance methods to be thread-safe is to use synchronization contexts like mutexes and monitors. This is all covered in the docs and I speak from several years experience with .NET as well.
 
 
Microsoft MVP, Visual C#
My Articles
GeneralFor a good time... PinmemberRobert Hinrichs10-Feb-03 15:40 
GeneralRe: For a good time... Pinmemberzitun3-Nov-08 23:18 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140721.1 | Last Updated 11 Apr 2003
Article Copyright 2003 by Robert Hinrichs
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid