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
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
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]
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
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.
<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
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/
PlaySound is not complicated. It requires only a single line of
coding:
PlaySound(...,SND_RESOURCE|SND_ASYNC);
You should use it.
--
Lucian
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
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
Use the waveOutXXX functions.
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
"Lucian Wischik" <lu...@wischik.com> wrote in message
news:1aon8v0jhisqp4ilj...@4ax.com...
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
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
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
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
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...
<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.
> 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
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 :)