follow up How to generate arbitrary waveforms

Using Nyquist scripts in Audacity.
Post and download new plug-ins.
Forum rules
If you require help using Audacity, please post on the forum board relevant to your operating system:
Windows
Mac OS X
GNU/Linux and Unix-like
DERF
Posts: 217
Joined: Sun Jun 13, 2010 12:37 pm
Operating System: Please select

follow up How to generate arbitrary waveforms

Post by DERF » Thu Dec 14, 2017 5:11 pm

Hello. I have a question to ask.

Code: Select all

(setf adsr (pwlv      0
                 0.05 1 
                 0.3  0.4 
                 0.5  0.4 
                 1    0))
(setq wiggle 0.3)
(setq wigglerate 3)
(setf envelope
  (sim (mult adsr (- 1 (* 2 wiggle)))
    (mult adsr wiggle  (sum 1 (hzosc wigglerate)))))
(mult envelope s)
The operator' s manual say: "(sim [beh1 beh2 ...]) Returns a sound which is the sum of the given behaviors...)
my question is the following one:in this code

Code: Select all

 (sim (mult adsr (- 1 (* 2 wiggle)))
      (mult adsr wiggle  (sum 1 (hzosc wigglerate))))
_ the first behavior is:

Code: Select all

 (mult adsr (- 1 (* 2 wiggle))
_ the second behavior is:

Code: Select all

 (mult adsr wiggle  (sum 1 (hzosc wigglerate)))
Does it right?
Thank you.

steve
Site Admin
Posts: 47274
Joined: Sat Dec 01, 2007 11:43 am
Operating System: Linux *buntu
Contact:

Re: follow up How to generate arbitrary waveforms

Post by steve » Thu Dec 14, 2017 5:40 pm

DERF wrote:Does it right?
Yes.
9/10 questions are answered in the FREQUENTLY ASKED QUESTIONS (FAQ)

DERF
Posts: 217
Joined: Sun Jun 13, 2010 12:37 pm
Operating System: Please select

Re: follow up How to generate arbitrary waveforms

Post by DERF » Fri Dec 15, 2017 5:02 am

Thank you.
I would like to ask a second question.
She concerns the two behaviors exactly.
When we use without the function

Code: Select all

(sim
the second behavior, we obtain the sound wave n°2. If we use 2 behaviors, we obtain the sound wave n° 1.
We observe a small difference.The intensity decreased, and the wave is not altered in the same way all the time (the drawing of the wave is different) in the wave n° 2.The shape is more regular.
My question is the following one: is there an article which explains how the 1ier behavior acts on the second, and finally, which is the interest to combine behaviors, as in this precise example.

Thank you for your help
Attachments
BEHAVIORS .jpg
BEHAVIORS .jpg (61.74 KiB) Viewed 1154 times

steve
Site Admin
Posts: 47274
Joined: Sat Dec 01, 2007 11:43 am
Operating System: Linux *buntu
Contact:

Re: follow up How to generate arbitrary waveforms

Post by steve » Fri Dec 15, 2017 11:25 am

I'll split up your code into sections, and demonstrate what each bit does:

Code: Select all

(setf adsr (pwlv 0 0.05 1 0.3  0.4 0.5  0.4 1 0))
This creates an "envelope", which is a low sample rate control signal.
A "control signal" is just a "sound", but at a low sample rate, and changing much more slowly that a normal audio waveform.

By default, "PWLV" creates control signals ("sounds") that have a sample rate 1/20th of the track sample rate.
If you return this kind of "sound", on it's own, back to the Audacity track, the length of the sound will be 1/20th of the length that you generated.
The sound returned by PWLV is assigned as the value of "adsr".

Example,

(pwlv 0 0.05 1 0.3 0.4 0.5 0.4 1 0) creates a signal that has length "1".
If this is in a "generate" type effect (in the Generate menu), then that is "1 second".
If this is in a "process" type effect (in the "Effect menu), then "1 unit" of time gets stretch to equal the length of the selection.

The "Nyquist Prompt" is, by default, a "process" type effect, so running this command in the Nyquist Prompt will return as sound that is 1/20th of the length of the selection:
firsttrack001.png
firsttrack001.png (7.7 KiB) Viewed 1146 times

Code: Select all

(setq wigglerate 3)
(hzosc wigglerate)
HZOSC generates a sine wave at the specified frequency, which in this case is 3Hz. The sample rate of the Audacity track is used.
The default duration is 1 second, which when run in a process type effect is mapped to the length of the selection:
firsttrack003.png
firsttrack003.png (11.47 KiB) Viewed 1146 times

Code: Select all

(setq wigglerate 3)
(sum 1 (hzosc wigglerate))
Adding "1" to the sine wave, offsets it vertically, so that it has a range of 0 to 2.
I have zoomed out vertically so that you can see the top part of the waveform:
firsttrack004.png
firsttrack004.png (11.46 KiB) Viewed 1146 times

Code: Select all

(setq wiggle 0.3)
(setq wigglerate 3)
(setf adsr (pwlv 0 0.05 1 0.3  0.4 0.5  0.4 1 0))
(mult adsr wiggle  (sum 1 (hzosc wigglerate)))
Here we have generated a low frequency control signal "adsr", and a 3Hz sine wave which is offset vertically, and then we are combining them by multiplication.

Nyquist is clever here, because although the sample rate of adsr does not match the sample rate of the sine wave, Nyquist can handle that and uses the length in seconds, which in both cases is "1". However, if we are running this in the Nyquist Prompt, 1 second is mapped to the length of the selection.

Each sample in the sine wave is scaled (multiplied) by the value of adsr at the corresponding time.

Note that we are multiplying three things:
1) the control signal "adsr",
2) a constant value "wiggle", which is = 0.3
3) the sine wave (hzosc wigglerate)
firsttrack005.png
firsttrack005.png (9.35 KiB) Viewed 1146 times

