;; functional.sal - functional programming in Nyquist ;; ;; Roger B. Dannenberg ;; July 2024 ;; ;; Example showing development of a sound through ;; definitions and applications of functions ;; start with a simple tone based on FM example in ;; code_4.sal: play fm(gs4, pwl(0.3, 1, 0.7, 1, 1), 0.5, pwlv(0.5, 0.5, 10, 1, 2)) ;; make this into a function: function fmtone(p) return fm(p, pwl(0.3, 1, 0.7, 1, 1), 0.5, pwlv(0.5, 0.5, 10, 1, 2)) ;; try it: play fmtone(gs4) ;; add some tremolo (AM) function trem(s, i, r) ; sound, intenity, rate return s * (1 + i * lfo(r, 100)) ;; try it on fmtone, stretching by factor of 3: play trem(fmtone(g3), 0.2, 4) ~ 3 ;; add some reverb: load "reverb" function rvb(s, rt, wet) ; sound, rev. time, amount return reverb(seq(s, s-rest(rt * 2)), rt) * wet + s ;; try it: play rvb(trem(fmtone(g3), 0.2, 4) ~ 3, 5, 0.2) ;; not very clear or interesting, so let's make the ;; tone short to make it stand out: play rvb(env(0.1, 0.1, 0.1, 1, 1, 1) * 0.5 * trem(fmtone(g3), 0.2, 4) ~ 3, 5, 0.2) ;; that is still not clear, so make it shorter: play rvb((env(0.01, 0.01, 0.01, 1, 1, 1) ~ 0.1) * trem(fmtone(g3), 0.2, 4) ~ 3, 3, 0.1) ;; that sounds better, so let's make it a function: function beep(p) return rvb(env(0.01, 0.01, 0.01, 1, 1, 1) ~ 0.1 * trem(fmtone(p), 0.2, 4) ~ 3, 3, 0.1) ;; let's make several beeps in sequence: play beep(g4) + beep(bf4) @ 0.2 + beep(c5) @ 0.5 + beep(e4) @ 0.7 ;; make that a function too: function beep4() return beep(g4) + beep(bf4) @ 0.2 + beep(c5) @ 0.5 + beep(e4) @ 0.7 ;; play it repeatedly: play seqrep(i, 4, set-logical-stop(beep4(), 1.0)) ;; what if we transpose each repeat: play seqrep(i, 4, set-logical-stop(transpose(i, beep4()), 1.0)) ;; what if we make each repeat shorter/faster? ;; Note that 10 / (10.0 + i) is 1 when i = 0, but gets ;; smaller as i increases, e.g. it is 1/2 when i = 10. ;; Note also that we need 10.0 + i (floating point) rather ;; than 10 + i (integer) so that the division is a floating ;; point division rather than integer division. play seqrep(i, 10, set-logical-stop(transpose(i, beep4()) ~ (10 / (10.0 + i)), 10 / (10.0 + i))) ;; Sounds interesting; let's make it more extreme (start ;; lower, go higher): play transpose(-12, seqrep(i, 35, set-logical-stop(transpose(i, beep4()) ~ (10 / (10.0 + i)), 10 / (10.0 + i)))) ;; make it fade out; first, we need a function: function ascend() return transpose(-12, seqrep(i, 35, set-logical-stop(transpose(i, beep4()) ~ (10 / (10.0 + i)), 10 / (10.0 + i)))) ;; Now make the fade: play ascend() * pwz(0, 1, 10, 1, 16)