|
|
|
date: Fri, 4 Jul 2008 12:20:08 +0100,
group: microsoft.public.win32.programmer.mmedia
back
Tone generation
Hi all,
I succeeded creating a simple procedure to make and play sine, square or
triangle waves at given frequency and duration.
Now I'm searching, without results, for a method to play two or more tones
together. I tried to open two instances of my little program, passing
different frequences, and effectively it plays two tones together, but every
.exe file should: open the wave device and write the datablock of the tone.
Is there a method to play two tones togeter, opening the wave device only a
time in te program?
Thanks
P.S.: In the perspective that I'll create a class to play tones, what do you
think about tone duration handling? Should I use a timer in the class to
handle duration? Should I directly prepare a datablock for a tone with a
specified duration? Or should I just implementate playtone and stoptone, and
let the user to handle a timer for playing and stopping tones, to simulate
specified duration?
Thanks again
Fabio De Dominicis
date: Fri, 4 Jul 2008 12:20:08 +0100
author: Fabio De Dominicis
Re: Tone generation
"Fabio De Dominicis" wrote in message
news:486e0a59$0$41665$4fafbaef@reader4.news.tin.it...
> Hi all,
> I succeeded creating a simple procedure to make and play sine, square or
> triangle waves at given frequency and duration.
> Now I'm searching, without results, for a method to play two or more tones
> together. I tried to open two instances of my little program, passing
> different frequences, and effectively it plays two tones together, but
> every
> .exe file should: open the wave device and write the datablock of the
> tone.
> Is there a method to play two tones togeter, opening the wave device only
> a
> time in te program?
> Thanks
> P.S.: In the perspective that I'll create a class to play tones, what do
> you
> think about tone duration handling? Should I use a timer in the class to
> handle duration? Should I directly prepare a datablock for a tone with a
> specified duration? Or should I just implementate playtone and stoptone,
> and
> let the user to handle a timer for playing and stopping tones, to simulate
> specified duration?
> Thanks again
> Fabio De Dominicis
to play 2 tones from one program you just add them sample by sample and
divide by 2.
date: Fri, 4 Jul 2008 18:11:01 -0000
author: Dave
Re: Tone generation
"Dave" ha scritto nel messaggio
news:%23UcHDFg3IHA.1192@TK2MSFTNGP05.phx.gbl...
>
> "Fabio De Dominicis" wrote in message
> news:486e0a59$0$41665$4fafbaef@reader4.news.tin.it...
>> Hi all,
>> I succeeded creating a simple procedure to make and play sine, square or
>> triangle waves at given frequency and duration.
>> Now I'm searching, without results, for a method to play two or more
>> tones
>> together. I tried to open two instances of my little program, passing
>> different frequences, and effectively it plays two tones together, but
>> every
>> .exe file should: open the wave device and write the datablock of the
>> tone.
>> Is there a method to play two tones togeter, opening the wave device only
>> a
>> time in te program?
>> Thanks
>> P.S.: In the perspective that I'll create a class to play tones, what do
>> you
>> think about tone duration handling? Should I use a timer in the class to
>> handle duration? Should I directly prepare a datablock for a tone with a
>> specified duration? Or should I just implementate playtone and stoptone,
>> and
>> let the user to handle a timer for playing and stopping tones, to
>> simulate
>> specified duration?
>> Thanks again
>> Fabio De Dominicis
>
> to play 2 tones from one program you just add them sample by sample and
> divide by 2.
>
Well done, thanks: I succeeded! So I can deductively say that to obtain n
tones together, it's enough to sum them sample by sample and to divide the
result by n.
Ok, now.....
I'm introducing loop in my program, using the waveout interface loop flags.
I have a problem:
during looping, I hear some ticks during the sound. Sure the ticks are
caused from looping (in the moment that the sound finishes and restart
again). Can I avoid this ticks?
Here is the code I use to generate sine waves, I post here the procedure to
fill a buffer, sent after through the waveoutwrite api.
It generates 2 tones together, but if I set looping flags, I hear ticks:
VOID FillBuffer (PBYTE pBuffer, int iFreq){
double fAngle, angle1;
int f1=iFreq+220;
int i ;
for (i = 0 ; i < 4096 ; i++){
pBuffer[i] = (BYTE) 127 + (127 * sin(fAngle) + 127 * sin(angle1))/2;
fAngle += 2 * 3.14 * iFreq / 11025;
if (fAngle > 2 * 3.14) fAngle -= 2 * 3.14 ;
angle1 += 2 * 3.14 * f1 / 11025;
if (angle1> 2 * 3.14) angle1 -= 2 * 3.14;
}
}
What I should adjust to avoid ticks?
Thanks
date: Sat, 5 Jul 2008 00:35:48 +0100
author: Fabio De Dominicis
Re: Tone generation
"Fabio De Dominicis" wrote in message
news:486ea5fe$0$35957$4fafbaef@reader2.news.tin.it...
>
> "Dave" ha scritto nel messaggio
> news:%23UcHDFg3IHA.1192@TK2MSFTNGP05.phx.gbl...
>>
>> "Fabio De Dominicis" wrote in message
>> news:486e0a59$0$41665$4fafbaef@reader4.news.tin.it...
>>> Hi all,
>>> I succeeded creating a simple procedure to make and play sine, square or
>>> triangle waves at given frequency and duration.
>>> Now I'm searching, without results, for a method to play two or more
>>> tones
>>> together. I tried to open two instances of my little program, passing
>>> different frequences, and effectively it plays two tones together, but
>>> every
>>> .exe file should: open the wave device and write the datablock of the
>>> tone.
>>> Is there a method to play two tones togeter, opening the wave device
>>> only a
>>> time in te program?
>>> Thanks
>>> P.S.: In the perspective that I'll create a class to play tones, what do
>>> you
>>> think about tone duration handling? Should I use a timer in the class to
>>> handle duration? Should I directly prepare a datablock for a tone with a
>>> specified duration? Or should I just implementate playtone and stoptone,
>>> and
>>> let the user to handle a timer for playing and stopping tones, to
>>> simulate
>>> specified duration?
>>> Thanks again
>>> Fabio De Dominicis
>>
>> to play 2 tones from one program you just add them sample by sample and
>> divide by 2.
>>
> Well done, thanks: I succeeded! So I can deductively say that to obtain n
> tones together, it's enough to sum them sample by sample and to divide the
> result by n.
> Ok, now.....
> I'm introducing loop in my program, using the waveout interface loop
> flags. I have a problem:
> during looping, I hear some ticks during the sound. Sure the ticks are
> caused from looping (in the moment that the sound finishes and restart
> again). Can I avoid this ticks?
> Here is the code I use to generate sine waves, I post here the procedure
> to fill a buffer, sent after through the waveoutwrite api.
> It generates 2 tones together, but if I set looping flags, I hear ticks:
>
>
> VOID FillBuffer (PBYTE pBuffer, int iFreq){
>
> double fAngle, angle1;
>
> int f1=iFreq+220;
>
> int i ;
>
> for (i = 0 ; i < 4096 ; i++){
>
> pBuffer[i] = (BYTE) 127 + (127 * sin(fAngle) + 127 * sin(angle1))/2;
>
> fAngle += 2 * 3.14 * iFreq / 11025;
>
> if (fAngle > 2 * 3.14) fAngle -= 2 * 3.14 ;
>
> angle1 += 2 * 3.14 * f1 / 11025;
>
> if (angle1> 2 * 3.14) angle1 -= 2 * 3.14;
>
> }
>
> }
>
> What I should adjust to avoid ticks?
>
> Thanks
>
>
there are 2 possible causes of ticks.
1. making windows wait for the next buffer. if you only use one buffer then
windows has to wait while you refill it before it can continue playing.
2. a discontinuity in the waveforms at the end of a looped buffer (this is
likely your problem). This happens because there is not a smooth transition
at the end of a buffer. consider this, a single sine wave fills up a buffer
such that it starts at zero degrees. if exactly one cycle fits in the
buffer then when it ends and restarts there is a nice smooth transition.
But, lower the frequency of that wave so now there is not a full cycle in
the buffer, a the end of the buffer the partial wave won't be back at zero
so when the buffer starts over again there is a discontinuity... that makes
a tick. This is easy to fix for a single frequency, just make the buffer
length a multiple of the number of samples needed for a full cycle. When
mixing multiple frequencies it quickly becomes a problem though.
The ultimate fix for #2 and #1 is to learn how to use multiple buffers so
you can play one while filling the other and then alternate for as long as
you need to keep it playing. This makes sure that there is no gap in
playing, and also eliminates the unmatched end effects by never ending the
computation of the waveform... so this lets you generate an arbitrary number
of waveforms added together without the problem of making sure they are all
back to the beginning at the end of the buffer.
date: Sat, 5 Jul 2008 11:55:32 -0000
author: Dave
Re: Tone generation
On Sat, 5 Jul 2008 00:35:48 +0100, "Fabio De Dominicis"
wrote:
<snip>
>I'm introducing loop in my program, using the waveout interface loop flags.
>I have a problem:
>during looping, I hear some ticks during the sound. Sure the ticks are
>caused from looping (in the moment that the sound finishes and restart
>again). Can I avoid this ticks?
>Here is the code I use to generate sine waves, I post here the procedure to
>fill a buffer, sent after through the waveoutwrite api.
>It generates 2 tones together, but if I set looping flags, I hear ticks:
<code snipped>
Without attempting to analyze the details of your code, the most
likely problem is that the loop does not enclose an exact integer
number of cycles of each of the tones. If, for example, a tone buffer
starts at zero and ends at a peak, then there will be a tick when the
buffer rolls to zero after that.
To avoid the ticks you must either compute the tones and buffer length
to match (which may limit the tones you can combine in a single
buffer), OR don't use the simple Play loop method. Instead, you can
compute each buffer on-the-fly before you need it, using a queue of
buffers that you send out in sequence. This will require quite a lot
of changes from the Play method and some time to get it working
properly, so consider how much control you really need over the tones.
If you want to stick to Play loops, and you want to allow 2 tones with
a non-harmonic relationship, you may need long loop buffers. For
example, if you want to combine tones that are only 1 Hz different
(say 440 and 441 Hz) to get a beat effect, your buffer needs to hold
a full second of output so that the whole beat cycle is included.
Best regards,
Bob Masta
DAQARTA v4.00
Data AcQuisition And Real-Time Analysis
www.daqarta.com
Scope, Spectrum, Spectrogram, Sound Level Meter
FREE Signal Generator
Science with your sound card!
date: Sat, 05 Jul 2008 12:17:23 GMT
author: (Bob Masta)
Re: Tone generation
<snip>
Thanks both, I succeeded playing more notes together at different frequency
without ticks! I want to use loop, because I want create a little c++ class
that plays sounds, at given frequency and duration. So I decided to play a
sound in loop mode and use a timer to stop the sound when duration time is
reached. Potentially, I think that this method is better than directly
create a buffer containing a sound with given duration, because 10 min of
possible sound occupies enough memory... So I create a 1-second buffer to
avoid all ticks, and then call waveoutreset to stop the sound. If you have
better method than mine, I'm here.
I would like to add to my class, the possibility to produce sweep waves,
from a frequency x to a frequency y. What I should consider to implement
this?
I'm helping myself using the goldwave expression evaluator, where I can
find different equations.
For example, the sine:
sin(2*pi*f*t)
square: int(2*t*f)%2*2-1
sweep from x to y: sin(2*pi*(((n/N/2)*(y-x))+x)*t)
Now, I know that t=freq/sample_rate
Here is the code I used to transform a goldwave expression in c++:
VOID FillBuffer (PBYTE pBuffer, int iFreq){
double fAngle;
double t=iFreq / SAMPLE_RATE;
for (int i = 0 ; i < OUT_BUFFER_SIZE ; i++){
pBuffer[i] = (BYTE) (127 + 127 * sin(fAngle));
fAngle += 2*M_PI*t;
if (fAngle > 2*M_PI) fAngle -= 2*M_PI;
}
}
The domain for fAngle in the sine is 0<=angle<=2PI, and its increment is
2*PI*t.
What is the increment in case of square wave?
I would like to create the buffer in the way that I should just substitute
the lines in the for{} instruction to create different types of wave.
And how can I interpret n and N variables in the goldwave expression to
simulate in my fillbufer procedure a sweep wave from x to y?
Many questions.... I don't know if someone of you has te time to answer....
I hope yes.
Thanks in advance,
Fabio De Dominicis
date: Sat, 5 Jul 2008 16:05:41 +0100
author: Fabio De Dominicis
|
|