Code: Select all

(- 1 (* 2 wiggle))
This part is a bit of a distraction. "wiggle" is just the value 0.3, so the above expression simply evaluates to:
1 - (2 * 0.3)
= 0.4

so this:

Code: Select all

(mult adsr (- 1 (* 2 wiggle)))
could be written more simply as:

Code: Select all

(mult adsr 0.4)
which gives us:
firsttrack006.png
firsttrack006.png (8.72 KiB) Viewed 1146 times

SIM is the same as SUM, and is simply a function for adding signals or numbers.

Code: Select all

(setf adsr (pwlv 0 0.05 1 0.3  0.4 0.5  0.4 1 0))
(setq wiggle 0.3)
(setq wigglerate 3)

(setf envelope
  (sim 
    (mult adsr (- 1 (* 2 wiggle)))
    (mult adsr wiggle  (sum 1 (hzosc wigglerate)))))
So here we are adding the envelope (mult adsr 0.4), with the wiggly line created in the final line, and assigning the result as the value if ENVELOPE:
firsttrack007.png
firsttrack007.png (9.47 KiB) Viewed 1146 times
We can now multiply this envelope with any sound that we like. In the initial code, it multiplies the envelope by the sound from the Audacity track "S". Alternatively you could generate a sound, and multiply (scale) it with the envelope, for example, here I generate a 440 Hz sawtooth waveform, and multiply it by the envelope:

Code: Select all

(setf adsr (pwlv 0 0.05 1 0.3  0.4 0.5  0.4 1 0))
(setq wiggle 0.3)
(setq wigglerate 3)

(setf envelope
  (sim 
    (mult adsr (- 1 (* 2 wiggle)))
    (mult adsr wiggle  (sum 1 (hzosc wigglerate)))))

(setf my-saw-waveform (osc (hz-to-step 440) 1 *saw-table*))
(mult envelope my-saw-waveform)
firsttrack008.png
firsttrack008.png (11.11 KiB) Viewed 1146 times
9/10 questions are answered in the FREQUENTLY ASKED QUESTIONS (FAQ)

DERF
Posts: 217
Joined: Sun Jun 13, 2010 12:37 pm
Operating System: Please select

Re: follow up How to generate arbitrary waveforms

Post by DERF » Sat Dec 16, 2017 8:16 am

Thank you very much.
It is very interesting.

DERF
Posts: 217
Joined: Sun Jun 13, 2010 12:37 pm
Operating System: Please select

Re: follow up How to generate arbitrary waveforms

Post by DERF » Sun Dec 17, 2017 10:54 am

Hello.
It is necessary to begin with this code:

Code: Select all

(push (/ (+ 1.0 count) num) point-list )
My question is the following one: Is the following code identical to the first one?

Code: Select all

(setf point-list (cons (/ (+ 1.0 count) num) point-list))
It is right?
Thank you.

steve
Site Admin
Posts: 47274
Joined: Sat Dec 01, 2007 11:43 am
Operating System: Linux *buntu
Contact:

Re: follow up How to generate arbitrary waveforms

