Start and Stop Sinewave sound

Status
Not open for further replies.

gerry

Member
Hi,

I am using the Audio Library on a Teensy 3.6 and I want to play a sine wave when a certain command with a frequency comes in via Serial. This sound should last some milliseconds, but not longer. Other programming may not be interrupted.
So, I thought I could use the AudioSynthWaveformSine and play it via DAC. But when I do that, I am not able to say start/stop playing. Of course, that is quite basic behaviour, so I am sure there must be a solution to this - I am just not able to find it or figure it out.

Little background: It is for an experiment, in which I want the subject to do something based on the sound they hear. So it may be that I need to play a sine wave at 1000 Hz for 20 ms and a little later a sine wave at 1500 Hz for 100 ms.

Can anyone give me some hints?

Thanks in advance! :)
 
You can start the waveform with begin() and stop it by setting the amplitude to zero. Like this...

sc1.png

Code:
waveform1.begin(1.0, 1000, WAVEFORM_SINE);
delay(20);
waveform1.amplitude(0);
delay(1000);
waveform1.begin(1.0, 1500, WAVEFORM_SINE);
delay(100);
waveform1.amplitude(0);


However, the sudden start and stop of a sine wave can have a broad spectral output which most people will hear as a click or slight pop sound. If you want the listener to perceive only the sine wave frequency without clicking as it starts and stops, you should probably add the envelope effect. Like this...

sc2.png

Code:
waveform1.begin(1.0, 1000, WAVEFORM_SINE);
envelope1.noteOn();
delay(20);
envelope1.noteOff();
delay(1000);
waveform1.begin(1.0, 1500, WAVEFORM_SINE);
envelope1.noteOn();
delay(100);
envelope1.noteOff();

You'll probably need to experiment with how to configure the envelope settings in setup().

You might also discover 20ms is such a short time that most people can't really discern the pitch. Very short sounds are heard as percussive events. You'll probably need much longer if you want tones where humans can hear different notes or pitch.
 
Hi,

Thank you so much for your help.
Indeed, I thought about using a dealy and then just setting the amplitude to zero. Unfortunately, it is essential that the other code runs simultaneously to the sound playing. So working with delay() is not really the solution right? As it would stop the whole code from continuing until after the delay time.
Is there any other possibility?

I thought about using sinewave tables with a certain length and then only playing those. That can be done simultaneously to other code running. But I need to use sine waves of different frequencies and I am having trouble to generate those tables and playing them.
But maybe there is a better solution anyway?
 
Look a bit more at the envelope object. You can set the timings for the stages. If sustain is set 0, then you don't even need to worry about the precise time of calling noteoff(), but you could use attack(0), hold(19), decay(1) say to get a 20ms tone that doesn't end with a pop. Then just call noteoff() sometime before starting the next one (you can monitor the system time to be sure the duration has passed).

Alternatively, if you want to control the note off time more precisely, use sustain(1) but add a very short release time. Then when noteoff() is called, the note decays for the release duration.

I demonstrate how envelopes work here http://thewessens.net/synthbook/#chap:envelopes (including Teensy code) if you're interested in more details.
 
So working with delay() is not really the solution right? As it would stop the whole code from continuing until after the delay time.
Is there any other possibility?

Yes. Use elapsedMillis.

https://www.pjrc.com/teensy/td_timing_elaspedMillis.html

You can create as many elapsedMillis variables as you need, and then check them without delaying so you start and stop sounds as needed.

If you want more than 1 sine wave to play at the same time, remember you need to create multiple waveform instances and feed them into a mixer to get the combined sound.
 
Great, that works. Thank you.

I now use elapsedMillis to stop the sound after x milliseconds. The stopping has to happen via the loop, which is not perfect, but I think it is good enough.
 
If you wanted it done all within the audio library, you could try using the envelope effect with sustain level at zero. Then you'd set the attack and decay to low numbers and the hold time to the length of time you want the sound to be heard.
 
Status
Not open for further replies.
Back
Top