Page 1 of 3

follow up How to generate arbitrary waveforms

Posted: 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.

Re: follow up How to generate arbitrary waveforms

Posted: Thu Dec 14, 2017 5:40 pm
DERF wrote:Does it right?

Yes.

Re: follow up How to generate arbitrary waveforms

Posted: 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.

Re: follow up How to generate arbitrary waveforms

Posted: 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 (7.7 KiB) Viewed 709 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 (11.47 KiB) Viewed 709 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 (11.46 KiB) Viewed 709 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:
2) a constant value "wiggle", which is = 0.3
3) the sine wave (hzosc wigglerate)

firsttrack005.png (9.35 KiB) Viewed 709 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 (8.72 KiB) Viewed 709 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 (9.47 KiB) Viewed 709 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 (11.11 KiB) Viewed 709 times

Re: follow up How to generate arbitrary waveforms

Posted: Sat Dec 16, 2017 8:16 am
Thank you very much.
It is very interesting.

Re: follow up How to generate arbitrary waveforms

Posted: 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.

Re: follow up How to generate arbitrary waveforms

Posted: 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)

Re: follow up How to generate arbitrary waveforms

Posted: 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.

Re: follow up How to generate arbitrary waveforms

Posted: 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
`4Item 0 in a-list = ANEW-LISt = (A)Item 1 in a-list = BNEW-LISt = (B A)Item 2 in a-list = CNEW-LISt = (C B A)Item 3 in a-list = DNEW-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.

Re: follow up How to generate arbitrary waveforms

Posted: 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?