Post by steve » Sun Dec 17, 2017 11:28 am

Code: Select all

(setf a '(1)) ; A list containing the number 1
(setf b (push 2 a))
(setf c (cons 3 a))
(print a) (print b) (print c)

(setf a (cons 4 a))
(print a)
prints to the debug window:

Code: Select all

(2 1)
(2 1)
(3 2 1)
(4 2 1)
PUSH added "2" to the list A, modifying A, so A = (2, 1)
B = A, so B also = (2, 1)

CONS adds "3" to the list and returns the extended list, but does not modify the list,
C = (3, 2, 1), but A is still = (2, 1)

(setf a (cons 4 a)) adds "4" to the list, and sets A to the returned value of CONS, so A now = (4, 2, 1)

More about CONS: http://www.audacity-forum.de/download/e ... ef-080.htm
More about PUSH: http://www.audacity-forum.de/download/e ... l#index791
9/10 questions are answered in the FREQUENTLY ASKED QUESTIONS (FAQ)

DERF
Posts: 217
Joined: Sun Jun 13, 2010 12:37 pm
Operating System: Please select

Re: follow up How to generate arbitrary waveforms

Post by DERF » Mon Dec 18, 2017 6:00 pm

Thank you.
It is necessary to leave the following code:

Code: Select all

(setf point-list  '(list 0.1 0.5  1 0))
(setf amp-list (list 0.1  0.8  0.2  0.8   0.1  1 0))
(setf num (1- (length amp-list)))

(dotimes (count   num)
(setf a  (push (nth (1+ count) amp-list) point-list)))

(print a)
return : (0  1  0.1  0.8  0.2  0.8 LIST 0.1 0.5 1 0)
I tried to explain.
It seems to me that:
_ "num" take this "value": 6
_ "count" takes successively the "value" (0 - 1- 2- 3 - 4 - 5 )

My question is the following one:
Why does the evaluation proceed upside down?
[nth] takes successively the values 5 4 3 2 1 0.

Code: Select all

(push (nth (1+ 5) amp-list) point-list))
If you write this code

Code: Select all

(setf a (nth 6 '( 0.1  0.8  0.2  0.8   0.1  1 0    )))

(print a)

LISP return "0"
Then:

Code: Select all

(push (nth (1+ 4) amp-list) point-list))
return the value "1"
and so on.
Thank you for your reply.

steve
Site Admin
Posts: 47274
Joined: Sat Dec 01, 2007 11:43 am
Operating System: Linux *buntu
Contact:

Re: follow up How to generate arbitrary waveforms

Post by steve » Tue Dec 19, 2017 1:04 am

DERF wrote:Why does the evaluation proceed upside down?
It doesn't.

Let me give an example:

Code: Select all

(setf a-list (list "A" "B" "C" "D"))  ; a list containing letters
(setf num (length a-list))  ; set NUM to the length of the list
(print num)         ; prints 4 to debug window
(terpri)            ; new line
(setf new-list ())  ; an empty list

(dotimes (count num)    ; loop where "count" takes values 0 to 4
  (setf val (nth count a-list))   ; set VAL to the nth item in A-LIST
  (format t "Item ~a in a-list = ~a~%" count val) ; prints the value of the nth term in A-List
  (push val new-list)   ; push the value to the begining of NEW-LIST
  (format t "NEW-LISt = ~a~%" new-list) ; print NEW-LIST
  (terpri))             ; new line
The debug window shows:

Code: Select all

4

Item 0 in a-list = A
NEW-LISt = (A)

Item 1 in a-list = B
NEW-LISt = (B A)

Item 2 in a-list = C
NEW-LISt = (C B A)

Item 3 in a-list = D
NEW-LISt = (D C B A)

Note that PUSH adds the value to the start of the new list, so the new list is the reverse of the original list.
9/10 questions are answered in the FREQUENTLY ASKED QUESTIONS (FAQ)

DERF
Posts: 217
Joined: Sun Jun 13, 2010 12:37 pm
Operating System: Please select

Re: follow up How to generate arbitrary waveforms

Post by DERF » Mon Jan 01, 2018 5:28 pm

Thank you.
It concerns the function [(format].
We can write:

Code: Select all

(format nil "~s ho ho" "o&&") 
But, we can also write:

Code: Select all

(format t "~s ho ho" "o&&") 
The answer of the nyquist prompt is identical.
My question is this: Is there a difference nevertheless?
Thank you for your response.

Post Reply