Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Asynchronous Beep?

1,206 views
Skip to first unread message

Timo

unread,
Mar 28, 2003, 8:31:51 AM3/28/03
to
I have some difficulties trying to figure out how to produce
asynchronous
Beep under Win32 (Windows 2000). The Beep function seems to be
synchronous.
Because of the nature of my application, at the moment when the beep
is
started, it's duration is not yet know. The duration depens on certain
event.
And also the UI of my application shouldn't freeze while producing
long beeps.

One way to do this might be to start a backround thread which calls
the
Beep function, and lets my WndProc to keep processing messages, but
this
doesn't actually solve the unknown beep duration problem. Producing a
long
enough Beep and then killing the Beep thread might do the trick, but
killing
a thread is propably not a good idea, because it may left some system
resources unallocated.

There also seems to be function
PlaySound(LPCSTR pszSound, HMODULE hmod, DWORD fdwSound), which could
be propably used, but it requires that the beep sound is in
a file. I have several frequencies I need to play, so this means I
should
create WAV files containing beeps for each frequency used in my app.

The durations of the beeps should be quite accurate also, shortest
should be
5 ms and longest about 1 second. Don't know how much there is delay
when PlaySound is called, in WAV file loading etc, until the sound
actually starts
to play.

Timo

Mads Orbesen Troest

unread,
Mar 28, 2003, 12:21:13 PM3/28/03
to
> I have some difficulties trying to figure out how to produce
> asynchronous Beep under Win32 (Windows 2000).

You can been Beep from a separate thread.

> enough Beep and then killing the Beep thread might do the trick, but
> killing a thread is propably not a good idea, because it may left some
system
> resources unallocated.

Huh? You don't need to kill the thread; let it beep synchronously and then
exit. Simply launch the async beep on a separate thread that exists when
Beep returns.

/\/\\ads Orbesen Troest


Scott McPhillips

unread,
Mar 28, 2003, 6:40:51 PM3/28/03
to

You can make your own beep tone using the waveOut... APIs, although it
will be much more complicated than calling Beep. WaveOutReset will stop
the beep, so you won't have to know the duration at the start. With
some sound cards it will stop on command, with others it will stop when
it gets to the end of the currently playing audio buffer. You can
output multiple buffers to waveOutWrite and it will play them in
sequence, so making many small buffers will reduce the possible stop
latency. The duration of the beep will be extremely accurate if it is
an integral number of audio buffers.

--
Scott McPhillips [VC++ MVP]

Lucian Wischik

unread,
Mar 29, 2003, 2:42:41 AM3/29/03
to
t_i_m_...@yahoo.com (Timo) wrote:
>There also seems to be function
>PlaySound(LPCSTR pszSound, HMODULE hmod, DWORD fdwSound), which could
>be propably used, but it requires that the beep sound is in
>a file.

It doesn't. You should use SND_ASYNCHRONOUS | SND_MEMORY and play it
from memory. Or SND_RESOURCE to play it from a resource. My instinct
would be to create memory blocks of the right frequency and then play
them from memory. You can use PlaySound(NULL) to stop it.

>The durations of the beeps should be quite accurate also, shortest
>should be 5 ms and longest about 1 second.

I don't think you'll achieve 5ms accuracy if you rely on
PlaySound(NULL). Can't tell you why, it's just my instinct. To get
accurate lengths, I think you should make the original sound file (or
memory block or resource) that length.

--
Lucian

Alex Blekhman

unread,
Mar 29, 2003, 4:06:34 AM3/29/03
to
"Lucian Wischik" <lu...@wischik.com> wrote in message
news:lcja8vcttuf15sbhf...@4ax.com...

I noticed in debugger that PlaySound _allways_ starts new thread to
play a sound. Even if I specify SND_ASYNCHRONOUS flag. For first time
you have noticeable delay before hearing a sound. Probably
initializing some multimedia stuff. Then on subsequent calls thread is
started much faster. However, it started per each call to PlaySound
anyway.


Timo

unread,
Apr 1, 2003, 9:22:14 AM4/1/03
to
t_i_m_...@yahoo.com (Timo) wrote in message news:<9b5d49a8.03032...@posting.google.com>...

> I have some difficulties trying to figure out how to produce
> asynchronous
> Beep under Win32 (Windows 2000). The Beep function seems to be
> synchronous.
> Because of the nature of my application, at the moment when the beep
> is
> started, it's duration is not yet know. The duration depens on certain
> event.
> And also the UI of my application shouldn't freeze while producing
> long beeps.
>
> One way to do this might be to start a backround thread which calls
> the
> Beep function, and lets my WndProc to keep processing messages, but
> this
> doesn't actually solve the unknown beep duration problem. Producing a
> long
> enough Beep and then killing the Beep thread might do the trick, but
> killing
> a thread is propably not a good idea, because it may left some system
> resources unallocated.

