Beep Beep


What’s the deal with the Beep() API anyway?

It’s one of the oldest Windows API, dating back to Windows 1.0.  It’s also one of the few audio APIs that my team doesn’t own.  The Beep API actually has its own dedicated driver (beep.sys).  The reason for this is that the Beep() API works totally differently from any other audio API in the system.

Back when IBM built the first IBM PCs, they realized that they needed to have the ability to do SOME level of audio, even if it wasn’t particularly high quality.  So they built a speaker into the original PC hardware.

But how do you drive the speaker?  It turns out that the original PC hardware used an 8253 programmable interval timer to control the system hardware timer.  The 8253 was a pretty cool little chip – it would operate in 5 different modes – one shot timer, interrupt on terminal count, rate generator, square wave generator, software strobe or hardware strobe.  It also contained three independent counters – counter 0 was used by the operating system, counter 1 was reserved for the hardware.  The third counter, counter 2 was special.  The IBM hardware engineers tied the OUT2 line from the 8253 to the speaker line, and they programmed the timer to operate in square wave generation mode.

What that means is that whenever the 2nd counter of the 8253 counted to 0, it would toggle the output of the OUT2 line from the 8253.  This gave the PC a primitive way of generating very simple tones.

The original Windows Beep() API simply fiddled the controls on the 8253 to cause it to generate a square wave with the appropriate frequency, and that’s what Beep.sys continues to do.  Legacy APIs can be hard to remove sometimes 🙂

Nowadays, the internal PC speaker is often also connected to the PCs audio solution, that allows the PC to have sound even when there are no external speakers connected to the machine.

In addition to the simple beep, some very clever people figured out how they could use the 8253 to generate honest to goodness audio, I’m not sure how they succeeded in doing it but I remember someone had a PC speaker based sound driver for DOS available at one point – it totally killed your PCs performance but it DID play something better than BEEEEEEP.

Edit: s/interrupt conroller/interval timer/

Edit2: fixed description of channel 1 (in case someone comes along later and decides to depend on my error).

