Commitecdada7cRecorded23 Sep 2026Repositorymotif
Let every bed kind take cents: (a just-tuned drone on tracker notes)
Message
Tracker notes are equal-tempered; Harkfell's drone is just-tuned (H5 is 13.7 cents under F#, H7 31.2 under C). cents: multiplies the note by 2^(cents/1200) in every kind of (motif patches beds). test-beds checks a 220 Hz note at +1200 sounds at 440 and C5 at -31.17 sounds at 513.9 Hz.
Changed
src/motif/patches/beds.sgl | 21 +++++++++++++++------
src/motif/tests/beds.sgl | 19 +++++++++++++++++++
2 files changed, 34 insertions(+), 6 deletions(-)Diff
src/motif/patches/beds.sglmodified
@@ -20,6 +20,8 @@
20
;;; finding-tone a soft FM tone that pulses, darkened and quietened by 21
;;; `cutoff` and the note volume (how far away it is) 22
;;;+23
;;; Every kind takes `seed:` (see the drone kinds) and `cents:` (a pitch offset).+24
;;; 25
;;; Speaker-first (Harkfell design D10): the drone kinds are never pure 26
;;; sines; `bright` (drone-saw) and `index` (drone-fm) keep partials above 27
;;; 300 Hz so a phone speaker carries a low pitch.@@ -38,6 +40,13 @@
40
(define (wander-gain p rate lo) 41
(if (>= lo 1.0) 1.0 (g:randi rate lo 1.0 (setting p (quote seed) 0.0)))) 42
+43
;; The note moved by `cents:` (a just-tuned drone on equal-tempered+44
;; notes: H5 is -13.7 cents from F#, H7 -31.2 from C); every kind here+45
;; takes it.+46
(define (tuned freq p)+47
(let ((c (setting p (quote cents) 0.0)))+48
(if (= c 0.0) freq (g:mul freq (expt 2.0 (/ c 1200.0))))))+49
50
(define (times x y) 51
(cond ((and (number? y) (= y 1.0)) x) 52
((and (number? x) (number? y)) (* x y))@@ -63,7 +72,7 @@
72
73
(define (noise-bed-graph p) 74
(graph-begin)−66
(let* ((freq (g:freq))+75
(let* ((freq (tuned (g:freq) p)) 76
(gate (g:gate)) 77
(src (noise-source (setting p 'color 'pink) (setting p 'level 0.5) (setting p 'seed 0.0))) 78
(centre (let ((c (setting p 'centre 900.0)))@@ -103,7 +112,7 @@
112
113
(define (drip-graph p) 114
(graph-begin)−106
(let* ((freq (g:freq))+115
(let* ((freq (tuned (g:freq) p)) 116
(gate (g:gate)) 117
(pitch-env (g:adsr gate 0.0005 (setting p 'sweep 0.04) 0.0 0.01)) 118
;; rises from freq to freq * (1 + rise) as pitch-env falls 1 -> 0@@ -127,7 +136,7 @@
136
137
(define (pipe-breath-graph p) 138
(graph-begin)−130
(let* ((freq (g:freq))+139
(let* ((freq (tuned (g:freq) p)) 140
(gate (g:gate)) 141
(w (min 1.0 (setting p 'width 0.08))) 142
(air (g:pink 1.0 (setting p 'seed 0.0)))@@ -155,7 +164,7 @@
164
165
(define (drone-saw-graph p) 166
(graph-begin)−158
(let* ((freq (g:freq))+167
(let* ((freq (tuned (g:freq) p)) 168
(gate (g:gate)) 169
(ratio (expt 2.0 (/ (setting p 'detune 4.0) 2400.0))) 170
(a (g:saw (g:mul freq ratio) 0.5))@@ -177,7 +186,7 @@
186
187
(define (drone-fm-graph p) 188
(graph-begin)−180
(let* ((freq (g:freq))+189
(let* ((freq (tuned (g:freq) p)) 190
(gate (g:gate)) 191
(index (setting p 'index 1.4)) 192
(iw (setting p 'index-wander 0.4))@@ -196,7 +205,7 @@
205
206
(define (finding-tone-graph p) 207
(graph-begin)−199
(let* ((freq (g:freq))+208
(let* ((freq (tuned (g:freq) p)) 209
(gate (g:gate)) 210
(x (g:fosc freq (setting p 'index 1.1) 1.0 2.0 (setting p 'level 0.4))) 211
(x (g:butlp x (setting p 'cutoff 5000.0)))src/motif/tests/beds.sglmodified
@@ -565,6 +565,24 @@
565
'((drip (decay . 0.02) (echo . 0.4) (feedback . 0.7)) 566
(noise-bed (release . 0.1))))) 567
+568
;; cents: moves the pitch. A drone-fm at 220 Hz with cents 1200 sounds+569
;; at 440; with cents -31.17 on C5 (523.25) it is H7 of D2, 513.9 Hz.+570
(define (test-cents)+571
(display "[cents]\n")+572
(let* ((n sr)+573
(graph (lambda (params freq)+574
(bv->vector (%render-graph (make-synth-graph 'drone-fm params) n sr freq 1.0 #f))))+575
(up (graph '((cents . 1200.0) (breath-lo . 1.0) (index-wander . 0.0) (attack . 0.01)) 220.0))+576
(h7 (graph '((cents . -31.17) (breath-lo . 1.0) (index-wander . 0.0) (attack . 0.01)) 523.25))+577
(a440 (tone-amplitude up 440.0 4410 22050))+578
(a220 (tone-amplitude up 220.0 4410 22050))+579
(a514 (tone-amplitude h7 513.9 4410 22050))+580
(a523 (tone-amplitude h7 523.25 4410 22050)))+581
(assert "cents 1200 puts a 220 Hz note at 440 (440 over 10x 220)"+582
(> a440 (* 10.0 a220)) (string-append (num a440) " vs " (num a220)))+583
(assert "cents -31.17 on C5 sounds H7 of D2, 513.9 Hz (over 523.25)"+584
(> a514 (* 2.0 a523)) (string-append (num a514) " vs " (num a523)))))+585
586
(define (run-bed-tests) 587
(dsp-init sr) 588
(test-colours)@@ -573,5 +591,6 @@
591
(test-bandpass) 592
(test-exciter) 593
(test-kinds)+594
(test-cents) 595
(display (string-append "Beds: " (num passes) " passed, " (num failures) " failed\n")) 596
(if (= failures 0) 0 1))))