<CLIP>

The PlaySound and waveOut* functions appeared to be a little bit too
complicated and requiring too much coding, so I created a quick&dirty
solution: I used CreateThread to start a backround thread which calls
Beep for a duration longer than any beep in my app. After an event
has occurred which means that Beep should be ended, I call
TerminateThread
on that thread, and after that also Beep(0,0), because otherwise the
Beep sound
is still being produced.

This seems to be fairly fast, although at short durations (5 ms or
so), the
Beep thread hasn't managed to even start when it is time to kill it. I
"fixed" this with starting a timer which kill my Beep thread 5 ms
later.
Ugly but it seems to be working. ;)

However, MSDN warns about TerminateThread function:

"TerminateThread is a dangerous function that should only be used in
the most extreme cases. You should call TerminateThread only if you
know exactly what the target thread is doing, and you control all of
the code that the target thread could possibly be running at the time
of the termination."

I only call Beep in my thread function, don't do any mallocs etc.
However,
I am not absolutely sure whether Beep allocates some resources.

I will propably try the PlaySound function later, when/if I have more
time.

Timo

Tim Robinson

unread,
Apr 1, 2003, 6:37:44 PM4/1/03
to
"Timo" <t_i_m_...@yahoo.com> wrote in message
news:9b5d49a8.03040...@posting.google.com...

> However, MSDN warns about TerminateThread function:
>
> "TerminateThread is a dangerous function that should only be used in
> the most extreme cases. You should call TerminateThread only if you
> know exactly what the target thread is doing, and you control all of
> the code that the target thread could possibly be running at the time
> of the termination."
>
> I only call Beep in my thread function, don't do any mallocs etc.
> However,
> I am not absolutely sure whether Beep allocates some resources.

Don't use TerminateThread. Ever*. It's not about allocating resources or
malloc; it's about the fundamental stability of your application, and maybe
Windows as a whole. Anything your thread is doing at the time
TerminateThread is called is stopped -- not cleanly, but forcibly.

Notice how you have to call Beep(0, 0) to stop the sound after calling
TerminateThread. This is because the kernel-mode driver, BEEP.SYS, isn't
notified that your thread is being stopped. Whatever I/O request that was in
progress at the time is cut short without having chance to finish. Moreover,
you don't (and can't) know what Beep() is doing; so nobody has any idea what
calling TerminateThread in the middle of a call to Beep does.

In summary: don't do this. Either come up with a way of interfacing to
BEEP.SYS directly (DeviceIoControl? Maybe the Windows DDK will tell you) or
start using PlaySound or the waveXXX functions.

--
* Use TerminateThread when you want to obliterate a thread at all costs. Use
it when the cost of having the thread running is far greater than the side
effects of using TerminateThread.

--
Tim Robinson (MVP, Windows SDK)
http://www.themobius.co.uk/


Lucian Wischik

unread,
Apr 2, 2003, 1:37:08 AM4/2/03
to
t_i_m_...@yahoo.com (Timo) wrote:
>The PlaySound and waveOut* functions appeared to be a little bit too
>complicated and requiring too much coding

PlaySound is not complicated. It requires only a single line of
coding:

PlaySound(...,SND_RESOURCE|SND_ASYNC);

You should use it.

--
Lucian

Timo

unread,
Apr 2, 2003, 8:30:15 AM4/2/03
to
Lucian Wischik <lu...@wischik.com> wrote in message news:<b71l8vgd270iba47s...@4ax.com>...

OK, the next stupid question: ;)
What are the easiest ways to create WAV files of the various beep frequencies
I need in my application?

Timo

Lucian Wischik

unread,
Apr 2, 2003, 8:50:48 AM4/2/03
to
t_i_m_...@yahoo.com (Timo) wrote:
>OK, the next stupid question: ;)
>What are the easiest ways to create WAV files of the various beep frequencies
>I need in my application?

I used a shareware app called "Goldwave" to do this. www.goldwave.com
I guess. It lets you enter an equation for a waveform, and produces
it.

--
Lucian

Carlo Carlini

unread,
Apr 2, 2003, 3:53:15 PM4/2/03
to
I've almost the same Timo's problem.
I should simulate the noise of the engine in my VB6 program.
So I have continuous frequencies and it's impossible to record so many
files.
Fortunately I don't need a real effect (also the BEEP (x,y) would be good
but it's not asyncronous).
I'm able to use only VB, and some API (if well documented on some web site).
Is there any possibility to write to memory and use sndPlaySound without
having recorded 100.000 files?
Thanks.
Carlo


Tim Robinson