Comments (44)

  1. Nathan says:

    Believe it or not, Microsoft actually released a Windows 3.1 PC speaker audio driver. I know because at the time I was too poor to afford a sound blaster for my 386-33, but I downloaded that driver from Microsoft (via a long-distance modem call to Redmond, no less) and could play actual low-quality audio through the PC speaker, both wav and MIDI.

  2. Eric says:

    At least a few motherboard manufacturers have taken advantage of the PC Speaker in similar ways; I have a Soyo board that, if it experiences a problem during POST (i.e. doesn’t find a keyboard or video card/monitor) will actually tell you so, in very robotic but understandable English (or Chinese, if you flip a jumper on the board).

    It spooked my wife out the first time I turned it on with no video card in the box. 😉

  3. Mark Steward says:

    You mean Windows 98? See http://support.microsoft.com/kb/q138857/

    A little scratchy, but works well on low-end machines – I loved that Windows 3.1 on my 16 MHz 286 could play the Windows ’95 startup sound!

    (I’ve since put a network and sound card in and it runs RDP over a wireless bridge to XP, but that’s another story…)

  4. Ricky Dhatt says:

    I remember using the PC Speaker driver for Win 3.1. You can still get it for Win95/98/ME:

    How to Install and Use the PC Speaker Driver with Windows

    http://support.microsoft.com/kb/q138857/

  5. I actually wrote a program that could play music in seven parts using just the PC speaker. Fifteen years ago; time flies! I made it play a movement of a Bach concerto, with a duration of ten minutes. It was a pure DOS program, however, and I had to disable all interrupts when it played, since I used the stack pointer in the code…

  6. Jeff Parker says:

    Hah, this brings back some good memories. Some co workers late one evening deep in the vault of the server room. One programmer (me) upstairs know about this and knows how to make it run different tones different lengths. Imagine their puzzlement as a server starts beeping, like an alarm, then as they are looking to see which one is an alarm (I am watching them log into the terminals from terminal services) then as they get close to the server beeping I start playing Yankee Doodle Dandy.

  7. Sean McLellan says:

    I remember back in the day a few games and a actually capitalized on the sound driver feature.. From what I remember there was a game called World Class Leaderboard Golf made by Access Software (which was later acquired by Microsoft for the Links series) had something they licensed or developed called "RealSound" which had pretty decent audio (for the time) though the PC speaker

    Used to get a thrill on that old 8086 playing Leaderboard Golf (WCLB.exe) and acually hearing a metalliac "I think he hit a tree, Jim" from the PC speaker.

    Most of the audio at that time was the bleeps and bloops of monotone sound — and if you were lucky enough to have an AdLib card, some rudimentary midi audio…

    Also recall that there was also a freeware sound driver for Windows 3.0 that someone hacked together which would allow to use the PC speaker as a wave audio device..

    Thanks for the trip down memory lane 😉

  8. Dan McCarty says:

    I remember that program, too. IIRC, it wasn’t a driver, but an actual program that would let you load sound files (its own custom format, I think) and play them through the PC speaker. I wish I could remember it’s name.

    I was in college at the time, and after 10 years of hearing PC be-boops I was blown away when I first heard it. But as my EE friend explained to me, why shouldn’t it be hard to do? It’s a speaker!

    ‘Course, anyone worth their salt back then had a Sound Blaster anyway. 😉

  9. Dan McKinley says:

    That’s all very interesting. I’m sitting next to a girl using the MySQL command line interface, which happens to call this API every time she mistypes a query.

    So my question is, does anyone know a good way to destroy beep.sys and/or physically disable the PC speaker?

  10. Ben Cooke says:

    I use a program right now that uses the Beep() function. It takes several remote desktop windows and hides them away, and then exposes them in response to certain key sequences. This is intended to emulate a KVM switch in software.

    To switch to a different desktop requires you to hit a trigger key twice and then hit a number from the numeric row on the keyboard. When you hit the trigger key it plays a low-pitch acknowledgement, and then in response to a recognised command it plays a high-pitch acknlowledgement. It sounds a bit like "bloop blooop, bleeeep!", and uses the Beep() API. It maybe old, but it’s handy!

    Beep(500, 50);

    Beep(500, 50);

    Beep(2000, 50);

    I remember a sound driver for Win9x which exposed the internal speaker as a wave device. That was a neat hack. I don’t know of any similar neat hacks on NT, though.

  11. Purplet says:

    Incidentally I wrote one of them (actually mine was a DOS program to listen wav files).

    The way it worked was actually simple (well depends on your concept of simple).

    If I remember well it hooked the IRQ 0 (the timer) which was pumped to very high frequency (the trick was to daisy chain to the old handler at about its expected frequency). That handler simply downsampled the wav to 1 bit (I used an algorithm I found which was used to downsample bitmaps). Then it drove the speaker as if it were a switch driving it to its two extremes (it was simply an out on some arcane I/O port…). The sound was not that great, but the inertia of the speaker’s membrane was helping to reduce the artifacts of downsampling anyway.

    Incidentally I used Summer of 69 of Bryan Adams to test because it was the only wave I had at the time (a friend ripped it for me, I had not a CD drive at the time). Now I’ve written audio code many times and I always used that song for testing 🙂

  12. I have some classic Infosys games that actually played music over the PC speaker…

    StickyKeys’ notification sound comes over the PC speaker on my machine. Does it use Beep? It’s particularly annoying since I work in a cubicle environment and most sound from my computer goes through my headphones.

  13. Michael Quinlivan says:

    Just a minor correction, I think you meant to say "Programmable Interval Timer", not "Programmable Interrupt Controller"

  14. Maurits,

    Funny you should mention that :)….

    StickyKeys is Monday’s post 🙂

  15. Roman says:

    Actually, port 1 was not available for applications. It was used for driving RAM refreshing cycles. By increasing the divider in channel 0x1 the memory could be "overclocked" by the virtue of decreasing the chances of the memory bus being busy with refreshing. The downside was — you guessed it right — risk of loosing data.

    This channel was not used in PS/2 and later models, and there was no access to it’s output (not documented, at least)

  16. jeuge says:

    Does printf("7") work the same way as Beep()

    -Jeu George

  17. Moz says:

    I get "translation" of beeps by Virtual PC (and VMWare) from the virtual machine out to the audio card of the host machine. It is phenominally annoying, as I habitually use my audio player to control the volume… so every now and then I get a violently loud beep from the client. I can’t disable this by disabling/uninstalling the system.speaker either!

  18. ShadowChaser says:

    One of my first applications written when I was very young was in the QBasic interpreter that shipped with MSDos.

    Played different tones over the PC Speaker in a loop. At the time I found it fairly interesting 🙂

    Interesting enough, up until a few days ago, the .NET framework only had a single Beep() API via the one of the VB assemblies. I spent today ripping out my Interop calls to the wav-based ‘system beeps’ and moving them to .net 2.0.

    Thanks for the great post!

  19. Jonathan says:

    in CMD, type "echo ^g" (^g mean you click CTRL-G, not Shift-6 G) – you’ll get a beep, presumably a Beep(). I use it all the time to get notified when some log command finishes:

    xcopy bla & echo ^g

  20. David Powell says:

    "net stop beep" will silence the beeper.

    Ideal for when you’ve just accidentally listed several pages of 0x07 rich binary to the console.

  21. daz says:

    for the guy sitting next to the beeping girl – net stop beep should solve your problem 🙂

  22. Centaur says:

    I remember a DOS driver that used i386’s protected mode to emulate a Sound Blaster on either PC Speaker or Covox. Covox was a simple 8-bit DAC which was plugged into an LPT port, and gave much better sound than 1-bit PC Speaker. Performance-wise, yes, it was a nightmare.

  23. Marcel says:

    I remember stumbling accross the beep command while porting a DOS app to Windows (an emulator for an old computer. The PC speaker was to emulate its sound). On 9x one could still use the ports to control the speaker, but on NT beep was the only way. Back then the MSDN docs said "if passed 0 for duration, the call will immediatelly return while the beep keeps playing" or something like that. Perfect! Exactly what I needed! Except, it didn’t work. The disassembly showed that value 0 is handled specially, but the jump went directly to the "kill beep" code sequence…

    Somewhat later it was fixed. Not the buggy driver, of course, the doc just didn’t mention the 0 value anymore. :-/ That’s why my app stayed silent on NT until years later I finally mustered the courage to write some fairly complex DirectSound code to fix it.

  24. RolfBjarne says:

    thanks for "net stop beep", it saved my night!

    but why doesn’t "beep" appear as a service when I do "net start"?

  25. "beep" is a driver (beep.sys). The "Net stop" command can be used to stop both drivers and services (loosely speaking, the service controller is responsible for starting drivers)

  26. Phaeron says:

    The way programs generated high-quality audio was to kick timer 2 into one-shot mode instead of the regular square-wave mode, then drive it from IRQ0 at sampling rate, varying the width of the output pulses based on the sound samples. The result was a reasonably good ~6-bit reproduction of the sound, along with the sampling rate frequency. Raising the timer rate high enough (22KHz+), along with the inertia of the speaker, made the latter inaudible. If you were unlucky enough to have a piezoelectric speaker, through, the scheme didn’t work.

    One really nice feature of this scheme was that the sound ran in the background like real sound hardware, and the interrupt routine was fast enough to still allow foreground tasks. You could set up a "DMA buffer" along with read/write pointers and soft interrupts back to the main code, and treat it much like any other sound card. I once wrote a video player for DOS this way. It became very clear if other drivers were spending too much time with interrupts disabled, however. It also didn’t work on most DOS emulation environments due to interrupt handling latency, although impressively it _almost_ worked in an OS/2 DOS box.

  27. Miral says:

    Hey, does that mean that if my video card / network card drivers have gone weird that I can "net stop"/"net start" them to reset them without rebooting?

  28. Miral, you can try, but I’m willing to bet that it won’t work.

    The video card driver is loaded by win32k.sys, the only way to unload/reload that is by rebooting the machine.

    The network stack can be unloaded but that assumes that every app that uses it knows how to deal with PnP notifications – most don’t

  29. Norman Diamond says:

    The correct way to generate computer music in the old days was to put an AM radio next to the CPU. And yes there were programs for some machines that execute various loops the right number of times to cause some transistor somewhere to send out the right kind of EMI to do it.

    The correct way to turn off sound on such a machine was to rotate the AM radio’s volume control all the way to the left.

    On a more modern machine, if it’s a desktop machine then you can open the case and pull the speaker off of its jumpers. If it’s a notebook machine then you can open the case and use some diagonal cutters.

  30. Norman, that trick didn’t work with the IBM PC, it was too well shielded.

    The TRS-80, on the other hand…..

    I had a friend in college who had a TRS-80 and he showed how he could make music on his stereo with it.

  31. ScottR says:

    On my first day of work at NCR (1980), I walked up to the console of the mainframe and, since all the terminals in college made a beep when you pressed control-g, I pressed control-g.

    Unfortunately, on this particular NCR mainframe, it invoked the debugger and stopped the machine.

    Which several people were actually USING at the time.

  32. Daniel says:

    Like a lot of other features in the IBM PC, the speaker requirement probably was to be better then the Apple ][.

    On the Apple ][ there was no timer chip, just a bit that the software could toggle. And I remember a game called Karateca, playing music while horizontally scrolling a "high res" background…

    Daniel

  33. Donald Payne says:

    Thank you for "net stop beep"!

    I didn’t find this _anywhere_ else.

    The beep from an MS-DOS app (e.g. running choice.com and pressing invalid key) was REALLY LOUD, even when the Windows volume control (in systray) was way low on my laptop. A Windows "ding" at the proper Windows volume would be better, but this is a big improvement. (I’m running Windows 2000.)

    FYI, if beeps bother you, I found another page

    <http://www.annoyances.org/exec/forum/winxp/1054090503&gt;

    (works in Win 2000 also) that fixed a problem where the volume control slider in the system tray gave a BEEP at full volume whenever I adjusted it. Now it makes a nice "ding" at the selected volume.

  34. I came across the speaker trick in a DDJ article 11 years ago. However the absense of Internet in India at that time meant that I could not get my hands on the sample code. I searched around and the closest I got to was a program called "Scream Tracker" that played mod files on the PC Speaker. Spending some time reverse engineering ST, and I got a good example for the DDJ article.

    I ended up writing a wav file player for DOS on the PC Speaker that would playback Stereo/Mono,16 bit or 8 bit .WAV files. The resolution was around 6 bits and I had a table which could downconvert 8 bits to 6 bits of audio. Unfortunately I put too many anti-debugging checks in there (stack tricks, pre-fetch queue and all) so it will no longer work. I remember showing it off to a non-techie friend at that time. He wasn’t impressed. "My Radio has more clarity than that", was his response :-).

    I remember that I optimized the code sufficiently to be able to even get it to work on a PCT XT @10 Mhz. The biggest pain I had wa s the IDE interrupting the timer when reading the wave file. The audio suffered even though I was double buffering. I finally solved the problem by using XMS api’s to cache the entire wave file in memory before playback.

    The old program is still available here http://www.xtendtech.com/rpm i.e. If you still have a PC XT@ 10 Mhz or higher running DOS 🙂

  35. Rune Moberg says:

    Quote: "From what I remember there was a game called World Class Leaderboard Golf made by Access Software (which was later acquired by Microsoft for the Links series) had something they licensed or developed called "RealSound" which had pretty decent audio (for the time) though the PC speaker"

    Sean, Access also made other games, most notably "Mean Streets" that was one of the first VGA games IIRC, and it too used RealSound. It had decent graphics even for those of us stuck with EGA, and the sound was indeed playable! 🙂 I think they did a remake of that game, but I never got around checking it out. "Mean Streets" was an adventure game with a good exciting story. Can’t get games of that caliber today! :/

  36. Fred Dearhart says:

    Larry,

    I am not a programmer and know just enough hardware to be dangerous. I have a dos application that runs ok in 98 dos window but does not generate the beep supervisory tones while in the dos window or booted in dos mode. How do I get the program to connect to the windows audio card ( soft solution). I have been making a 10 to 1 dc isolated divider at the speaker and connecting to the aux input or the line in jack to make the trip. The later computer mother boards no longer use a speaker creating a problem for me. Can you guys help??

    Mrfx2001@comcast.net

  37. matt pileggi says:

    Thanks for the ‘net stop beep’ command! I was searching for exactly that. One day while plugging away merrily in mysql command-line with my headphones on, I nearly vomited after entering invalid sql. The beep was so loud that even after I removed my headphones it played through my small earbuds louder than my pc speakers are usually set.

    Another nifty side effect I noticed was that encountering the same beep without my headphones plugged in caused the beep sound to overload my laptop’s speakers and actually shutdown my machine (2005 Dell Inspiron). How’s THAT for a bad sql error!

    For you ms batch masters out there, is there a way to ensure that ‘net stop beep’ gets run each time I open up a dos window in XP?

  38. cool! now if only it would act as a real "Sounds and Audio Devices"!

    I have a c****** laptop running windows 98, and the sound card doesn’t work ("Device not present or drivers not loaded" error?)

    So i went around looking for some sort of driver to use the PC Speaker (worked…)

  39. Was mein Vista momentan an Ton zu wenig hat, das hat mein Dienstnotebook zu viel: Ton. Ständig piept einen der interne PC-Lautsprecher (oder seine heutige Entsprechung) an, wenn man sich vertippt, verklickt, vertut… Und das Ganze in einer Lautstärk