Tone Generators: Siren

Which JAWS command is this? Is it Control+C? I’m confused!

This has never worked for me.
On my first attempts in IE, the browser crashed.

You can copy by defining a start and end point:
NVDA+F9: Set start point
NVDA+F10: Set end point and copy to the clipboard.

Ensure that the start point is at the beginning of the line (press home) and that the end point is at the end of the block - include a line more than needed.

You can alternatively select the text by holding shift while pressing up and down. Shift+Page up/down selects more text at once and you can fine tune afterwards. Here, the usual Control+C will be needed eventually.

Here’s why I realized that the characters are wrongly encoded:

Normally, multiple Spaces are read out by NVDA as e.g. “5 space”.
If 128 is added to the usual code 32, NVDA reads “space space space space space”.

NVDA’s review cursor can be used to read the Unicode number of a Character.
The commands are distributed over the Numpad:
7 8 9: prior, current and next line
4 5 6: prior current and next word
1 2 3: prior current and next character

So, if you’re at the right position, pressing numpad 2 says e.g. “n”, pressing 2 twice gives “November”
and trice “110 0x6e”.

It is a bit difficult to place the review cursor on a web page since it does not correspond to the normal cursor - in contrast to the Nyquist prompt for instance.

Hope this helps.


Thanks, that works for me.

Another way that works for me with NVDA and Firefox is:

  1. Navigate to the link that says “Select All” above the posted Nyquist code
  2. Press enter.
  3. Alt+E to open the Firefox Edit menu
  4. Either, scroll down to “Copy” and press Enter, or press the “C” key

I am still not able to reproduce the error that Annabelle reported that begins with “error: illegal character - -62”

I get the same error as Annabelle.

However, first pressing “Select all” and then copying works.
NVDA catches the normal Control+C shortcut, thus I have to pass by NVDA by first pressing NVDA+F2 and then Control-C. For JAWS it would be JAWS+3, I think.

After pasting into the Nyquist prompt, the code works.

However, each line has 4 spaces in front - at least your last sample code, a few posts back.


If you copy from Firefox into NotePad, then save the text file, and then “Load” the text file into the Nyquist Prompt, do you still get the same error as Annabelle?
If you do, please post the text file as an attachment.

Yes, copying from the Code block in Firefox increases the number of spaces. There is an Add-on available for Firefox to “copy as text”. I use that extension on my Linux machine to work around that problem.

How does this look for a plugin? Please tell me if this looks right to you.
Siren.ny (1.14 KB)

Does that work for you as a plug-in? It works here.
The choice control does not do anything yet, but you have written it correctly.

A couple of minor details:

  1. As Robert and I were discussing, there are more spaces at the start of lines than there should be, but that should not adversely affect it.
  2. You have the “;type generate” header twice (line 3 and line 7).

Regarding how to make the plug-in more versatile so that you can produce different tones, there are a couple of different approaches that you can take. One approach is to carefully craft each desired preset exactly the way that you want it, then use the multi-choice control to select which code to use. Another approach would be to have a number of controls (perhaps the usual slider and text box widgets) for different parameters, such as, one for the upper frequency, one to set the lower frequency, one to set the speed at which it cycles from one to the other, one for the output level, and so on. Which approach you take is up to you. I would tend to go for the second option so that a wide range of different siren sounds can be made using the same code.

According to the code you gave, I’m not sure which parameter would set the frequencies and the cycles of the tone. Is it the “setf siren” code? I’m confused!

This code is not such a close approximation of the real siren, but I think that it is easier to understand, so should be easier to customise.
As we have discussed previously, the key part of the siren code is the FMOSC function. Here it is in the Nyquist manual:

Let’s take a simple example, a sine tone that rises from 440 Hz to 880 Hz over 2 seconds - that’s A4 to A5. (I’ll write this without code tags as that may be easier to copy). If you read the description of FMOSC in the manual, you will see that we can achieve this if we set the “pitch” parameter to A4, then we just need to “modulate” it by a 2 second duration signal that rises from 0 to 440. We can use the PWLV function to create the rising modulation signal. We need “pitch” as a note value, so we use the function HZ-TO-STEP to calculate the correct note value (see:

;type generate
(setf mod (pwlv 0 2 440))
(setf pitch (hz-to-step 440))
(fmosc pitch mod)

Similarly, if we want a pitch that rises from 440 to 880 over 2 seconds, and then falls from 880 back to 440 over the next 2 seconds, the only modification that we need is to make our modulation control signal rise from 0 to 440 over 2 seconds, then fall back to 0 over the next 2 seconds:

;type generate
(setf mod (pwlv 0 2 440 4 0))
(setf pitch (hz-to-step 440))
(fmosc pitch mod)

Do you see how that works?

OK, so now let’s give that some controls for the pitch values. First let’s just consider the low pitch value:

;type generate
;control low-hz “Low frequency (Hz)” float “” 440 100 1000
(setf mod (pwlv 0 2 440 4 0))
(setf pitch (hz-to-step low-hz))
(fmosc pitch mod)

OK so far? Please say if not.

Now to add a control for the high frequency value. Note that our high frequency is the maximum modulation value + the low frequency. In other words, the maximum modulation value needs to be the difference between the high frequency and the low frequency.

;type generate
;control low-hz “Low frequency (Hz)” float “” 440 100 1000
;control high-hz “Low frequency (Hz)” float “” 880 400 4000
(setf range (- high-hz low-hz))
(setf mod (pwlv 0 2 range 4 0))
(setf pitch (hz-to-step low-hz))
(fmosc pitch mod)

For our siren, we don’t really just want up and down once, we want it to repeat up, down, up, down, and so on. In other words we want an oscillating control signal. So instead of using PWLV, let’s try using an triangle wave oscillator. The LFO function can create a triangle wave if we use a triangle table (see:

So to reproduce our 4 second tone, rising by 440 Hz for two seconds and falling for the next two seconds, we would want a low frequency triangle wave that has a frequency of 1/4 second and an amplitude that rises from 0 to 440 then falls back down to 0.

We can create a triangle waveform with a frequency of 1/4 Hz and a duration of 4 seconds with (lfo (/ 4.0) 4.0 tri-table), but this has an amplitude from -1 to +1 and we want it to go from 0 to 440, so what we need to do is to raise it by 1, which will give it a range of 0 to 2, then multiply by 220 to give it a range of 0 to 440.

(mult 220 (sum 1 (lfo (/ 4.0) 4.0 tri-table)))

So let’s try dropping this into our second bit of code:

;type generate
(setf mod (mult 220 (sum 1 (lfo (/ 4.0) 4.0 tri-table))))
(setf pitch (hz-to-step 440))
(fmosc pitch mod)

Notice that we multiplied by half of the required range (because after adding 1 to the triangle waveform the range was 0 to 2). Taking that into account, let’s drop the LFO into the code that has controls:

;type generate
;control low-hz “Low frequency (Hz)” float “” 440 100 1000
;control high-hz “Low frequency (Hz)” float “” 880 400 4000
(setf range (- high-hz low-hz))
(setf mod (mult (/ range 2) (sum 1 (lfo (/ 4.0) 4.0 tri-table))))
(setf pitch (hz-to-step low-hz))
(fmosc pitch mod)

Because we are now using an oscillator, we can easily make the duration of the siren as long as we like. For example:

;type generate
;control low-hz “Low frequency (Hz)” float “” 440 100 1000
;control high-hz “Low frequency (Hz)” float “” 880 400 4000
;control duration “Duration (seconds)” float “” 10 0 100
(setf range (- high-hz low-hz))
(setf mod (mult (/ range 2) (sum 1 (lfo (/ 4.0) duration tri-table))))
(setf pitch (hz-to-step low-hz))
(fmosc pitch mod)

Then of course you can specify the waveform for the FMOSC by defining the table parameter. That part is already in your code, so I’ll leave you to have a go at that.

I’ve straightende the code out a little bit, but I’m still not sure if this will look right. Look at this attachment and tell me if there’s something more that I may need to change.
Siren.ny (1.45 KB)

Try this:
siren.ny (1.52 KB)

I’ve discovered the problem.
It has nothing to do with any of the code in this forum topic. That error occurs when running the code from this post (in a different forum topic) REQ: R1 MF ("Blue box") Tone Generator - #7 by Robert_J_H and it is caused by errors in that code.

Funny when I tested the plugin, the siren sounds to me like a hair dryer that can’t make up its mind between high and low after the initial wind-up! So now thatI’ve got the idea of how to make the wail, I’m stuck on how to make the codes for the other choices (Yelp, hyperyelp/phaser/piercer, powercall, hi-lo, and airhorn. Any pointers?
Siren.ny (1.49 KB)

Does the version that I posted here not give enough options?

From what I’m reading in the code, it doesn’t really tell me how to make the tones other than the wail.

Have you tried running the effect and changing the settings? (Hint, use the “Preview” button).

Which setting would I change?

Try them all, see what sort of sounds you can make. Play with it :slight_smile:

I’ve tried adjusting the cycle length, and was able to make a convincing yelp tone, but I got stuck trying to make the phaser/piercer/hyperyelp tone, as it didn’t sound quite right when I adjusted the cycle length to the shortest it could go. It seems I can’t go anywhere below 0.100. I know the phaser/piercer tone is a fast tone, I guess that’s why they sometimes call it “hyperyelp”. For example, you can hear a siren hyperyelp in this video.
I also wonder, is it possible for me to put the specific names of the siren tones next to the codes you made for Rise-Fall Ratio and Cycle Length? If so, how would I write the code, and where exactly would I place it in the document?