unread,
Apr 2, 2003, 6:01:31 PM4/2/03
to
"Carlo Carlini" <carloc...@libero.it> wrote in message
news:%4Iia.1603$DT4....@twister1.libero.it...

> I'm able to use only VB, and some API (if well documented on some web
site).
> Is there any possibility to write to memory and use sndPlaySound without
> having recorded 100.000 files?

Use the waveOutXXX functions.

Lucian Wischik

unread,
Apr 3, 2003, 2:25:43 AM4/3/03
to
"Carlo Carlini" <carloc...@libero.it> wrote:
>Is there any possibility to write to memory and use sndPlaySound without
>having recorded 100.000 files?

Yes, it's easy. But don't use sndPlaySound. Use PlaySound instead.

I wrote this web page:
http://www.wischik.com/lu/programmer/avi_utils.html

It defines the structures that make up a WAV file. So: you should
calculate how large your sound will be, then dynamically allocate a
WavChunk structure of the appropriate size, then fill in the
dat.data[] bytes with your waveform data.

The format of that data will depend on your wBitsPerSample and
wChannels. BitsPerSample will be either 8bit (unsigned) or 16bit
signed. If you have two channels, then each sample is interleaved. The
format of raw sound data is really obvious, but is also explained in
the win32 docs.

Anyway, once you have created your WavChunk data, then just call
PlaySound(SND_MEMORY) on it.

--
Lucian

Carlo Carlini

unread,
Apr 3, 2003, 7:45:15 AM4/3/03
to
dear Lucian I visited your fine web site where I learned that you also stay
in Italy
--- per cui si potrebbe parlare anche in italiano... ;-) ---
but it was only useful to understand how ignorant I am; in fact, as I wrote,
I know only VB and ASM :(
waiting to know if there is any possibility to do the same by API, I'm going
to deepen your examples trying not to drown.
Ciao
Carlo

"Lucian Wischik" <lu...@wischik.com> wrote in message

news:1aon8v0jhisqp4ilj...@4ax.com...

Bob Masta

unread,
Apr 3, 2003, 8:30:48 AM4/3/03
to

You can probably get excellent engine simulations by having a small
circular buffer that stores one "blat" of the exhaust. This is just
going to be a rounded-off rectangle or a fast-decaying sine wave.
Then you just step through that at whatever speed you want the
engine to go. This is a simple example of wavetable synthesis.

Note that you don't have to move in integer-sample steps around
the buffer. You can maintain the buffer pointer as an integer plus
fraction portion, and use a similarly-scaled int.frac step size.
(Use a dword for the integer, and another for the fraction.) Then
you keep adding the step size for each sample, and use only
the integer part of the result to look up the value in the table.


Bob Masta
tech(AT)daqarta(DOT)com

D A Q A R T A
Data AcQuisition And Real-Time Analysis
Shareware from Interstellar Research
www.daqarta.com

Timo

unread,
Apr 3, 2003, 8:58:24 AM4/3/03
to
Lucian Wischik <lu...@wischik.com> wrote in message news:<b71l8vgd270iba47s...@4ax.com>...

> t_i_m_...@yahoo.com (Timo) wrote:
> >The PlaySound and waveOut* functions appeared to be a little bit too
> >complicated and requiring too much coding
>
> PlaySound is not complicated. It requires only a single line of
> coding:
>
> PlaySound(...,SND_RESOURCE|SND_ASYNC);

I downloaded GoldWave and managed to create WAV files containing Beeps
of the frequencies needed in my app, with the GoldWave's expression
evaluator and sine function.

However, PlaySound is causing me some troubles.
I start playing the sound this way:
soundRet = PlaySound(sndFileName, NULL,
SND_FILENAME | SND_ASYNC | SND_NODEFAULT);

1. There seems to be too much delay between the moment I call the
function
and when the sound actually starts to play. Much more than with Beep
function.
I can't accept this since my app should react fairly fast to user
input and other events.

2. When I start to play new WAV file (after first stopping the
previous
play), for a very short duration, PlaySound plays the sound from
previous file. This can be heard as very rapid change of frequency in
my beep sound. Not good. ;(

3. PlaySound doesn't return error code, even when I specify name of
non-existing filename. It always returns TRUE.

BTW, I stop the playing of sound this way:
soundRet = PlaySound(NULL, NULL, SND_FILENAME | SND_ASYNC | SND_LOOP
);

Would PlaySound be faster if I play sound from resource? How can I put
my WAV files to Windows resources?

What if I play the sound directly from memory instead of file?
PlaySound
seems to support this with the SND_MEMORY flag. However, I have no
idea
how to load WAV file into memory. I checked the wave* functions from
MSDN
but couldn't figure it out.

BTW, I am using Windows 2000, if that matters.

Any help would be greatly appreciated.
BR,
Timo

Lucian Wischik

unread,
Apr 3, 2003, 9:12:41 AM4/3/03
to
t_i_m_...@yahoo.com (Timo) wrote:
>What if I play the sound directly from memory instead of file?
>PlaySound seems to support this with the SND_MEMORY flag. However, I have no
>idea how to load WAV file into memory.

HANDLE hf = CreateFile(fn,... OPEN_EXISTING);
DWORD size = GetFileSize(hf,NULL);
char *buf = new char[size];
DWORD red; ReadFile(hf,buf,size,&red);
CloseHandle(hf);
...
delete[] buf;

My impression was that PlaySound was slow the first time you call it
(when it loads up the subsystem) but is faster on subsequent calls. So
at application startup time, you could try playing a silent sound just
to load it.

--
Lu

Timo

unread,
Apr 3, 2003, 10:19:51 AM4/3/03
to
Lucian Wischik <lu...@wischik.com> wrote in message news:<b71l8vgd270iba47s...@4ax.com>...

Darn, groups.google.com is so slow to update, so I can't yet followup
to my
previous posting. ;)

However, I was thinking too complicated again, to get WAV file to
memory
is simple, just malloc big enough buffer, use fopen and fgetc to read
the WAV
data to that memory block, and use parameter SND_MEMORY with
PlaySound. However,
there is still too much latency when starting to play the sound. I
guess using
Windows resources as WAV sources wouldn't help either.

And I still have the strange sound problems I mentioned in my previous
post,
when PlaySound is called for new file, old sound file is played for a
few millisecond. This also applies to any sound Windows is creating,
for example when other application beeps after I have used my
PlaySound app, at the start of the other app's beep I can hear the
previous WAV file sound for a few
milliseconds. Very strange indeed! :-o

Timo

Carlo Carlini

unread,
Apr 3, 2003, 4:19:49 PM4/3/03
to
As I don't think to be able to handle too complicated program steps (if I
cannot find easy documentation) I'm using a rough solution that seems to
agree with your tip:
I've seen that the file that I need has an initial "blat" and a variable
pause (according to RPM of the engine). It has this look:

RIFFO WAVEfmt @ @ datah
?ÿÿÿÿÿÿÿÿ????????????????????????????????????????????????????

If I add more ??? I get a lower RPM sound.
So I think I will create a different file, in real time, for each different
RPM and I'll load it using PaySound in loop. I know that it would be better
accessing the memory but I suppose it's too complicated for me. :(


"Bob Masta" <no_...@aol.com> wrote in message
news:3e8c361c...@news.itd.umich.edu...

Timo

unread,
Apr 4, 2003, 4:00:57 AM4/4/03
to
t_i_m_...@yahoo.com (Timo) wrote in message news:<9b5d49a8.03040...@posting.google.com>...

<CLIP>

> 2. When I start to play new WAV file (after first stopping the
> previous
> play), for a very short duration, PlaySound plays the sound from
> previous file. This can be heard as very rapid change of frequency in
> my beep sound. Not good. ;(

I tested this on another PC running Windows NT 4.0, and this problem
doesn't occur there. But it seems to happen in Windows 2000.

Timo

unread,
Apr 4, 2003, 4:03:49 AM4/4/03
to
Lucian Wischik <lu...@wischik.com> wrote in message news:<u7go8vo682o36vc3t...@4ax.com>...

> My impression was that PlaySound was slow the first time you call it
> (when it loads up the subsystem) but is faster on subsequent calls. So
> at application startup time, you could try playing a silent sound just
> to load it.

I noticed that PlaySound is slow _every_ time it is called. Both in
Windows 2000 and Windows NT. This is not acceptable! ;(

What other options do I have left to produce asynchronous Beep with
fast response time? Maybe some DirectX programming etc? How can such
a simple task seem to be causing so much trouble? ;)

Timo

Scott McPhillips

unread,
Apr 4, 2003, 8:06:47 AM4/4/03
to
Timo wrote:
> I noticed that PlaySound is slow _every_ time it is called. Both in
> Windows 2000 and Windows NT. This is not acceptable! ;(
>
> What other options do I have left to produce asynchronous Beep with
> fast response time? Maybe some DirectX programming etc? How can such
> a simple task seem to be causing so much trouble? ;)
>
> Timo

Expecting this to be simple is unrealistic. Audio reproduction is a
real-time process that you are trying to do on a non-realtime operating
system. And your need for low latency (start time) is the thing Windows
is just about the worst at. You can use WaveOut or DirectSound APIs to
produce low latency audio tones without needing to access files. You
will have to create buffers containing the audio tone (sine waves) and
output several of them so the device driver can seamlessly transition
from one buffer to the next. I only have experience with the waveOut
APIs so don't know which approach would be better for you. Study them
both :)

0 new messages