Click here to Skip to main content
15,867,765 members
Articles / Programming Languages / C#
Article

Managed MessageBeep() in C#

Rate me:
Please Sign up or sign in to vote.
4.97/5 (24 votes)
10 Apr 20034 min read 177.7K   7.3K   50   25
Managed MessageBeep() and Beep() classes in C#

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:

C#
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(</FONT><FONT color=#0000ff size=2>double</FONT><FONT size=2> frequency, System.Int32 duration)</FONT> 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

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


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionWhats wrong with System.Media.SystemSounds? Pin
blocks10-Aug-10 4:27
blocks10-Aug-10 4:27 
AnswerRe: Whats wrong with System.Media.SystemSounds? [modified] Pin
Robert Hinrichs16-Sep-10 4:46
Robert Hinrichs16-Sep-10 4:46 
GeneralRe: Whats wrong with System.Media.SystemSounds? Pin
blocks16-Sep-10 21:25
blocks16-Sep-10 21:25 
GeneralWin32Emu Pin
leishao8724-Oct-09 18:33
leishao8724-Oct-09 18:33 
GeneralASUS Eee-PC 904 has no pc-speaker inside Pin
bokler18-Mar-09 1:57
bokler18-Mar-09 1:57 
so System.Console.Beep() don't works.
Managed MessageBeep is a good solution for this problem.

Thanx
GeneralWindows xp64 Pin
zitun24-Sep-08 3:32
zitun24-Sep-08 3:32 
QuestionHow tTo generate(produce) sound in C# using Frequency and intensity Pin
SharjeelHKhan11-Mar-08 20:33
SharjeelHKhan11-Mar-08 20:33 
GeneralBob's not *my* uncle Pin
Sharpmike21-Nov-05 4:36
Sharpmike21-Nov-05 4:36 
GeneralRe: Bob's not *my* uncle Pin
joelperez31-Mar-09 8:22
joelperez31-Mar-09 8:22 
QuestionWhy no sound when run in a thread? Pin
CPfx3000se30-Jul-05 6:33
CPfx3000se30-Jul-05 6:33 
AnswerRe: Why no sound when run in a thread? Pin
CPfx3000se3-Aug-05 6:28
CPfx3000se3-Aug-05 6:28 
GeneralRe: Why no sound when run in a thread? Pin
zitun25-Sep-08 22:20
zitun25-Sep-08 22:20 
Generalhelp Pin
tom_dx7-Nov-04 8:20
tom_dx7-Nov-04 8:20 
GeneralSimple Interop Alternative Pin
Victor Boctor21-Aug-04 3:52
Victor Boctor21-Aug-04 3:52 
GeneralRe: Simple Interop Alternative Pin
bob_h21-Aug-04 12:49
bob_h21-Aug-04 12:49 
GeneralOverkill Pin
NormDroid11-Apr-03 9:38
professionalNormDroid11-Apr-03 9:38 
GeneralRe: Overkill Pin
Robert Hinrichs11-Apr-03 10:23
Robert Hinrichs11-Apr-03 10:23 
GeneralRe: Overkill Pin
NormDroid11-Apr-03 21:37
professionalNormDroid11-Apr-03 21:37 
GeneralSuggest Statics Pin
Heath Stewart11-Apr-03 2:44
protectorHeath Stewart11-Apr-03 2:44 
GeneralRe: Suggest Statics Pin
Robert Hinrichs11-Apr-03 10:35
Robert Hinrichs11-Apr-03 10:35 
GeneralRe: Suggest Statics Pin
Heath Stewart11-Apr-03 15:49
protectorHeath Stewart11-Apr-03 15:49 
GeneralRe: Suggest Statics Pin
spratic7-May-04 14:04
spratic7-May-04 14:04 
GeneralRe: Suggest Statics Pin
Heath Stewart8-May-04 19:13
protectorHeath Stewart8-May-04 19:13 
GeneralFor a good time... Pin
Robert Hinrichs10-Feb-03 15:40
Robert Hinrichs10-Feb-03 15:40 
GeneralRe: For a good time... Pin
zitun3-Nov-08 23:18
zitun3-Nov-08 23:18 

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

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