Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

2799 lines
96KB

  1. ;;; a DSP-related grabbag
  2. (provide 'snd-dsp.scm)
  3. (if (provided? 'snd)
  4. (require snd-ws.scm)
  5. (require sndlib-ws.scm))
  6. (require snd-env.scm)
  7. (when (provided? 'pure-s7)
  8. (define (make-polar mag ang)
  9. (if (and (real? mag) (real? ang))
  10. (complex (* mag (cos ang)) (* mag (sin ang)))
  11. (error 'wrong-type-arg "make-polar args should be real"))))
  12. (define binomial
  13. (let ((documentation "(binomial n k) computes the binomial coefficient C(N,K)"))
  14. (lambda (n k)
  15. (let ((mn (min k (- n k))))
  16. (if (< mn 0)
  17. 0
  18. (if (= mn 0)
  19. 1
  20. (let ((mx (max k (- n k))))
  21. (do ((cnk (+ 1 mx))
  22. (i 2 (+ 1 i)))
  23. ((> i mn) cnk)
  24. (set! cnk (/ (* cnk (+ mx i)) i))))))))))
  25. (define log10
  26. (let ((documentation "(log10 a) returns the log base 10 of 'a'"))
  27. (lambda (a)
  28. (log a 10))))
  29. ;;; src-duration (see src-channel in extsnd.html)
  30. (define src-duration
  31. (let ((documentation "(src-duration envelope) returns the new duration of a sound after using 'envelope' for time-varying sampling-rate conversion"))
  32. (lambda (e)
  33. (let ((len (- (length e) 2)))
  34. (do ((all-x (- (e len) (e 0))) ; last x - first x
  35. (dur 0.0)
  36. (i 0 (+ i 2)))
  37. ((>= i len) dur)
  38. (let ((area (let ((x0 (e i))
  39. (x1 (e (+ i 2)))
  40. (y0 (e (+ i 1))) ; 1/x x points
  41. (y1 (e (+ i 3))))
  42. (if (< (abs (real-part (- y0 y1))) .0001)
  43. (/ (- x1 x0) (* y0 all-x))
  44. (/ (* (- (log y1) (log y0))
  45. (- x1 x0))
  46. (* (- y1 y0) all-x))))))
  47. ;; or (* (/ (- (log y1) (log y0)) (- y1 y0))
  48. ;; or (/ (log (/ y1 y0)) (- y1 y0))
  49. ;; (/ (- x1 x0) all-x)
  50. (set! dur (+ dur (abs area)))))))))
  51. ;;; :(src-duration '(0 1 1 2))
  52. ;;; 0.69314718055995
  53. ;;; :(src-duration #(0 1 1 2))
  54. ;;; 0.69314718055995
  55. (define (src-fit-envelope e target-dur)
  56. (scale-envelope e (/ (src-duration e) target-dur))) ; scale-envelope is in env.scm
  57. ;;; -------- Dolph-Chebyshev window
  58. ;;;
  59. ;;; formula taken from Richard Lyons, "Understanding DSP"
  60. ;;; see clm.c for C version (using either GSL's or GCC's complex trig functions)
  61. (define dolph
  62. (let ((documentation "(dolph n gamma) produces a Dolph-Chebyshev FFT data window of 'n' points using 'gamma' as the window parameter."))
  63. (lambda (N gamma)
  64. (let ((rl (make-float-vector N))
  65. (im (make-float-vector N)))
  66. (let ((alpha (cosh (/ (acosh (expt 10.0 gamma)) N))))
  67. (do ((den (/ 1.0 (cosh (* N (acosh alpha)))))
  68. (freq (/ pi N))
  69. (i 0 (+ i 1))
  70. (phase 0.0 (+ phase freq)))
  71. ((= i N))
  72. (let ((val (* den (cos (* N (acos (* alpha (cos phase))))))))
  73. (set! (rl i) (real-part val))
  74. (set! (im i) (imag-part val))))) ;this is always essentially 0.0
  75. (fft rl im -1) ;direction could also be 1
  76. (float-vector-scale! rl (/ 1.0 (float-vector-peak rl)))
  77. (do ((i 0 (+ i 1))
  78. (j (/ N 2)))
  79. ((= i N))
  80. (set! (im i) (rl j))
  81. (set! j (+ j 1))
  82. (if (= j N) (set! j 0)))
  83. im))))
  84. ;;; this version taken from Julius Smith's "Spectral Audio..." with three changes
  85. ;;; it does the DFT by hand, and is independent of anything from Snd (fft, float-vectors etc)
  86. (define dolph-1
  87. (let ((documentation "(dolph-1 n gamma) produces a Dolph-Chebyshev FFT data window of 'n' points using 'gamma' as the window parameter."))
  88. (lambda (N gamma)
  89. (let ((vals (make-vector N)))
  90. (let ((alpha (cosh (/ (acosh (expt 10.0 gamma)) N))))
  91. (do ((den (/ 1.0 (cosh (* N (acosh alpha)))))
  92. (freq (/ pi N))
  93. (mult -1 (- mult))
  94. (i 0 (+ i 1))
  95. (phase (* -0.5 pi) (+ phase freq)))
  96. ((= i N))
  97. (set! (vals i) (* mult den (cos (* N (acos (* alpha (cos phase)))))))))
  98. ;; now take the DFT
  99. (let ((pk 0.0)
  100. (w (make-vector N)))
  101. (do ((i 0 (+ i 1))
  102. (sum 0.0 0.0))
  103. ((= i N))
  104. (do ((k 0 (+ k 1)))
  105. ((= k N))
  106. (set! sum (+ sum (* (vals k) (exp (/ (* 2.0 0+1.0i pi k i) N))))))
  107. (set! (w i) (magnitude sum))
  108. (set! pk (max pk (w i))))
  109. ;; scale to 1.0 (it's usually pretty close already, that is pk is close to 1.0)
  110. (do ((i 0 (+ i 1)))
  111. ((= i N))
  112. (set! (w i) (/ (w i) pk)))
  113. w)))))
  114. ;;; -------- move sound down by n (a power of 2)
  115. (define down-oct
  116. (let ((documentation "(down-n n) moves a sound down by n-1 octaves"))
  117. (lambda* (n snd chn)
  118. ;; I think this is "stretch" in DSP jargon -- to interpolate in the time domain we're squeezing the frequency domain
  119. ;; the power-of-2 limitation is based on the underlying fft function's insistence on power-of-2 data sizes
  120. ;; see stretch-sound-via-dft below for a general version
  121. (let* ((len (framples snd chn))
  122. (fftlen (floor (expt 2 (ceiling (log len 2))))))
  123. (let ((fftlen2 (/ fftlen 2))
  124. (fft-1 (- (* n fftlen) 1))
  125. (fftscale (/ 1.0 fftlen))
  126. (rl1 (channel->float-vector 0 fftlen snd chn))
  127. (im1 (make-float-vector fftlen)))
  128. (fft rl1 im1 1)
  129. (float-vector-scale! rl1 fftscale)
  130. (float-vector-scale! im1 fftscale)
  131. (let ((rl2 (make-float-vector (* n fftlen)))
  132. (im2 (make-float-vector (* n fftlen))))
  133. (copy rl1 rl2 0 fftlen2)
  134. (copy im1 im2 0 fftlen2)
  135. (do ((k (- fftlen 1) (- k 1))
  136. (j fft-1 (- j 1)))
  137. ((= k fftlen2))
  138. (float-vector-set! rl2 j (float-vector-ref rl1 k))
  139. (float-vector-set! im2 j (float-vector-ref im1 k)))
  140. (fft rl2 im2 -1)
  141. (float-vector->channel rl2 0 (* n len) snd chn #f (format #f "down-oct ~A" n))))))))
  142. (define stretch-sound-via-dft
  143. (let ((documentation "(stretch-sound-via-dft factor snd chn) makes the given channel longer ('factor' should be > 1.0) by \
  144. squeezing in the frequency domain, then using the inverse DFT to get the time domain result."))
  145. (lambda* (factor snd chn)
  146. ;; this is very slow! factor>1.0
  147. (let* ((n (framples snd chn))
  148. (out-n (round (* n factor))))
  149. (let ((out-data (make-float-vector out-n))
  150. (fr (make-vector out-n 0.0))
  151. (freq (/ (* 2 pi) n)))
  152. (do ((in-data (channel->float-vector 0 n snd chn))
  153. (n2 (floor (/ n 2.0)))
  154. (i 0 (+ i 1)))
  155. ((= i n))
  156. ;; DFT + split
  157. (set! (fr (if (< i n2) i (- (+ i out-n) n 1)))
  158. (edot-product (* freq 0.0-1.0i i) in-data)))
  159. (set! freq (/ (* 2 pi) out-n))
  160. (do ((i 0 (+ i 1)))
  161. ((= i out-n))
  162. ;; inverse DFT
  163. (set! (out-data i) (real-part (/ (edot-product (* freq 0.0+1.0i i) fr) n))))
  164. (float-vector->channel out-data 0 out-n snd chn #f (format #f "stretch-sound-via-dft ~A" factor)))))))
  165. ;;; -------- vibrating-uniform-circular-string
  166. ;;;
  167. ;;; this is a simplification of the underlying table-filling routine for "scanned synthesis".
  168. ;;; To watch the wave, open some sound (so Snd has some place to put the graph), turn off
  169. ;;; the time domain display (to give our graph all the window -- to do this in a much more
  170. ;;; elegant manner, see snd-motif.scm under scanned-synthesis).
  171. #|
  172. (define old-vibrating-uniform-circular-string
  173. (lambda (size x0 x1 x2 mass xspring damp)
  174. (define circle-ref
  175. (lambda (v i)
  176. (if (< i 0)
  177. (v (+ size i))
  178. (if (>= i size)
  179. (v (- i size))
  180. (v i)))))
  181. (let* ((dm (/ damp mass))
  182. (km (/ xspring mass))
  183. (denom (+ 1.0 dm))
  184. (p1 (/ (+ 2.0 (- dm (* 2.0 km))) denom))
  185. (p2 (/ km denom))
  186. (p3 (/ -1.0 denom)))
  187. (do ((i 0 (+ i 1)))
  188. ((= i size))
  189. (set! (x0 i) (+ (* p1 (x1 i))
  190. (* p2 (+ (circle-ref x1 (- i 1)) (circle-ref x1 (+ i 1))))
  191. (* p3 (x2 i)))))
  192. (copy x1 x2)
  193. (copy x0 x1))))
  194. ;;; (vibrating-uniform-circular-string 100 (make-float-vector 100) (make-float-vector 100) (make-float-vector 100) .5 .5 .5)
  195. |#
  196. (define (vibrating-uniform-circular-string size x0 x1 x2 mass xspring damp)
  197. (let ((dm (/ damp mass))
  198. (km (/ xspring mass)))
  199. (let ((denom (+ 1.0 dm)))
  200. (let ((p2 (/ km denom))
  201. (s1 (- size 1)))
  202. (float-vector-scale! x2 (/ -1.0 denom))
  203. (copy x1 x0)
  204. (float-vector-scale! x0 (/ (- (+ 2.0 dm) (* 2.0 km)) denom))
  205. (float-vector-add! x0 x2)
  206. (set! (x0 0) (+ (x0 0) (* p2 (+ (x1 s1) (x1 1)))))
  207. (do ((i 1 (+ i 1)))
  208. ((= i s1))
  209. (float-vector-set! x0 i (+ (float-vector-ref x0 i) (* p2 (+ (float-vector-ref x1 (- i 1)) (float-vector-ref x1 (+ i 1)))))))
  210. (set! (x0 s1) (+ (x0 s1) (* p2 (+ (x1 (- s1 1)) (x1 0))))))))
  211. (copy x1 x2)
  212. (copy x0 x1))
  213. (define (vibrating-string size x0 x1 x2 masses xsprings esprings damps haptics)
  214. ;; this is the more general form
  215. (do ((i 0 (+ i 1)))
  216. ((= i size))
  217. (let ((mass (masses i)))
  218. (let ((dm (/ (damps i) mass))
  219. (km (/ (xsprings i) mass))
  220. (cm (/ (esprings i) mass)))
  221. (let ((denom (+ 1.0 dm cm)))
  222. (let ((p1 (/ (- (+ 2.0 dm) (* 2.0 km)) denom))
  223. (p2 (/ km denom))
  224. (p3 (/ -1.0 denom))
  225. (p4 (/ (haptics i) (* mass denom)))
  226. (j (if (= i 0) size (- i 1)))
  227. (k (if (= i (- size 1)) 0 (+ i 1))))
  228. (set! (x0 i) (+ (* p1 (x1 i))
  229. (* p2 (+ (x1 j) (x1 k)))
  230. (* p3 (x2 i))
  231. p4)))))))
  232. (copy x1 x2)
  233. (copy x0 x1))
  234. ;;; -------- "frequency division" -- an effect from sed_sed@my-dejanews.com
  235. (define freqdiv
  236. (let ((documentation "(freqdiv n snd chn) repeats each nth sample n times (clobbering the intermediate samples): (freqdiv 8)"))
  237. (lambda* (n snd chn)
  238. (let* ((data (channel->float-vector 0 #f snd chn))
  239. (len (length data)))
  240. (if (> n 1)
  241. (do ((i 0 (+ i n)))
  242. ((>= i len)
  243. (float-vector->channel data 0 len snd chn))
  244. (let ((val (data i))
  245. (stop (min len (+ i n))))
  246. (do ((k (+ i 1) (+ k 1)))
  247. ((= k stop))
  248. (float-vector-set! data k val)))))))))
  249. ;;; -------- "adaptive saturation" -- an effect from sed_sed@my-dejanews.com
  250. ;;;
  251. ;;; a more extreme effect is "saturation":
  252. ;;; (map-channel (lambda (val) (if (< (abs val) .1) val (if (>= val 0.0) 0.25 -0.25))))
  253. (define adsat
  254. (let ((documentation "(adsat size beg dur snd chn) is an 'adaptive saturation' sound effect"))
  255. (lambda* (size (beg 0) dur snd chn)
  256. (let* ((len (if (number? dur) dur (- (framples snd chn) beg)))
  257. (data (make-float-vector (* size (ceiling (/ len size))))))
  258. (let ((reader (make-sampler beg snd chn))
  259. (mn 0.0)
  260. (mx 0.0)
  261. (vals (make-float-vector size)))
  262. (do ((i 0 (+ i size)))
  263. ((>= i len))
  264. (do ((k 0 (+ k 1)))
  265. ((= k size))
  266. (float-vector-set! vals k (next-sample reader)))
  267. (set! mn (float-vector-min vals))
  268. (set! mx (float-vector-max vals))
  269. (do ((k 0 (+ k 1)))
  270. ((= k size))
  271. (float-vector-set! data (+ i k) (if (negative? (float-vector-ref vals k)) mn mx))))
  272. (float-vector->channel data beg len snd chn current-edit-position (format #f "adsat ~A ~A ~A" size beg dur)))))))
  273. ;;; -------- spike
  274. ;;;
  275. ;;; makes sound more spikey -- sometimes a nice effect
  276. #|
  277. (define spike
  278. (let ((documentation "(spike snd chn) multiplies successive samples together to make a sound more spikey"))
  279. (lambda* (snd chn)
  280. (let* ((len (framples snd chn))
  281. (data (make-float-vector len))
  282. (amp (maxamp snd chn))) ; keep resultant peak at maxamp
  283. (let ((reader (make-sampler 0 snd chn))
  284. (x1 0.0)
  285. (x2 0.0)
  286. (amp1 (/ 1.0 (* amp amp))))
  287. (do ((i 0 (+ i 1)))
  288. ((= i len))
  289. (let ((x0 (next-sample reader)))
  290. (float-vector-set! data i (* x0 x1 x2))
  291. (set! x2 x1)
  292. (set! x1 (abs x0))))
  293. (float-vector->channel (float-vector-scale! data amp1) 0 len snd chn current-edit-position "spike"))))))
  294. |#
  295. (define spike
  296. (let ((documentation "(spike snd chn) multiplies successive samples together to make a sound more spikey"))
  297. (lambda* (snd chn)
  298. (let ((len (framples snd chn)))
  299. (let ((data (channel->float-vector 0 (+ len 2) snd chn))
  300. (amp (maxamp snd chn)) ; keep resultant peak at maxamp
  301. ;; multiply x[0]*x[1]*x[2]
  302. (data1 (make-float-vector (+ len 1))))
  303. (copy data data1 1)
  304. (float-vector-abs! (float-vector-multiply! data1 data))
  305. (float-vector-multiply! data (make-shared-vector data1 (list len) 1))
  306. (let ((amp1 (/ amp (float-vector-peak data))))
  307. (float-vector->channel (float-vector-scale! data amp1) 0 len snd chn current-edit-position "spike")))))))
  308. ;;; the more successive samples we include in the product, the more we
  309. ;;; limit the output to pulses placed at (just after) wave peaks
  310. ;;; -------- easily-fooled autocorrelation-based pitch tracker
  311. (define spot-freq
  312. (let ((documentation "(spot-freq samp snd chn) tries to determine the current pitch: (spot-freq (left-sample))"))
  313. (lambda* (s0 snd chn)
  314. (let* ((fftlen (floor (expt 2 (ceiling (log (/ (srate snd) 20.0) 2)))))
  315. (data (autocorrelate (channel->float-vector s0 fftlen snd chn)))
  316. (cor-peak (float-vector-peak data)))
  317. (if (= cor-peak 0.0)
  318. 0.0
  319. (call-with-exit
  320. (lambda (return)
  321. (do ((i 1 (+ i 1)))
  322. ((= i (- fftlen 2)) 0)
  323. (if (and (< (data i) (data (+ i 1)))
  324. (> (data (+ i 1)) (data (+ i 2))))
  325. (let ((offset (let ((logla (log10 (/ (+ cor-peak (data i)) (* 2 cor-peak))))
  326. (logca (log10 (/ (+ cor-peak (data (+ i 1))) (* 2 cor-peak))))
  327. (logra (log10 (/ (+ cor-peak (data (+ i 2))) (* 2 cor-peak)))))
  328. (/ (* 0.5 (- logla logra))
  329. (+ logla logra (* -2.0 logca))))))
  330. (return (/ (srate snd)
  331. (* 2 (+ i 1 offset))))))))))))))
  332. ;(hook-push graph-hook
  333. ; (lambda (hook)
  334. ; (status-report (format #f "~A" (spot-freq (left-sample))))))
  335. ;;; -------- chorus (doesn't always work and needs speedup)
  336. (define chorus-size 5)
  337. (define chorus
  338. (let ((documentation "(chorus) tries to produce the chorus sound effect"))
  339. (lambda ()
  340. (let ((make-flanger
  341. (let ((chorus-time .05)
  342. (chorus-amount 20.0)
  343. (chorus-speed 10.0))
  344. (lambda ()
  345. (let ((ri (make-rand-interp :frequency chorus-speed :amplitude chorus-amount))
  346. (len (floor (random (* 3.0 chorus-time (srate))))))
  347. (list (make-delay len :max-size (+ len chorus-amount 1)) ri)))))
  348. (flanger (lambda (dly inval)
  349. (+ inval
  350. (delay (car dly)
  351. inval
  352. (rand-interp (cadr dly))))))
  353. (dlys (make-vector chorus-size)))
  354. (do ((i 0 (+ i 1)))
  355. ((= i chorus-size))
  356. (set! (dlys i) (make-flanger)))
  357. (lambda (inval)
  358. (do ((sum 0.0)
  359. (i 0 (+ i 1)))
  360. ((= i chorus-size)
  361. (* .25 sum))
  362. (set! sum (+ sum (flanger (dlys i) inval)))))))))
  363. ;;; -------- chordalize (comb filters to make a chord using chordalize-amount and chordalize-base)
  364. (define chordalize-amount .95)
  365. (define chordalize-base 100)
  366. (define chordalize-chord '(1 3/4 5/4))
  367. (define chordalize
  368. (let ((documentation "(chordalize) uses harmonically-related comb-filters to bring out a chord in a sound"))
  369. (lambda ()
  370. ;; chord is a list of members of chord such as '(1 5/4 3/2)
  371. (let ((combs (make-comb-bank (apply vector (map (lambda (interval)
  372. (make-comb chordalize-amount (floor (* chordalize-base interval))))
  373. chordalize-chord))))
  374. (scaler (/ 0.5 (length chordalize-chord)))) ; just a guess -- maybe this should rescale to old maxamp
  375. (lambda (x)
  376. (* scaler (comb-bank combs x)))))))
  377. ;;; -------- zero-phase, rotate-phase
  378. ;;; fft games (from the "phazor" package of Scott McNab)
  379. (define zero-phase
  380. (let ((documentation "(zero-phase snd chn) calls fft, sets all phases to 0, and un-ffts"))
  381. (lambda* (snd chn)
  382. (let* ((len (framples snd chn))
  383. (fftlen (floor (expt 2 (ceiling (log len 2)))))
  384. (rl (channel->float-vector 0 fftlen snd chn)))
  385. (let ((fftscale (/ 1.0 fftlen))
  386. (old-pk (float-vector-peak rl))
  387. (im (make-float-vector fftlen)))
  388. (if (> old-pk 0.0)
  389. (begin
  390. (fft rl im 1)
  391. (rectangular->magnitudes rl im)
  392. (float-vector-scale! rl fftscale)
  393. (float-vector-scale! im 0.0)
  394. (fft rl im -1)
  395. (let ((pk (float-vector-peak rl)))
  396. (float-vector->channel (float-vector-scale! rl (/ old-pk pk)) 0 len snd chn #f "zero-phase")))))))))
  397. (define rotate-phase
  398. (let ((documentation "(rotate-phase func snd chn) calls fft, applies func to each phase, then un-ffts"))
  399. (lambda* (func snd chn)
  400. (let* ((len (framples snd chn))
  401. (fftlen (floor (expt 2 (ceiling (log len 2)))))
  402. (rl (channel->float-vector 0 fftlen snd chn)))
  403. (let ((fftlen2 (floor (/ fftlen 2)))
  404. (fftscale (/ 1.0 fftlen))
  405. (old-pk (float-vector-peak rl))
  406. (im (make-float-vector fftlen)))
  407. (if (> old-pk 0.0)
  408. (begin
  409. (fft rl im 1)
  410. (rectangular->magnitudes rl im)
  411. (float-vector-scale! rl fftscale)
  412. (set! (im 0) 0.0)
  413. (do ((i 1 (+ i 1))
  414. (j (- fftlen 1) (- j 1)))
  415. ((= i fftlen2))
  416. ;; rotate the fft vector by func, keeping imaginary part complex conjgate of real
  417. (set! (im i) (func (im i)))
  418. (set! (im j) (- (im i))))
  419. (polar->rectangular rl im)
  420. (fft rl im -1)
  421. (let ((pk (float-vector-peak rl)))
  422. (float-vector->channel (float-vector-scale! rl (/ old-pk pk)) 0 len snd chn #f
  423. (format #f "rotate-phase ~A" (procedure-source func)))))))))))
  424. #|
  425. (rotate-phase (lambda (x) 0.0)) is the same as (zero-phase)
  426. (rotate-phase (lambda (x) (random pi))) randomizes phases
  427. (rotate-phase (lambda (x) x)) returns original
  428. (rotate-phase (lambda (x) (- x))) reverses original (might want to write fftlen samps here)
  429. (rotate-phase (lambda (x) (* x 2))) reverb-effect (best with voice)
  430. (rotate-phase (lambda (x) (* x 12)) "bruise blood" effect
  431. |#
  432. (define (signum n)
  433. ;; in CL this returns 1.0 if n is float
  434. (if (positive? n) 1
  435. (if (zero? n) 0
  436. -1)))
  437. ;;; -------- brighten-slightly
  438. (define brighten-slightly
  439. (let ((documentation "(brighten-slightly amount snd chn) is a form of contrast-enhancement ('amount' between ca .1 and 1)"))
  440. (lambda* (amount snd chn)
  441. (let ((len (framples snd chn)))
  442. (let ((mx (maxamp))
  443. (brt (* 2 pi amount))
  444. (data (make-float-vector len))
  445. (reader (make-sampler 0 snd chn)))
  446. (do ((i 0 (+ i 1)))
  447. ((= i len))
  448. (float-vector-set! data i (sin (* (next-sample reader) brt))))
  449. (float-vector->channel
  450. (float-vector-scale! data (/ mx (float-vector-peak data))) 0 len snd chn current-edit-position (format #f "brighten-slightly ~A" amount)))))))
  451. (define brighten-slightly-1
  452. (let ((documentation "(brighten-slightly-1 coeffs) is a form of contrast-enhancement: (brighten-slightly-1 '(1 .5 3 1))"))
  453. (lambda (coeffs)
  454. (let ((pcoeffs (partials->polynomial coeffs))
  455. (mx (maxamp))
  456. (len (framples)))
  457. (let ((data (make-float-vector len))
  458. (reader (make-sampler 0)))
  459. (do ((i 0 (+ i 1)))
  460. ((= i len))
  461. (float-vector-set! data i (polynomial pcoeffs (next-sample reader))))
  462. (float-vector->channel (float-vector-scale! data (/ mx (float-vector-peak data)))))))))
  463. ;;; -------- FIR filters
  464. ;;; Snd's (very simple) spectrum->coefficients procedure is:
  465. (define spectrum->coeffs
  466. (let ((documentation "(spectrum->coeffs order spectr) returns FIR filter coefficients given the filter order and desired spectral envelope (a float-vector)"))
  467. (lambda (order spectr)
  468. (let ((coeffs (make-float-vector order))
  469. (m (floor (/ (+ order 1) 2)))
  470. (am (* 0.5 (+ order 1)))
  471. (q (/ (* pi 2.0) order)))
  472. (if (not (float-vector? spectr))
  473. (error "spectrum->coeffs spectrum argument should be a float-vector"))
  474. (do ((j 0 (+ j 1))
  475. (jj (- order 1) (- jj 1)))
  476. ((= j m) coeffs)
  477. (let ((xt (* 0.5 (spectr 0))))
  478. (do ((i 1 (+ i 1)))
  479. ((= i m))
  480. (set! xt (+ xt (* (spectr i) (cos (* q i (- am j 1)))))))
  481. (let ((coeff (* 2.0 (/ xt order))))
  482. (set! (coeffs j) coeff)
  483. (set! (coeffs jj) coeff))))))))
  484. ;; (filter-channel et al reflect around the midpoint, so to match exactly you need to take
  485. ;; the env passed and flip it backwards for the back portion -- that is to say, this function
  486. ;; needs a wrapper to make it act like anyone would expect)
  487. (define fltit-1
  488. (let ((documentation "(fltit-1 order spectrum) creates an FIR filter from spectrum and order and returns a closure that calls it: \
  489. (map-channel (fltit-1 10 (float-vector 0 1.0 0 0 0 0 0 0 1.0 0)))"))
  490. (lambda (order spectr)
  491. (let ((flt (make-fir-filter order (spectrum->coeffs order spectr))))
  492. (lambda (x)
  493. (fir-filter flt x))))))
  494. ;(map-channel (fltit-1 10 (float-vector 0 1.0 0 0 0 0 0 0 1.0 0)))
  495. ;
  496. ;(let ((notched-spectr (make-float-vector 40)))
  497. ; (set! (notched-spectr 2) 1.0)
  498. ; (set! (notched-spectr 37) 1.0)
  499. ; (map-channel (fltit-1 40 notched-spectr)))
  500. ;
  501. ;;; -------- Hilbert transform
  502. (define make-hilbert-transform
  503. (let ((documentation "(make-hilbert-transform (len 30)) makes a Hilbert transform filter"))
  504. (lambda* ((len 30))
  505. (let ((arrlen (+ 1 (* 2 len))))
  506. (do ((arr (make-float-vector arrlen))
  507. (lim (if (even? len) len (+ 1 len)))
  508. (i (- len) (+ i 1)))
  509. ((= i lim)
  510. (make-fir-filter arrlen arr))
  511. (let ((k (+ i len))
  512. (denom (* pi i))
  513. (num (- 1.0 (cos (* pi i)))))
  514. (set! (arr k)
  515. (if (or (= num 0.0)
  516. (= i 0))
  517. 0.0
  518. ;; this is the "ideal" -- rectangular window -- version:
  519. ;; (set! (arr k) (/ num denom))
  520. ;; this is the Hamming window version:
  521. (* (/ num denom)
  522. (+ .54 (* .46 (cos (/ (* i pi) len))))))))))))) ; window
  523. (define hilbert-transform fir-filter)
  524. #|
  525. (let ((h (make-hilbert-transform 15)))
  526. (map-channel (lambda (y)
  527. (hilbert-transform h y))))
  528. ;;; this comes from R Lyons:
  529. (define* (sound->amp-env snd chn)
  530. (let ((hlb (make-hilbert-transform 40))
  531. (d (make-delay 40)))
  532. (map-channel
  533. (lambda (y)
  534. (let ((hy (hilbert-transform hlb y))
  535. (dy (delay d y)))
  536. (sqrt (+ (* hy hy) (* dy dy)))))
  537. 0 #f snd chn #f "sound->amp-env")))
  538. (define* (hilbert-transform-via-fft snd chn)
  539. ;; same as FIR version but use FFT and change phases by hand
  540. ;; see snd-test.scm test 18 for a faster version
  541. (let* ((size (framples snd chn))
  542. (len (expt 2 (ceiling (log size 2.0))))
  543. (rl (make-float-vector len))
  544. (im (make-float-vector len))
  545. (rd (make-sampler 0 snd chn))
  546. (pi2 (* 0.5 pi)))
  547. (do ((i 0 (+ i 1)))
  548. ((= i size))
  549. (set! (rl i) (rd)))
  550. (mus-fft rl im len)
  551. (do ((i 0 (+ i 1)))
  552. ((= i len))
  553. (let* ((c (complex (rl i) (im i)))
  554. (ph (angle c))
  555. (mag (magnitude c)))
  556. (if (< i (/ len 2))
  557. (set! ph (+ ph pi2))
  558. (set! ph (- ph pi2)))
  559. (set! c (make-polar mag ph))
  560. (set! (rl i) (real-part c))
  561. (set! (im i) (imag-part c))))
  562. (mus-fft rl im len -1)
  563. (float-vector-scale! rl (/ 1.0 len))
  564. (float-vector->channel rl 0 len snd chn #f "hilbert-transform-via-fft")))
  565. |#
  566. ;;; -------- highpass filter
  567. (define make-highpass
  568. (let ((documentation "(make-highpass fc (len 30)) makes an FIR highpass filter"))
  569. (lambda* (fc (len 30))
  570. (let ((arrlen (+ 1 (* 2 len))))
  571. (do ((arr (make-float-vector arrlen))
  572. (i (- len) (+ i 1)))
  573. ((= i len)
  574. (make-fir-filter arrlen arr))
  575. (let ((k (+ i len))
  576. (denom (* pi i))
  577. (num (- (sin (* fc i)))))
  578. (set! (arr k)
  579. (if (= i 0)
  580. (- 1.0 (/ fc pi))
  581. (* (/ num denom)
  582. (+ .54 (* .46 (cos (/ (* i pi) len)))))))))))))
  583. (define highpass fir-filter)
  584. #|
  585. (let ((hp (make-highpass (* .1 pi))))
  586. (map-channel (lambda (y)
  587. (highpass hp y))))
  588. |#
  589. ;;; -------- lowpass filter
  590. (define make-lowpass
  591. (let ((documentation "(make-lowpass fc (len 30)) makes an FIR lowpass filter"))
  592. (lambda* (fc (len 30))
  593. (let ((arrlen (+ 1 (* 2 len))))
  594. (do ((arr (make-float-vector arrlen))
  595. (i (- len) (+ i 1)))
  596. ((= i len)
  597. (make-fir-filter arrlen arr))
  598. (let ((k (+ i len))
  599. (denom (* pi i))
  600. (num (sin (* fc i))))
  601. (set! (arr k)
  602. (if (= i 0)
  603. (/ fc pi)
  604. (* (/ num denom)
  605. (+ .54 (* .46 (cos (/ (* i pi) len)))))))))))))
  606. (define lowpass fir-filter)
  607. #|
  608. (let ((hp (make-lowpass (* .2 pi))))
  609. (map-channel (lambda (y)
  610. (lowpass hp y))))
  611. |#
  612. ;;; -------- bandpass filter
  613. (define make-bandpass
  614. (let ((documentation "(make-bandpass flo fhi (len 30)) makes an FIR bandpass filter"))
  615. (lambda* (flo fhi (len 30))
  616. (let ((arrlen (+ 1 (* 2 len))))
  617. (do ((arr (make-float-vector arrlen))
  618. (i (- len) (+ i 1)))
  619. ((= i len)
  620. (make-fir-filter arrlen arr))
  621. (let ((k (+ i len))
  622. (denom (* pi i))
  623. (num (- (sin (* fhi i)) (sin (* flo i)))))
  624. (set! (arr k)
  625. (if (= i 0)
  626. (/ (- fhi flo) pi)
  627. (* (/ num denom)
  628. (+ .54 (* .46 (cos (/ (* i pi) len)))))))))))))
  629. (define bandpass fir-filter)
  630. #|
  631. (let ((hp (make-bandpass (* .1 pi) (* .2 pi))))
  632. (map-channel (lambda (y)
  633. (bandpass hp y))))
  634. ;; for more bands, you can add the coeffs:
  635. (define* (make-bandpass-2 flo1 fhi1 flo2 fhi2 (len 30))
  636. (let* ((f1 (make-bandpass flo1 fhi1 len))
  637. (f2 (make-bandpass flo2 fhi2 len)))
  638. (float-vector-add! (mus-xcoeffs f1) (mus-xcoeffs f2))
  639. f1))
  640. (let ((ind (new-sound "test.snd")))
  641. (map-channel (lambda (y) (mus-random 1.0)) 0 10000)
  642. (let ((f2 (make-bandpass-2 (* .12 pi) (* .15 pi) (* .22 pi) (* .25 pi) 100)))
  643. (map-channel (lambda (y) (fir-filter f2 y)))
  644. ))
  645. |#
  646. ;;; -------- bandstop filter
  647. (define make-bandstop
  648. (let ((documentation "(make-bandstop flo fhi (len 30)) makes an FIR bandstop (notch) filter"))
  649. (lambda* (flo fhi (len 30))
  650. (let ((arrlen (+ 1 (* 2 len))))
  651. (do ((arr (make-float-vector arrlen))
  652. (i (- len) (+ i 1)))
  653. ((= i len)
  654. (make-fir-filter arrlen arr))
  655. (let ((k (+ i len))
  656. (denom (* pi i))
  657. (num (- (sin (* flo i)) (sin (* fhi i)))))
  658. (set! (arr k)
  659. (if (= i 0)
  660. (- 1.0 (/ (- fhi flo) pi))
  661. (* (/ num denom)
  662. (+ .54 (* .46 (cos (/ (* i pi) len)))))))))))))
  663. (define bandstop fir-filter)
  664. #|
  665. (let ((hp (make-bandstop (* .1 pi) (* .3 pi))))
  666. (map-channel (lambda (y)
  667. (bandstop hp y))))
  668. |#
  669. ;;; -------- differentiator
  670. (define make-differentiator
  671. (let ((documentation "(make-differentiator (len 30)) makes an FIR differentiator (highpass) filter"))
  672. (lambda* ((len 30))
  673. (let ((arrlen (+ 1 (* 2 len))))
  674. (do ((arr (make-float-vector arrlen))
  675. (i (- len) (+ i 1)))
  676. ((= i len)
  677. (make-fir-filter arrlen arr))
  678. (let ((k (+ i len)))
  679. (set! (arr k)
  680. (if (= i 0)
  681. 0.0
  682. (* (/ (cos (* pi i)) i)
  683. (+ .54 (* .46 (cos (/ (* i pi) len)))))))))))))
  684. (define differentiator fir-filter)
  685. #|
  686. (let ((hp (make-differentiator)))
  687. (map-channel (lambda (y)
  688. (differentiator hp y))))
  689. |#
  690. ;;; -------- IIR filters
  691. ;;; see analog-filter.scm for the usual suspects
  692. ;;; -------- Butterworth filters (see also further below -- make-butter-lp et al)
  693. ;;;
  694. ;; translated from CLM butterworth.cl:
  695. ;;
  696. ;; Sam Heisz, January 1998
  697. ;; inspired by some unit generators written for Csound by Paris Smaragdis
  698. ;; who based his work on formulas from
  699. ;; Charles Dodge, Computer music: synthesis, composition, and performance.
  700. (define butter filter)
  701. (define make-butter-high-pass
  702. (let ((documentation "(make-butter-high-pass freq) makes a Butterworth filter with high pass cutoff at 'freq'"))
  703. (lambda (fq)
  704. ;; this is the same as iir-low-pass-2 below with 'din' set to (sqrt 2.0) -- similarly with the others
  705. (let* ((r (tan (/ (* pi fq) (srate))))
  706. (r2 (* r r))
  707. (c1 (/ 1.0 (+ 1.0 (* r (sqrt 2.0)) r2))))
  708. (make-filter 3
  709. (float-vector c1
  710. (* -2.0 c1)
  711. c1)
  712. (float-vector 0.0
  713. (* 2.0 (- r2 1.0) c1)
  714. (* (- (+ 1.0 r2) (* r (sqrt 2.0))) c1)))))))
  715. (define make-butter-low-pass
  716. (let ((documentation "(make-butter-low-pass freq) makes a Butterworth filter with low pass cutoff at 'freq'. The result \
  717. can be used directly: (filter-sound (make-butter-low-pass 500.0)), or via the 'butter' generator"))
  718. (lambda (fq)
  719. (let* ((r (/ 1.0 (tan (/ (* pi fq) (srate)))))
  720. (r2 (* r r))
  721. (c1 (/ 1.0 (+ 1.0 (* r (sqrt 2.0)) r2))))
  722. (make-filter 3
  723. (float-vector c1 (* 2.0 c1) c1)
  724. (float-vector 0.0
  725. (* 2.0 (- 1.0 r2) c1)
  726. (* (- (+ 1.0 r2) (* r (sqrt 2.0))) c1)))))))
  727. (define make-butter-band-pass
  728. (let ((documentation "(make-butter-band-pass freq band) makes a bandpass Butterworth filter with low edge at 'freq' and width 'band'"))
  729. (lambda (fq bw)
  730. (let ((c (/ 1.0 (tan (/ (* pi bw) (srate))))))
  731. (let ((d (* 2.0 (cos (/ (* 2.0 pi fq) (srate)))))
  732. (c1 (/ 1.0 (+ 1.0 c))))
  733. (make-filter 3
  734. (float-vector c1 0.0 (- c1))
  735. (float-vector 0.0
  736. (* (- c) d c1)
  737. (* (- c 1.0) c1))))))))
  738. (define make-butter-band-reject
  739. (let ((documentation "(make-butter-band-reject freq band) makes a band-reject Butterworth filter with low edge at 'freq' and width 'band'"))
  740. (lambda (fq bw)
  741. (let* ((c (tan (/ (* pi bw) (srate))))
  742. (c1 (/ 1.0 (+ 1.0 c)))
  743. (c2 (* c1 -2.0 (cos (/ (* 2.0 pi fq) (srate))))))
  744. (make-filter 3
  745. (float-vector c1 c2 c1)
  746. (float-vector 0.0 c2 (* (- 1.0 c) c1)))))))
  747. ;;; simplest use is (filter-sound (make-butter-low-pass 500.0))
  748. ;;; see also effects.scm
  749. ;;; from "DSP Filter Cookbook" by Lane et al, Prompt Pubs, 2001
  750. ;;;
  751. ;;; use with the filter generator
  752. ;;; (define gen (make-iir-high-pass-2 1000))
  753. ;;; (filter gen 1.0)
  754. ;;; etc
  755. (define make-biquad
  756. (let ((documentation "(make-biquad a0 a1 a2 b1 b2) returns a biquad filter (use with the CLM filter gen)"))
  757. (lambda (a0 a1 a2 b1 b2)
  758. (make-filter 3
  759. (float-vector a0 a1 a2)
  760. (float-vector 0.0 b1 b2)))))
  761. (define (make-local-biquad a0 a1 a2 gamma beta)
  762. (make-biquad a0 a1 a2 (* -2.0 gamma) (* 2.0 beta)))
  763. (define* (make-iir-low-pass-2 fc din) ; din=(sqrt 2.0) for example (suggested range 0.2.. 10)
  764. (let* ((theta (/ (* 2 pi fc) *clm-srate*))
  765. (beta (let ((d (* (sin theta) (/ (or din (sqrt 2.0)) 2))))
  766. (* 0.5 (/ (- 1.0 d) (+ 1.0 d)))))
  767. (gamma (* (+ 0.5 beta) (cos theta)))
  768. (alpha (* 0.5 (- (+ 0.5 beta) gamma))))
  769. (make-local-biquad alpha (* 2.0 alpha) alpha gamma beta)))
  770. (define* (make-iir-high-pass-2 fc din)
  771. (let* ((theta (/ (* 2 pi fc) *clm-srate*))
  772. (beta (let ((d (* (sin theta) (/ (or din (sqrt 2.0)) 2))))
  773. (* 0.5 (/ (- 1.0 d) (+ 1.0 d)))))
  774. (gamma (* (+ 0.5 beta) (cos theta)))
  775. (alpha (* 0.5 (+ 0.5 beta gamma))))
  776. (make-local-biquad alpha (* -2.0 alpha) alpha gamma beta)))
  777. (define (make-iir-band-pass-2 f1 f2)
  778. (let* ((theta (/ (* 2 pi (sqrt (* f1 f2))) *clm-srate*))
  779. (beta (let ((t2 (tan (/ theta (* 2 (/ (sqrt (* f1 f2)) (- f2 f1)))))))
  780. (* 0.5 (/ (- 1.0 t2) (+ 1.0 t2))))))
  781. (let ((gamma (* (+ 0.5 beta) (cos theta)))
  782. (alpha (- 0.5 beta)))
  783. (make-local-biquad alpha 0.0 (- alpha) gamma beta))))
  784. (define (make-iir-band-stop-2 f1 f2)
  785. (let* ((theta (/ (* 2 pi (sqrt (* f1 f2))) *clm-srate*))
  786. (beta (let ((t2 (tan (/ theta (* 2 (/ (sqrt (* f1 f2)) (- f2 f1)))))))
  787. (* 0.5 (/ (- 1.0 t2) (+ 1.0 t2))))))
  788. (let ((gamma (* (+ 0.5 beta) (cos theta)))
  789. (alpha (+ 0.5 beta)))
  790. (make-local-biquad alpha (* -2.0 gamma) alpha gamma beta))))
  791. #|
  792. (define* (old-make-eliminate-hum (hum-freq 60.0) (hum-harmonics 5) (bandwidth 10))
  793. (let ((gen (make-vector hum-harmonics)))
  794. (do ((i 0 (+ i 1)))
  795. ((= i hum-harmonics))
  796. (let ((center (* (+ i 1.0) hum-freq))
  797. (b2 (* 0.5 bandwidth)))
  798. (set! (gen i) (make-iir-band-stop-2 (- center b2) (+ center b2)))))
  799. gen))
  800. (define (old-eliminate-hum gen x0)
  801. (do ((i 0 (+ i 1)))
  802. ((= i (length gen)) x0)
  803. (set! x0 (filter (vector-ref gen i) x0)))) ; "cascade" n filters
  804. ;;; (let ((hummer (old-make-eliminate-hum))) (map-channel (lambda (x) (old-eliminate-hum hummer x))))
  805. |#
  806. ;;; the new form is creating a function/closure of the form:
  807. ;;; (let ((g0 (make-iir-band-stop-2 c00 c01)) (g1 (make-iir-band-stop-2 c10 c11))) (lambda (y) (filter g1 (filter g0 y))))
  808. (define-macro* (make-eliminate-hum (hum-freq 60.0) (hum-harmonics 5) (bandwidth 10))
  809. `(let ((body 'y)
  810. (closure ()))
  811. (do ((i 0 (+ i 1)))
  812. ((= i ,hum-harmonics))
  813. (let ((filt (string->symbol (format #f "g~D" i)))
  814. (center (* (+ i 1.0) ,hum-freq))
  815. (b2 (* 0.5 ,bandwidth)))
  816. (set! body (list 'filter filt body))
  817. (set! closure (cons (list filt (list 'make-iir-band-stop-2 (- center b2) (+ center b2))) closure))))
  818. (apply let closure
  819. `((lambda (y) ,body)))))
  820. ;;; (map-channel (make-eliminate-hum))
  821. (define (make-peaking-2 f1 f2 m)
  822. ;; bandpass, m is gain at center of peak
  823. ;; use map-channel with this one (not clm-channel or filter)
  824. (let ((flt (let* ((theta (/ (* 2 pi (sqrt (* f1 f2))) *clm-srate*))
  825. (beta (let ((t2 (* (/ 4.0 (+ m 1)) (tan (/ theta (* 2 (/ (sqrt (* f1 f2)) (- f2 f1))))))))
  826. (* 0.5 (/ (- 1.0 t2) (+ 1.0 t2))))))
  827. (let ((gamma (* (+ 0.5 beta) (cos theta)))
  828. (alpha (- 0.5 beta)))
  829. (make-local-biquad alpha 0.0 (- alpha) gamma beta))))
  830. (m1 (- m 1.0)))
  831. (lambda (x) (+ x (* m1 (filter flt x))))))
  832. (define cascade->canonical
  833. (let ((documentation "(cascade->canonical A) converts a list of cascade coeffs (float-vectors with 3 entries) to canonical form"))
  834. ;; from Orfanidis "Introduction to Signal Processing"
  835. (lambda (A)
  836. (define (conv M h L x y)
  837. ;; x * h -> y
  838. (do ((n 0 (+ n 1)))
  839. ((= n (+ L M)))
  840. (let ((sum 0.0)
  841. (start (max 0 (- n L 1)))
  842. (end (min n M)))
  843. (do ((m start (+ m 1)))
  844. ((> m end))
  845. (set! sum (+ sum (* (h m) (x (- n m))))))
  846. (set! (y n) sum))))
  847. (let ((K (length A)))
  848. (let ((d (make-float-vector (+ 1 (* 2 K))))
  849. (a1 (make-float-vector (+ 1 (* 2 K)))))
  850. (set! (a1 0) 1.0)
  851. (do ((i 0 (+ i 1)))
  852. ((= i K))
  853. (conv 2 (A i) (+ 1 (* 2 i)) a1 d)
  854. (copy d a1 0 (+ 3 (* 2 i))))
  855. a1)))))
  856. (define make-butter-lp
  857. (let ((documentation "(make-butter-lp M fc) returns a butterworth low-pass filter; its order is 'M' * 2, 'fc' is the cutoff frequency in Hz"))
  858. (lambda (M fc)
  859. (let ((theta (/ (* 2 pi fc) *clm-srate*)))
  860. (do ((xcoeffs ())
  861. (ycoeffs ())
  862. (st (sin theta))
  863. (ct (cos theta))
  864. (k 1 (+ k 1)))
  865. ((> k M)
  866. (make-filter (+ 1 (* 2 M))
  867. (cascade->canonical xcoeffs)
  868. (cascade->canonical ycoeffs)))
  869. (let* ((beta (let ((d (* st (sin (/ (* pi (- (* 2 k) 1)) (* 4 M))))))
  870. (* 0.5 (/ (- 1.0 d) (+ 1.0 d)))))
  871. (gamma (* ct (+ 0.5 beta)))
  872. (alpha (* 0.25 (- (+ 0.5 beta) gamma))))
  873. (set! xcoeffs (cons (float-vector (* 2 alpha) (* 4 alpha) (* 2 alpha)) xcoeffs))
  874. (set! ycoeffs (cons (float-vector 1.0 (* -2.0 gamma) (* 2.0 beta)) ycoeffs))))))))
  875. (define make-butter-hp
  876. (let ((documentation "(make-butter-hp M fc) returns a butterworth high-pass filter; its order is 'M' * 2, 'fc' is the cutoff frequency in Hz"))
  877. (lambda (M fc)
  878. (let ((theta (/ (* 2 pi fc) *clm-srate*)))
  879. (do ((xcoeffs ())
  880. (ycoeffs ())
  881. (st (sin theta))
  882. (ct (cos theta))
  883. (k 1 (+ k 1)))
  884. ((> k M)
  885. (make-filter (+ 1 (* 2 M))
  886. (cascade->canonical xcoeffs)
  887. (cascade->canonical ycoeffs)))
  888. (let* ((beta (let ((d (* st (sin (/ (* pi (- (* 2 k) 1)) (* 4 M))))))
  889. (* 0.5 (/ (- 1.0 d) (+ 1.0 d)))))
  890. (gamma (* ct (+ 0.5 beta)))
  891. (alpha (* 0.25 (+ 0.5 beta gamma))))
  892. (set! xcoeffs (cons (float-vector (* 2 alpha) (* -4 alpha) (* 2 alpha)) xcoeffs))
  893. (set! ycoeffs (cons (float-vector 1.0 (* -2.0 gamma) (* 2.0 beta)) ycoeffs))))))))
  894. (define make-butter-bp
  895. (let ((documentation "(make-butter-bp M f1 f2) returns a butterworth band-pass filter; its order is 'M' * 2, 'f1' and 'f2' are the band edge frequencies in Hz"))
  896. (lambda (M f1 f2)
  897. (let* ((f0 (sqrt (* f1 f2)))
  898. (theta0 (/ (* 2 pi f0) *clm-srate*))
  899. (de (let ((Q (/ f0 (- f2 f1))))
  900. (/ (* 2 (tan (/ theta0 (* 2 Q)))) (sin theta0)))))
  901. (do ((xcoeffs ())
  902. (ycoeffs ())
  903. (de2 (/ de 2))
  904. (tn0 (tan (* theta0 0.5)))
  905. (i 1 (+ i 1))
  906. (k 1)
  907. (j 1))
  908. ((> i M)
  909. (make-filter (+ 1 (* 2 M))
  910. (cascade->canonical xcoeffs)
  911. (cascade->canonical ycoeffs)))
  912. (let* ((Dk (* 2 (sin (/ (* pi (- (* 2 k) 1)) (* 2 M)))))
  913. (dk1 (let ((Ak (/ (+ 1 (* de2 de2)) (* Dk de2))))
  914. (sqrt (/ (* de Dk)
  915. (+ Ak (sqrt (- (* Ak Ak) 1)))))))
  916. (Wk (let ((Bk (* de2 (/ Dk dk1))))
  917. (real-part (+ Bk (sqrt (- (* Bk Bk) 1.0)))))) ; fp inaccuracies causing tiny (presumably bogus) imaginary part here
  918. (thetajk (* 2 (if (= j 1) (atan tn0 Wk) (atan (* tn0 Wk)))))
  919. (betajk (* 0.5 (/ (- 1.0 (* 0.5 dk1 (sin thetajk)))
  920. (+ 1.0 (* 0.5 dk1 (sin thetajk)))))))
  921. (let ((gammajk (* (+ 0.5 betajk) (cos thetajk)))
  922. (alphajk (let ((wk2 (/ (- Wk (/ 1.0 Wk)) dk1)))
  923. (* 0.5 (- 0.5 betajk) (sqrt (+ 1.0 (* wk2 wk2)))))))
  924. (set! xcoeffs (cons (float-vector (* 2 alphajk) 0.0 (* -2 alphajk)) xcoeffs))
  925. (set! ycoeffs (cons (float-vector 1.0 (* -2.0 gammajk) (* 2.0 betajk)) ycoeffs))))
  926. (if (= j 1)
  927. (set! j 2)
  928. (begin
  929. (set! k (+ k 1))
  930. (set! j 1))))))))
  931. (define make-butter-bs
  932. (let ((documentation "(make-butter-bs M f1 f2) returns a butterworth band-stop filter; its order is 'M' * 2, 'f1' and 'f2' are the band edge frequencies in Hz"))
  933. (lambda (M f1 f2)
  934. (let* ((f0 (sqrt (* f1 f2)))
  935. (theta0 (/ (* 2 pi f0) *clm-srate*))
  936. (de (let ((Q (/ f0 (- f2 f1))))
  937. (/ (* 2 (tan (/ theta0 (* 2 Q)))) (sin theta0)))))
  938. (do ((xcoeffs ())
  939. (ycoeffs ())
  940. (de2 (/ de 2))
  941. (ct (cos theta0))
  942. (tn0 (tan (* theta0 0.5)))
  943. (i 1 (+ i 1))
  944. (k 1)
  945. (j 1))
  946. ((> i M)
  947. (make-filter (+ 1 (* 2 M))
  948. (cascade->canonical xcoeffs)
  949. (cascade->canonical ycoeffs)))
  950. (let* ((Dk (* 2 (sin (/ (* pi (- (* 2 k) 1)) (* 2 M)))))
  951. (dk1 (let ((Ak (/ (+ 1 (* de2 de2)) (* Dk de2))))
  952. (sqrt (/ (* de Dk)
  953. (+ Ak (sqrt (- (* Ak Ak) 1)))))))
  954. (thetajk (let ((Wk (let ((Bk (* de2 (/ Dk dk1))))
  955. (real-part (+ Bk (sqrt (- (* Bk Bk) 1.0)))))))
  956. (* 2 (if (= j 1) (atan tn0 Wk) (atan (* tn0 Wk))))))
  957. (betajk (* 0.5 (/ (- 1.0 (* 0.5 dk1 (sin thetajk)))
  958. (+ 1.0 (* 0.5 dk1 (sin thetajk)))))))
  959. (let ((gammajk (* (+ 0.5 betajk) (cos thetajk)))
  960. (alphajk (/ (* 0.5 (+ 0.5 betajk) (- 1.0 (cos thetajk))) (- 1.0 ct))))
  961. (set! xcoeffs (cons (float-vector (* 2 alphajk) (* -4 ct alphajk) (* 2 alphajk)) xcoeffs))
  962. (set! ycoeffs (cons (float-vector 1.0 (* -2.0 gammajk) (* 2.0 betajk)) ycoeffs))))
  963. (if (= j 1)
  964. (set! j 2)
  965. (begin
  966. (set! k (+ k 1))
  967. (set! j 1))))))))
  968. ;;; -------- notch filters
  969. (define* (make-notch-frequency-response cur-srate freqs (notch-width 2))
  970. (let ((freq-response (list 1.0 0.0)))
  971. (for-each
  972. (lambda (i)
  973. (set! freq-response (cons 1.0 (cons (/ (* 2 (- i notch-width)) cur-srate) freq-response))) ; left upper y resp hz
  974. (set! freq-response (cons 0.0 (cons (/ (* 2 (- i (/ notch-width 2))) cur-srate) freq-response))) ; left bottom y resp hz
  975. (set! freq-response (cons 0.0 (cons (/ (* 2 (+ i (/ notch-width 2))) cur-srate) freq-response))) ; right bottom y resp hz
  976. (set! freq-response (cons 1.0 (cons (/ (* 2 (+ i notch-width)) cur-srate) freq-response)))) ; right upper y resp hz
  977. freqs)
  978. (set! freq-response (cons 1.0 (cons 1.0 freq-response)))
  979. (reverse freq-response)))
  980. (define notch-channel
  981. (let ((documentation "(notch-channel freqs filter-order beg dur snd chn edpos (truncate #t) (notch-width 2)) -> notch filter removing freqs"))
  982. (lambda* (freqs filter-order beg dur snd chn edpos (truncate #t) (notch-width 2))
  983. (filter-channel (make-notch-frequency-response (* 1.0 (srate snd)) freqs notch-width)
  984. (or filter-order (min (framples snd chn) (expt 2 (floor (log (/ (srate snd) notch-width) 2)))))
  985. beg dur snd chn edpos truncate
  986. (format #f "notch-channel '~A ~A ~A ~A" freqs filter-order beg dur)))))
  987. (define notch-sound
  988. (let ((documentation "(notch-sound freqs filter-order snd chn (notch-width 2)) -> notch filter removing freqs"))
  989. (lambda* (freqs filter-order snd chn (notch-width 2))
  990. (filter-sound (make-notch-frequency-response (* 1.0 (srate snd)) freqs notch-width)
  991. (or filter-order (min (framples snd chn) (expt 2 (floor (log (/ (srate snd) notch-width) 2)))))
  992. snd chn #f
  993. (format #f "notch-channel '~A ~A 0 #f" freqs filter-order)))))
  994. (define notch-selection
  995. (let ((documentation "(notch-selection freqs filter-order (notch-width 2)) -> notch filter removing freqs"))
  996. (lambda* (freqs filter-order (notch-width 2))
  997. (if (selection?)
  998. (filter-selection (make-notch-frequency-response (* 1.0 (selection-srate)) freqs notch-width)
  999. (or filter-order (min (selection-framples) (expt 2 (floor (log (/ (selection-srate) notch-width) 2))))))))))
  1000. ;; apparently I'm using powers of 2 here so that mus_make_fir_coeffs, called from get_filter_coeffs, can use an fft
  1001. ;; the others use the fft internally for the fir filter, but not filter-selection
  1002. ;;; -------- fractional Fourier Transform, z transform
  1003. ;;;
  1004. ;;; translated from the fxt package of Joerg Arndt
  1005. (define fractional-fourier-transform
  1006. (let ((documentation "(fractional-fourier-transform real imaginary n angle) performs a fractional Fourier transform on data; if angle=1.0, you get a normal Fourier transform"))
  1007. (lambda (fr fi n v)
  1008. ;; this is the slow (dft) form
  1009. ;; v=1 -> normal fourier transform
  1010. (do ((hr (make-float-vector n))
  1011. (hi (make-float-vector n))
  1012. (ph0 (/ (* v 2 pi) n))
  1013. (w 0 (+ 1 w))
  1014. (sr 0.0 0.0)
  1015. (si 0.0 0.0))
  1016. ((= w n)
  1017. (list hr hi))
  1018. (do ((k 0 (+ k 1)))
  1019. ((= k n))
  1020. (let ((phase (* ph0 k w)))
  1021. (let ((c (cos phase))
  1022. (s (sin phase))
  1023. (x (fr k))
  1024. (y (fi k)))
  1025. (let ((r (- (* x c) (* y s)))
  1026. (i (+ (* y c) (* x s))))
  1027. (set! sr (+ sr r))
  1028. (set! si (+ si i))))))
  1029. (set! (hr w) sr)
  1030. (set! (hi w) si)))))
  1031. (define z-transform
  1032. (let ((documentation "(z-transform data n z) performs a Z transform on data; if z=e^2*pi*j/n you get a Fourier transform; complex results in returned vector"))
  1033. (lambda (f n z)
  1034. ;; using vector to allow complex sums (z=e^2*pi*i/n -> fourier transform)
  1035. ;; (z-transform data n (exp (complex 0.0 (* (/ 2.0 n) pi))))
  1036. (let ((res ((if (float-vector? f) make-float-vector make-vector) n)))
  1037. (do ((w 0 (+ 1 w)))
  1038. ((= w n))
  1039. (do ((sum 0.0)
  1040. (t 1.0)
  1041. (m (expt z w))
  1042. ;; -w?? there seems to be confusion here -- slowzt.cc in the fxt package uses +w
  1043. (k 0 (+ k 1)))
  1044. ((= k n)
  1045. (set! (res w) sum))
  1046. (set! sum (+ sum (* (f k) t)))
  1047. (set! t (* t m))))
  1048. res))))
  1049. ;;; -------- slow Hartley transform
  1050. (define dht
  1051. (let ((documentation "(dht data) returns the Hartley transform of 'data'."))
  1052. (lambda (data)
  1053. ;; taken from Perry Cook's SignalProcessor.m (the slow version of the Hartley transform)
  1054. (let ((len (length data)) )
  1055. (do ((arr (make-float-vector len))
  1056. (w (/ (* 2.0 pi) len))
  1057. (i 0 (+ i 1)))
  1058. ((= i len) arr)
  1059. (do ((j 0 (+ j 1)))
  1060. ((= j len))
  1061. (set! (arr i) (+ (arr i)
  1062. (* (data j)
  1063. (+ (cos (* i j w))
  1064. (sin (* i j w))))))))))))
  1065. (define find-sine
  1066. (let ((documentation "(find-sine freq beg dur snd) returns the amplitude and initial-phase (for sin) at freq"))
  1067. (lambda* (freq beg dur snd)
  1068. (let ((incr (/ (* freq 2 pi) (srate snd)))
  1069. (sw 0.0)
  1070. (cw 0.0)
  1071. (reader (make-sampler beg snd))
  1072. (samp 0.0))
  1073. (do ((i 0 (+ i 1)) ; this could also use edot-product
  1074. (x 0.0 (+ x incr)))
  1075. ((= i dur))
  1076. (set! samp (next-sample reader))
  1077. (set! sw (+ sw (* samp (sin x))))
  1078. (set! cw (+ cw (* samp (cos x)))))
  1079. (list (* 2 (/ (sqrt (+ (* sw sw) (* cw cw))) dur))
  1080. (atan cw sw))))))
  1081. ;;; this is a faster version of find-sine using the "Goertzel algorithm" taken from R Lyons "Understanding DSP" p 529
  1082. ;;; it returns the same result as find-sine above if you take (* 2 (/ (goertzel...) dur)) -- see snd-test.scm examples
  1083. (define goertzel
  1084. (let ((documentation "(goertzel freq beg dur snd) returns the amplitude of the 'freq' spectral component"))
  1085. (lambda* (freq (beg 0) dur snd)
  1086. (let* ((rfreq (/ (* 2.0 pi freq) (srate snd)))
  1087. (cs (* 2.0 (cos rfreq))))
  1088. (let ((reader (make-sampler beg snd 0))
  1089. (len (- (if (number? dur) dur (- (framples snd 0) beg)) 2))
  1090. (flt (make-two-pole 1.0 (- cs) 1.0)))
  1091. (do ((i 0 (+ i 1)))
  1092. ((= i len))
  1093. (two-pole flt (next-sample reader)))
  1094. (let ((y1 (two-pole flt (next-sample reader)))
  1095. (y0 (two-pole flt (next-sample reader))))
  1096. (magnitude (- y0 (* y1 (exp (complex 0.0 (- rfreq))))))))))))
  1097. #|
  1098. ;; old version:
  1099. (let ((y2 0.0)
  1100. (y1 0.0)
  1101. (y0 0.0)
  1102. (reader (make-sampler beg snd 0))
  1103. (len (if (number? dur) dur (- (framples snd 0) beg))))
  1104. (do ((i 0 (+ i 1)))
  1105. ((= i len))
  1106. (set! y2 y1)
  1107. (set! y1 y0)
  1108. (set! y0 (+ (- (* y1 cs) y2) (next-sample reader))))
  1109. |#
  1110. (define make-spencer-filter
  1111. (let ((documentation "(make-spencer-filter) is a version of make-fir-filter; it returns one of the standard smoothing filters from \
  1112. the era when computers were human beings"))
  1113. (lambda ()
  1114. (make-fir-filter 15 (apply float-vector (map (lambda (n) (/ n 320.0)) '(-3 -6 -5 3 21 46 67 74 67 46 21 3 -5 -6 -3)))))))
  1115. ;;; -------- any-random
  1116. ;;;
  1117. ;;; arbitrary random number distributions via the "rejection method"
  1118. (define* (any-random amount e)
  1119. (if (= amount 0.0)
  1120. 0.0
  1121. (if (not e)
  1122. (random amount)
  1123. (let next-random ()
  1124. (let ((x (random (* 1.0 (e (- (length e) 2)))))
  1125. (y (random 1.0)))
  1126. (if (<= y (envelope-interp x e))
  1127. x
  1128. (next-random)))))))
  1129. (define (gaussian-distribution s)
  1130. (do ((e ())
  1131. (den (* 2.0 s s))
  1132. (i 0 (+ i 1))
  1133. (x 0.0 (+ x .05))
  1134. (y -4.0 (+ y .4)))
  1135. ((= i 21)
  1136. (reverse e))
  1137. (set! e (cons (exp (- (/ (* y y) den))) (cons x e)))))
  1138. (define (pareto-distribution a)
  1139. (do ((e ())
  1140. (scl (/ (expt 1.0 (+ a 1.0)) a))
  1141. (i 0 (+ i 1))
  1142. (x 0.0 (+ x .05))
  1143. (y 1.0 (+ y .2)))
  1144. ((= i 21)
  1145. (reverse e))
  1146. (set! e (cons (* scl (/ a (expt y (+ a 1.0)))) (cons x e)))))
  1147. ;(map-channel (lambda (y) (any-random 1.0 '(0 1 1 1)))) ; uniform distribution
  1148. ;(map-channel (lambda (y) (any-random 1.0 '(0 0 0.95 0.1 1 1)))) ; mostly toward 1.0
  1149. ;(let ((g (gaussian-distribution 1.0))) (map-channel (lambda (y) (any-random 1.0 g))))
  1150. ;(let ((g (pareto-distribution 1.0))) (map-channel (lambda (y) (any-random 1.0 g))))
  1151. ;;; this is the inverse integration function used by CLM to turn a distribution function into a weighting function
  1152. (define* (inverse-integrate dist (data-size 512) (e-size 50))
  1153. (let ((sum (cadr dist))
  1154. (x0 (car dist)))
  1155. (let ((first-sum sum)
  1156. (data (make-float-vector data-size))
  1157. (e ())
  1158. (xincr (/ (- (dist (- (length dist) 2)) x0) e-size)))
  1159. (do ((i 0 (+ i 1))
  1160. (x x0 (+ x xincr)))
  1161. ((> i e-size))
  1162. (set! e (cons x (cons sum e)))
  1163. (set! sum (+ sum (envelope-interp x dist))))
  1164. (let ((incr (/ (- (cadr e) first-sum) (- data-size 1))))
  1165. (set! e (reverse e))
  1166. (do ((i 0 (+ i 1))
  1167. (x first-sum (+ x incr)))
  1168. ((= i data-size))
  1169. (set! (data i) (envelope-interp x e)))
  1170. data))))
  1171. (define (gaussian-envelope s)
  1172. (do ((e ())
  1173. (den (* 2.0 s s))
  1174. (i 0 (+ i 1))
  1175. (x -1.0 (+ x .1))
  1176. (y -4.0 (+ y .4)))
  1177. ((= i 21)
  1178. (reverse e))
  1179. (set! e (cons (exp (- (/ (* y y) den))) (cons x e)))))
  1180. ;;; (make-rand :envelope (gaussian-envelope 1.0))
  1181. ;;; ---------------- Julius Smith stuff ----------------
  1182. ;;;
  1183. ;;; these are from "Mathematics of the DFT", W3K Pubs
  1184. (define channel-mean ; <f, 1> / n
  1185. (let ((documentation "(channel-mean snd chn) returns the average of the samples in the given channel: <f,1>/n"))
  1186. (lambda* (snd chn)
  1187. (let ((N (framples snd chn))
  1188. (reader (make-sampler 0 snd chn))
  1189. (incr (make-one-pole 1.0 -1.0)))
  1190. (do ((i 0 (+ i 1)))
  1191. ((= i N))
  1192. (one-pole incr (next-sample reader)))
  1193. (/ (one-pole incr 0.0) N)))))
  1194. (define channel-total-energy ; <f, f>
  1195. (let ((documentation "(channel-total-energy snd chn) returns the sum of the squares of all the samples in the given channel: <f,f>"))
  1196. (lambda* (snd chn)
  1197. (let ((data (samples 0 (framples snd chn) snd chn)))
  1198. (dot-product data data)))))
  1199. #|
  1200. (let ((sum 0.0)
  1201. (N (framples snd chn))
  1202. (reader (make-sampler 0 snd chn)))
  1203. (do ((i 0 (+ i 1)))
  1204. ((= i N))
  1205. (let ((y (next-sample reader)))
  1206. (set! sum (+ sum (* y y)))))
  1207. sum))
  1208. |#
  1209. (define channel-average-power ; <f, f> / n
  1210. (let ((documentation "(channel-average-power snd chn) returns the average power in the given channel: <f,f>/n"))
  1211. (lambda* (snd chn)
  1212. (/ (channel-total-energy snd chn) (framples snd chn)))))
  1213. (define channel-rms ; sqrt(<f, f> / n)
  1214. (let ((documentation "(channel-rms snd chn) returns the RMS value of the samples in the given channel: sqrt(<f,f>/n)"))
  1215. (lambda* (snd chn)
  1216. (sqrt (channel-average-power snd chn)))))
  1217. (define channel-variance ; "sample-variance" might be better, <f, f> - (<f, 1> / n) ^ 2 with quibbles
  1218. (let ((documentation "(channel-variance snd chn) returns the sample variance in the given channel: <f,f>-((<f,1>/ n)^2"))
  1219. (lambda* (snd chn)
  1220. (let ((mu (let ((N (framples snd chn)))
  1221. (* (/ N (- N 1)) (channel-mean snd chn))))) ; avoid bias sez JOS
  1222. (- (channel-total-energy snd chn)
  1223. (* mu mu))))))
  1224. (define channel-norm ; sqrt(<f, f>)
  1225. (let ((documentation "(channel-norm snd chn) returns the norm of the samples in the given channel: sqrt(<f,f>)"))
  1226. (lambda* (snd chn)
  1227. (sqrt (channel-total-energy snd chn)))))
  1228. (define channel-lp
  1229. (let ((documentation "(channel-lp p snd chn) returns the Lp norm of the samples in the given channel"))
  1230. (lambda* (p snd chn)
  1231. (let ((incr (make-one-pole 1.0 -1.0))
  1232. (N (framples snd chn))
  1233. (reader (make-sampler 0 snd chn)))
  1234. (do ((i 0 (+ i 1)))
  1235. ((= i N))
  1236. (one-pole incr (expt (abs (next-sample reader)) p)))
  1237. (expt (one-pole incr 0.0) (/ 1.0 p))))))
  1238. (define channel-lp-inf maxamp)
  1239. #|
  1240. "(channel-lp-inf snd chn) returns the maxamp in the given channel (the name is just math jargon for maxamp)"
  1241. (let ((mx 0.0)
  1242. (N (framples snd chn))
  1243. (reader (make-sampler 0 snd chn)))
  1244. (do ((i 0 (+ i 1)))
  1245. ((= i N))
  1246. (set! mx (max mx (abs (next-sample reader)))))
  1247. mx))
  1248. |#
  1249. (define channel2-inner-product ; <f, g>
  1250. (let ((documentation "(channel2-inner-product s1 c1 s2 c2) returns the inner-product of the two channels: <f,g>"))
  1251. (lambda (s1 c1 s2 c2)
  1252. (dot-product (samples 0 (framples s1 c1) s1 c1) (samples 0 (framples s1 c1) s2 c2)))))
  1253. #|
  1254. (let ((N (framples s1 c1))
  1255. (sum 0.0)
  1256. (r1 (make-sampler 0 s1 c1))
  1257. (r2 (make-sampler 0 s2 c2)))
  1258. (do ((i 0 (+ i 1)))
  1259. ((= i N))
  1260. (set! sum (+ sum (* (r1) (r2)))))
  1261. sum))
  1262. |#
  1263. (define channel2-angle ; acos(<f, g> / (sqrt(<f, f>) * sqrt(<g, g>)))
  1264. (let ((documentation "(channel2-angle s1 c1 s2 c2) treats the two channels as vectors, returning the 'angle' between them: acos(<f,g>/(sqrt(<f,f>)*sqrt(<g,g>)))"))
  1265. (lambda (s1 c1 s2 c2)
  1266. (let ((inprod (channel2-inner-product s1 c1 s2 c2))
  1267. (norm1 (channel-norm s1 c1))
  1268. (norm2 (channel-norm s2 c2)))
  1269. (acos (/ inprod (* norm1 norm2)))))))
  1270. (define channel2-orthogonal? ; <f, g> == 0
  1271. (let ((documentation "(channel2-orthogonal? s1 c1 s2 c2) returns #t if the two channels' inner-product is 0: <f,g>==0"))
  1272. (lambda (s1 c1 s2 c2)
  1273. (= (channel2-inner-product s1 c1 s2 c2) 0.0))))
  1274. (define channel2-coefficient-of-projection ; s1,c1 = x, s2,c2 = y, <f, g> / <f, f>
  1275. (let ((documentation "(channel2-coefficient-of-projection s1 c1 s2 c2) returns <f,g>/<f,f>"))
  1276. (lambda (s1 c1 s2 c2)
  1277. (/ (channel2-inner-product s1 c1 s2 c2)
  1278. (channel-total-energy s1 c1)))))
  1279. ;;; -------- end of JOS stuff --------
  1280. #|
  1281. (define channel-distance-1 ; sqrt(<f - g, f - g>)
  1282. (let ((documentation "(channel-distance s1 c1 s2 c2) returns the euclidean distance between the two channels: sqrt(<f-g,f-g>)"))
  1283. (lambda* ((s1 0) (c1 0) (s2 1) (c2 0))
  1284. (let ((r1 (make-sampler 0 s1 c1))
  1285. (r2 (make-sampler 0 s2 c2))
  1286. (sum 0.0)
  1287. (N (min (framples s1 c1) (framples s2 c2)))
  1288. (diff 0.0))
  1289. (do ((i 0 (+ i 1)))
  1290. ((= i N))
  1291. (set! diff (- (r1) (r2)))
  1292. (set! sum (+ sum (* diff diff))))
  1293. (sqrt sum)))))
  1294. |#
  1295. (define channel-distance ; sqrt(<f - g, f - g>)
  1296. (let ((documentation "(channel-distance s1 c1 s2 c2) returns the euclidean distance between the two channels: sqrt(<f-g,f-g>)"))
  1297. (lambda* ((s1 0) (c1 0) (s2 1) (c2 0))
  1298. (let ((N (min (framples s1 c1) (framples s2 c2))))
  1299. (let ((data1 (samples 0 N s1 c1))
  1300. (data2 (samples 0 N s2 c2)))
  1301. (float-vector-subtract! data1 data2)
  1302. (sqrt (dot-product data1 data1)))))))
  1303. (define periodogram
  1304. (let ((documentation "(periodogram N) displays an 'N' point Bartlett periodogram of the samples in the current channel"))
  1305. (lambda (N)
  1306. (let ((N2 (* 2 N)))
  1307. (let ((len (framples))
  1308. (average-data (make-float-vector N))
  1309. (rd (make-sampler 0))
  1310. (rl (make-float-vector N2))
  1311. (im (make-float-vector N2)))
  1312. (do ((i 0 (+ i N)))
  1313. ((>= i len))
  1314. (float-vector-scale! rl 0.0)
  1315. (float-vector-scale! im 0.0)
  1316. (do ((k 0 (+ k 1)))
  1317. ((= k N))
  1318. (float-vector-set! rl k (read-sample rd)))
  1319. (mus-fft rl im)
  1320. (float-vector-multiply! rl rl)
  1321. (float-vector-multiply! im im)
  1322. (float-vector-add! average-data (float-vector-add! rl im)))
  1323. ;; or add snd-spectrum results
  1324. (graph (float-vector-scale! average-data (/ 1.0 (ceiling (/ len N))))))))))
  1325. ;;; -------- ssb-am friends
  1326. (define shift-channel-pitch
  1327. (let ((documentation "(shift-channel-pitch freq (order 40) (beg 0) dur snd chn edpos) uses the ssb-am CLM generator to \
  1328. shift the given channel in pitch without changing its length. The higher 'order', the better usually."))
  1329. (lambda* (freq (order 40) (beg 0) dur snd chn edpos)
  1330. ;; higher order = better cancellation
  1331. (let ((gen (make-ssb-am freq order)))
  1332. (map-channel (lambda (y)
  1333. (ssb-am gen y))
  1334. beg dur snd chn edpos
  1335. (format #f "shift-channel-pitch ~A ~A ~A ~A" freq order beg dur))))))
  1336. (define hz->2pi
  1337. (let ((documentation "(hz->2pi freq) is like hz->radians but uses the current sound's srate, not mus-srate"))
  1338. (lambda (freq)
  1339. (/ (* 2 pi freq) (srate)))))
  1340. (define* (ssb-bank old-freq new-freq pairs (order 40) (bw 50.0) (beg 0) dur snd chn edpos)
  1341. (let ((ssbs (make-vector pairs))
  1342. (bands (make-vector pairs))
  1343. (factor (/ (- new-freq old-freq) old-freq)))
  1344. (do ((i 1 (+ i 1)))
  1345. ((> i pairs))
  1346. (let ((aff (* i old-freq))
  1347. (bwf (* bw (+ 1.0 (/ i (* 2 pairs))))))
  1348. (set! (ssbs (- i 1)) (make-ssb-am (* i factor old-freq)))
  1349. (set! (bands (- i 1)) (make-bandpass (hz->2pi (- aff bwf))
  1350. (hz->2pi (+ aff bwf))
  1351. order))))
  1352. (let ((data (channel->float-vector beg dur snd chn edpos)))
  1353. (let ((len (length data))
  1354. (mx (float-vector-peak data)))
  1355. (let ((summer (make-float-vector len)))
  1356. (set! *output* summer)
  1357. (do ((i 0 (+ i 1)))
  1358. ((= i pairs))
  1359. (do ((gen (vector-ref ssbs i))
  1360. (filt (vector-ref bands i))
  1361. (k 0 (+ k 1)))
  1362. ((= k len))
  1363. (outa k (ssb-am gen (bandpass filt (ina k data)))))) ; outa adds, (ina i v) is the same as (float-vector-ref v i)
  1364. (set! *output* #f)
  1365. (float-vector-scale! summer (/ mx (float-vector-peak summer)))
  1366. (float-vector->channel summer beg len snd chn current-edit-position
  1367. (format #f "ssb-bank ~A ~A ~A ~A ~A ~A ~A" old-freq new-freq pairs order bw beg dur)))))))
  1368. ;;; (let ((ind (open-sound "oboe.snd"))) (ssb-bank 550.0 660.0 10))
  1369. (define* (ssb-bank-env old-freq new-freq freq-env pairs (order 40) (bw 50.0) (beg 0) dur snd chn edpos)
  1370. ;; this version adds a frequency envelope
  1371. ;; (ssb-bank-env 557 880 '(0 0 1 100.0) 7)
  1372. (let ((ssbs (make-vector pairs))
  1373. (bands (make-vector pairs))
  1374. (factor (/ (- new-freq old-freq) old-freq))
  1375. (frenvs (make-vector pairs)))
  1376. (do ((i 1 (+ i 1)))
  1377. ((> i pairs))
  1378. (let ((aff (* i old-freq))
  1379. (bwf (* bw (+ 1.0 (/ i (* 2 pairs))))))
  1380. (set! (ssbs (- i 1)) (make-ssb-am (* i factor old-freq)))
  1381. (set! (bands (- i 1)) (make-bandpass (hz->2pi (- aff bwf))
  1382. (hz->2pi (+ aff bwf))
  1383. order))
  1384. (set! (frenvs (- i 1)) (make-env freq-env
  1385. :scaler (hz->radians i)
  1386. :length (framples)))))
  1387. (let ((data (channel->float-vector beg dur snd chn edpos)))
  1388. (let ((len (length data))
  1389. (mx (float-vector-peak data)))
  1390. (let ((summer (make-float-vector len)))
  1391. (set! *output* summer)
  1392. (do ((i 0 (+ i 1)))
  1393. ((= i pairs))
  1394. (do ((gen (vector-ref ssbs i))
  1395. (filt (vector-ref bands i))
  1396. (e (vector-ref frenvs i))
  1397. (k 0 (+ k 1)))
  1398. ((= k len))
  1399. (outa k (ssb-am gen (bandpass filt (ina k data)) (env e)))))
  1400. (set! *output* #f)
  1401. (float-vector-scale! summer (/ mx (float-vector-peak summer)))
  1402. (float-vector->channel summer beg len snd chn current-edit-position
  1403. (format #f "ssb-bank-env ~A ~A '~A ~A ~A ~A ~A ~A" old-freq new-freq freq-env pairs order bw beg dur)))))))
  1404. ;;; (let ((ind (open-sound "oboe.snd"))) (ssb-bank-env 550 600 '(0 1 1 2) 10))
  1405. #|
  1406. ;;; a "bump function" (Stein and Shakarchi)
  1407. (define (bumpy)
  1408. (let* ((x 0.0)
  1409. (xi (/ 1.0 (framples)))
  1410. (start 0)
  1411. (end 1)
  1412. (scl (exp (/ 4.0 (- end start))))) ; normalize it
  1413. (map-channel (lambda (y)
  1414. (let ((val (if (or (<= x start) ; don't divide by zero
  1415. (>= x end))
  1416. 0.0
  1417. (* (exp (/ -1.0 (- x start)))
  1418. (exp (/ -1.0 (- end x)))))))
  1419. (set! x (+ x xi))
  1420. (* scl val))))))
  1421. |#
  1422. ;;; float-vector|channel|spectral-polynomial
  1423. (define (float-vector-polynomial v coeffs)
  1424. ;; Horner's rule applied to entire float-vector
  1425. (let* ((num-coeffs (length coeffs))
  1426. (new-v (make-float-vector (length v) (coeffs (- num-coeffs 1)))))
  1427. (do ((i (- num-coeffs 2) (- i 1)))
  1428. ((< i 0))
  1429. (float-vector-offset! (float-vector-multiply! new-v v) (coeffs i)))
  1430. new-v))
  1431. (define* (channel-polynomial coeffs snd chn)
  1432. (let ((len (framples snd chn)))
  1433. (float-vector->channel
  1434. (float-vector-polynomial
  1435. (channel->float-vector 0 len snd chn)
  1436. coeffs)
  1437. 0 len snd chn #f (format #f "channel-polynomial ~A" (float-vector->string coeffs)))))
  1438. ;;; (channel-polynomial (float-vector 0.0 .5)) = x*.5
  1439. ;;; (channel-polynomial (float-vector 0.0 1.0 1.0 1.0)) = x*x*x + x*x + x
  1440. ;;; convolution -> * in freq
  1441. (define* (spectral-polynomial coeffs snd chn)
  1442. (let* ((len (framples snd chn))
  1443. (num-coeffs (length coeffs))
  1444. (fft-len (if (< num-coeffs 2)
  1445. len
  1446. (expt 2 (ceiling (log (* (- num-coeffs 1) len) 2))))))
  1447. (let ((sound (channel->float-vector 0 len snd chn))
  1448. (rl1 (make-float-vector fft-len))
  1449. (rl2 (make-float-vector fft-len))
  1450. (newv (make-float-vector fft-len)))
  1451. (if (> (coeffs 0) 0.0)
  1452. (let ((dither (coeffs 0)))
  1453. (do ((i 0 (+ i 1)))
  1454. ((= i fft-len))
  1455. (float-vector-set! newv i (mus-random dither)))))
  1456. (if (> num-coeffs 1)
  1457. (begin
  1458. (float-vector-add! newv (float-vector-scale! (copy sound) (coeffs 1)))
  1459. (if (> num-coeffs 2)
  1460. (let ((peak (maxamp snd chn)))
  1461. (copy sound rl1)
  1462. (do ((i 2 (+ i 1)))
  1463. ((= i num-coeffs))
  1464. (copy sound rl2)
  1465. (convolution rl1 rl2 fft-len)
  1466. (float-vector-add! newv (float-vector-scale! (copy rl1)
  1467. (/ (* (coeffs i) peak) (float-vector-peak rl1)))))
  1468. (float-vector-scale! newv (/ peak (float-vector-peak newv)))))))
  1469. (float-vector->channel newv 0 (max len (* len (- num-coeffs 1)))
  1470. snd chn #f
  1471. (format #f "spectral-polynomial ~A" (float-vector->string coeffs))))))
  1472. ;;; ----------------
  1473. ;;; SCENTROID
  1474. ;;;
  1475. ;;; by Bret Battey
  1476. ;;; Version 1.0 July 13, 2002
  1477. ;;; translated to Snd/Scheme Bill S 19-Jan-05
  1478. ;;;
  1479. ;;; Returns the continuous spectral centroid envelope of a sound.
  1480. ;;; The spectral centroid is the "center of gravity" of the spectrum, and it
  1481. ;;; has a rough correlation to our sense of "brightness" of a sound.
  1482. ;;;
  1483. ;;; [Beauchamp, J., "Synthesis by spectral amplitude and 'brightness' matching
  1484. ;;; analyzed musical sounds". Journal of Audio Engineering Society 30(6), 396-406]
  1485. ;;;
  1486. ;;; The formula used is:
  1487. ;;; C = [SUM<n=1toj>F(n)A(n)] / [SUM<n=1toj>A(n)]
  1488. ;;; Where j is the number of bins in the analysis,
  1489. ;;; F(n) is the frequency of a given bin,
  1490. ;;; A(n) is the magnitude of the given bin.
  1491. ;;;
  1492. ;;; If a pitch envelope for the analyzed sound is available, the results
  1493. ;;; of SCENTROID can be used with the function NORMALIZE-CENTROID, below,
  1494. ;;; to provide a "normalized spectral centroid".
  1495. ;;;
  1496. ;;; DB-FLOOR -- Frames below this decibel level (0 dB = max) will be discarded
  1497. ;;; and returned with spectral centroid = 0
  1498. ;;;
  1499. ;;; RFREQ -- Rendering frequency. Number of measurements per second.
  1500. ;;;
  1501. ;;; FFTSIZE -- FFT window size. Must be a power of 2. 4096 is recommended.
  1502. (define scentroid
  1503. (let ((documentation "(scentroid file (beg 0.0) dur (db-floor -40.0) (rfreq 100.0) (fftsize 4096)) returns the spectral centroid envelope of a sound; 'rfreq' is \
  1504. the rendering frequency, the number of measurements per second; 'db-floor' is the level below which data will be ignored"))
  1505. (lambda* (file (beg 0.0) dur (db-floor -40.0) (rfreq 100.0) (fftsize 4096))
  1506. (let* ((fsr (srate file))
  1507. (start (floor (* beg fsr))))
  1508. (let ((incrsamps (floor (/ fsr rfreq)))
  1509. (end (+ start (if dur (floor (* dur fsr)) (- (framples file) beg)))))
  1510. (let ((fdr (make-float-vector fftsize))
  1511. (fdi (make-float-vector fftsize))
  1512. (scl (make-float-vector (/ fftsize 2)))
  1513. (ones (make-float-vector (/ fftsize 2) 1.0))
  1514. (results (make-float-vector (+ 1 (floor (/ (- end start) incrsamps)))))
  1515. (fft2 (floor (/ fftsize 2)))
  1516. (binwidth (* 1.0 (/ fsr fftsize)))
  1517. (rd (make-readin file)))
  1518. (do ((k 0 (+ k 1)))
  1519. ((= k fft2))
  1520. (float-vector-set! scl k (* k binwidth)))
  1521. (do ((i start (+ i incrsamps))
  1522. (loc 0 (+ 1 loc)))
  1523. ((>= i end))
  1524. (set! (mus-location rd) i)
  1525. (do ((j 0 (+ j 1)))
  1526. ((= j fftsize))
  1527. (float-vector-set! fdr j (readin rd)))
  1528. (if (>= (linear->db (sqrt (/ (dot-product fdr fdr) fftsize))) db-floor)
  1529. (begin
  1530. (fill! fdi 0.0)
  1531. (mus-fft fdr fdi fftsize)
  1532. (rectangular->magnitudes fdr fdi)
  1533. (set! (results loc) (/ (dot-product scl fdr fft2)
  1534. (dot-product ones fdr fft2))))))
  1535. results))))))
  1536. ;;; ----------------
  1537. ;;;
  1538. ;;; invert-filter inverts an FIR filter
  1539. ;;;
  1540. ;;; say we previously filtered a sound via (filter-channel (float-vector .5 .25 .125))
  1541. ;;; and we want to undo it without using (undo):
  1542. ;;; (filter-channel (invert-filter (float-vector .5 .25 .125)))
  1543. ;;;
  1544. ;;; there are a million gotchas here. The primary one is that the inverse filter
  1545. ;;; can "explode" -- the coefficients can grow without bound. For example, any
  1546. ;;; filter returned by spectrum->coeffs above will be a problem (it always returns
  1547. ;;; a "linear phase" filter). Could this be used to remove reverb?
  1548. (define invert-filter
  1549. (let ((documentation "(invert-filter coeffs) tries to return an inverse filter to undo the effect of the FIR filter coeffs."))
  1550. (lambda (fcoeffs)
  1551. (let* ((flen (length fcoeffs))
  1552. (coeffs (make-float-vector (+ 32 flen))) ; add room for coeffs to die away
  1553. (order (length coeffs)))
  1554. (do ((i 0 (+ i 1)))
  1555. ((= i flen))
  1556. (set! (coeffs i) (fcoeffs i)))
  1557. (let ((nfilt (make-float-vector order)))
  1558. (set! (nfilt 0) (/ 1.0 (coeffs 0)))
  1559. (do ((i 1 (+ i 1)))
  1560. ((= i order))
  1561. (do ((sum 0.0)
  1562. (j 0 (+ j 1))
  1563. (k i (- k 1)))
  1564. ((= j i)
  1565. (set! (nfilt i) (/ sum (- (coeffs 0)))))
  1566. (set! sum (+ sum (* (nfilt j) (coeffs k))))))
  1567. nfilt)))))
  1568. ;;; ----------------
  1569. ;;;
  1570. ;;; Volterra filter
  1571. ;;;
  1572. ;;; one of the standard non-linear filters
  1573. ;;; this version is taken from Monson Hayes "Statistical DSP and Modeling"
  1574. ;;; it is a slight specialization of the form mentioned by J O Smith and others
  1575. (define make-volterra-filter
  1576. (let ((documentation "(make-volterra-filter acoeffs bcoeffs) returns a list for use with volterra-filter, producing one of the standard non-linear filters"))
  1577. (lambda (acoeffs bcoeffs)
  1578. (list acoeffs
  1579. bcoeffs
  1580. (make-float-vector (max (length acoeffs) (length bcoeffs)))))))
  1581. (define volterra-filter
  1582. (let ((documentation "(volterra-filter flt x) takes 'flt', a list returned by make-volterra-filter, and an input 'x', and returns the (non-linear filtered) result"))
  1583. (lambda (flt x)
  1584. (let ((as (car flt))
  1585. (bs (cadr flt))
  1586. (xs (caddr flt)))
  1587. (let ((x1len (length as))
  1588. (x2len (length bs))
  1589. (sum 0.0))
  1590. (let ((xlen (length xs)))
  1591. (float-vector-move! xs (- xlen 1) (- xlen 2) #t))
  1592. (set! (xs 0) x)
  1593. (set! sum (dot-product as xs x1len))
  1594. (do ((i 0 (+ i 1)))
  1595. ((= i x2len))
  1596. (do ((j i (+ j 1)))
  1597. ((= j x2len))
  1598. (set! sum (+ sum (* (bs j) (xs i) (xs j))))))
  1599. sum)))))
  1600. ;;; (define flt (make-volterra-filter (float-vector .5 .1) (float-vector .3 .2 .1)))
  1601. ;;; (map-channel (lambda (x) (volterra-filter flt x)))
  1602. ;;; ----------------
  1603. ;;;
  1604. ;;; harmonicizer (each harmonic is split into a set of harmonics via Chebyshev polynomials)
  1605. ;;; obviously very similar to ssb-bank above, but splits harmonics individually, rather than pitch-shifting them
  1606. (define harmonicizer
  1607. (let ((documentation "(harmonicizer freq coeffs pairs (order 40) (bw 50.0) (beg 0) dur snd chn edpos) splits out each harmonic \
  1608. and replaces it with the spectrum given in coeffs"))
  1609. (lambda* (freq coeffs pairs (order 40) (bw 50.0) (beg 0) dur snd chn edpos)
  1610. (let ((bands (make-vector pairs))
  1611. (pcoeffs (partials->polynomial coeffs))
  1612. (peaks (make-vector pairs))
  1613. (peaks2 (make-vector pairs))
  1614. (flt (make-filter 2 (float-vector 1 -1) (float-vector 0 -0.9)))
  1615. (old-mx (maxamp))
  1616. (startup 40)
  1617. (len (- (or dur (framples snd chn edpos)) beg)))
  1618. (let ((summer (make-float-vector len))
  1619. (indata (channel->float-vector beg len snd chn edpos)))
  1620. (do ((i 0 (+ i 1)))
  1621. ((= i pairs))
  1622. (let ((aff (* (+ i 1) freq))
  1623. (bwf (* bw (+ 1.0 (/ (+ i 1) (* 2 pairs))))))
  1624. (set! (peaks i) (make-moving-max 128))
  1625. (set! (peaks2 i) (make-moving-norm 128))
  1626. (set! (bands i) (make-bandpass (hz->2pi (- aff bwf))
  1627. (hz->2pi (+ aff bwf))
  1628. order))))
  1629. ;; ignore startup
  1630. (do ((k 0 (+ k 1)))
  1631. ((= k startup))
  1632. (do ((sum 0.0)
  1633. (i 0 (+ i 1)))
  1634. ((= i pairs)
  1635. (filter flt sum))
  1636. (let ((sig (bandpass (vector-ref bands i) (float-vector-ref indata k))))
  1637. (set! sum (+ sum (* (moving-max (vector-ref peaks i) sig)
  1638. (polynomial pcoeffs (* sig (moving-norm (vector-ref peaks2 i) sig)))))))))
  1639. (set! *output* summer)
  1640. (do ((pair 0 (+ pair 1)))
  1641. ((= pair pairs))
  1642. (do ((bp (vector-ref bands pair))
  1643. (pk (vector-ref peaks pair))
  1644. (pk2 (vector-ref peaks2 pair))
  1645. (k startup (+ k 1)))
  1646. ((= k len))
  1647. (let ((x (bandpass bp (float-vector-ref indata k))))
  1648. (outa k (* (moving-max pk x) (polynomial pcoeffs (* x (moving-norm pk2 x))))))))
  1649. ;; we're normalizing the polynomial input so its waveshaping index is more-or-less 1.0
  1650. ;; this might work better with len=256, max .1 -- we're assuming a well-behaved signal
  1651. (set! *output* #f)
  1652. (do ((k startup (+ k 1)))
  1653. ((= k len))
  1654. (float-vector-set! summer k (filter flt (float-vector-ref summer k))))
  1655. (let ((nmx (float-vector-peak summer)))
  1656. (if (> nmx 0.0)
  1657. (float-vector-scale! summer (/ old-mx nmx))))
  1658. (float-vector->channel summer beg len snd chn))))))
  1659. ;;; (harmonicizer 550.0 (list 1 .5 2 .3 3 .2) 10)
  1660. ;;; ----------------
  1661. ;;;
  1662. ;;; linear sampling rate conversion
  1663. (define linear-src-channel
  1664. (let ((documentation "(linear-src-channel sr snd chn) performs sampling rate conversion using linear interpolation."))
  1665. (lambda* (sr snd chn)
  1666. (let ((tempfile
  1667. (with-sound (:output (snd-tempnam) :srate (srate snd) :to-snd #f)
  1668. (let ((rd (make-sampler 0 snd chn)))
  1669. (do ((intrp 0.0)
  1670. (last (rd))
  1671. (next (rd))
  1672. (samp 0 (+ samp 1)))
  1673. ((sampler-at-end? rd))
  1674. (outa samp
  1675. (let ((pos intrp))
  1676. (if (>= pos 1.0)
  1677. (do ((num (floor pos))
  1678. (i 0 (+ i 1)))
  1679. ((= i num)
  1680. (set! pos (- pos num)))
  1681. (set! last next)
  1682. (set! next (read-sample rd))))
  1683. (set! intrp (+ pos sr))
  1684. (+ last (* pos (- next last))))))))))
  1685. (set-samples 0 (- (framples tempfile) 1) tempfile snd chn #t "linear-src" 0 #f #t)
  1686. ;; first #t=truncate to new length, #f=at current edpos, #t=auto delete temp file
  1687. ))))
  1688. ;;; -------- spectrum displayed in various frequency scales
  1689. (define display-bark-fft
  1690. ;; click in lisp-graph to change the tick placement choice
  1691. (let ((snd-color-1 (lambda args
  1692. (and (defined? 'snd-color)
  1693. (apply snd-color args)))))
  1694. (let ((bark-fft-size 0)
  1695. (bark-tick-function 0)
  1696. (color1 (snd-color-1 8)) ; selected-data-color
  1697. (color2 (snd-color-1 2)) ; red
  1698. (color3 (snd-color-1 4))) ; blue
  1699. (define (bark f)
  1700. (let ((f2 (/ f 7500)))
  1701. (+ (* 13.5 (atan (* .00076 f))) (* 3.5 (atan (* f2 f2))))))
  1702. (define (mel f)
  1703. (* 1127 (log (+ 1.0 (/ f 700.0)))))
  1704. (define (erb f)
  1705. (+ 43.0 (* 11.17 (log (/ (+ f 312) (+ f 14675))))))
  1706. (define (display-bark-fft-1 hook)
  1707. (let* ((snd (hook 'snd))
  1708. (chn (hook 'chn))
  1709. (ls (left-sample snd chn))
  1710. (fftlen (floor (expt 2 (ceiling (log (- (+ (right-sample snd chn) 1) ls) 2))))))
  1711. (when (> fftlen 0)
  1712. (let ((data (channel->float-vector ls fftlen snd chn))
  1713. (normalized (not (= (transform-normalization snd chn) dont-normalize)))
  1714. (linear #t)) ; can't currently show lisp graph in dB
  1715. ;; snd-axis make_axes: WITH_LOG_Y_AXIS, but LINEAR currently in snd-chn.c 3250
  1716. (when (float-vector? data)
  1717. (let ((fftdata (snd-spectrum data ; returns fftlen / 2 data points
  1718. (fft-window snd chn) fftlen linear
  1719. (fft-window-beta snd chn) #f normalized)))
  1720. (when (float-vector? fftdata)
  1721. (let ((sr (srate snd))
  1722. (data-len (length fftdata))
  1723. (bark-low (floor (bark 20.0)))
  1724. (mel-low (floor (mel 20.0)))
  1725. (erb-low (floor (erb 20.0))))
  1726. (let ((mx (float-vector-peak fftdata))
  1727. ;; bark settings
  1728. (bark-frqscl (/ data-len (- (ceiling (bark (* 0.5 sr))) bark-low)))
  1729. (bark-data (make-float-vector data-len))
  1730. ;; mel settings
  1731. (mel-frqscl (/ data-len (- (ceiling (mel (* 0.5 sr))) mel-low)))
  1732. (mel-data (make-float-vector data-len))
  1733. ;; erb settings
  1734. (erb-frqscl (/ data-len (- (ceiling (erb (* 0.5 sr))) erb-low)))
  1735. (erb-data (make-float-vector data-len)))
  1736. (set! bark-fft-size fftlen)
  1737. (do ((i 0 (+ i 1)))
  1738. ((= i data-len))
  1739. (let ((val (fftdata i))
  1740. (frq (* sr (/ i fftlen))))
  1741. (let ((bark-bin (round (* bark-frqscl (- (bark frq) bark-low))))
  1742. (mel-bin (round (* mel-frqscl (- (mel frq) mel-low))))
  1743. (erb-bin (round (* erb-frqscl (- (erb frq) erb-low)))))
  1744. (if (and (>= bark-bin 0)
  1745. (< bark-bin data-len))
  1746. (set! (bark-data bark-bin) (+ val (bark-data bark-bin))))
  1747. (if (and (>= mel-bin 0)
  1748. (< mel-bin data-len))
  1749. (set! (mel-data mel-bin) (+ val (mel-data mel-bin))))
  1750. (if (and (>= erb-bin 0)
  1751. (< erb-bin data-len))
  1752. (set! (erb-data erb-bin) (+ val (erb-data erb-bin)))))))
  1753. (if normalized
  1754. (let ((bmx (float-vector-peak bark-data))
  1755. (mmx (float-vector-peak mel-data))
  1756. (emx (float-vector-peak erb-data)))
  1757. (if (> (abs (- mx bmx)) .01)
  1758. (float-vector-scale! bark-data (/ mx bmx)))
  1759. (if (> (abs (- mx mmx)) .01)
  1760. (float-vector-scale! mel-data (/ mx mmx)))
  1761. (if (> (abs (- mx emx)) .01)
  1762. (float-vector-scale! erb-data (/ mx emx)))))
  1763. (graph (list bark-data mel-data erb-data)
  1764. "ignored"
  1765. 20.0 (* 0.5 sr)
  1766. 0.0 (if normalized 1.0 (* data-len (y-zoom-slider snd chn)))
  1767. snd chn
  1768. #f show-bare-x-axis))))))))
  1769. (list color1 color2 color3))) ; tell lisp graph display what colors to use
  1770. (define (make-bark-labels hook)
  1771. ;; at this point the x axis has no markings, but there is room for labels and ticks
  1772. (let* ((snd (hook 'snd))
  1773. (chn (hook 'chn))
  1774. (old-foreground-color (foreground-color snd chn copy-context))
  1775. (axinfo (axis-info snd chn lisp-graph))
  1776. (axis-x0 (axinfo 10))
  1777. (axis-x1 (axinfo 12))
  1778. (axis-y1 (axinfo 11))
  1779. (bark-label-font (snd-font 3))
  1780. (cr (make-cairo (car (channel-widgets snd chn))))
  1781. (scale-position (let ((sr2 (* 0.5 (srate snd))))
  1782. (lambda (scale f)
  1783. (let ((b20 (scale 20.0)))
  1784. (round (+ axis-x0
  1785. (/ (* (- axis-x1 axis-x0) (- (scale f) b20))
  1786. (- (scale sr2) b20))))))))
  1787. (bark-position (lambda (f) (scale-position bark f)))
  1788. (mel-position (lambda (f) (scale-position mel f)))
  1789. (erb-position (lambda (f) (scale-position erb f)))
  1790. (draw-bark-ticks
  1791. (let ((minor-tick-len 6)
  1792. (major-tick-len 12))
  1793. (let (;; (tick-y0 axis-y1)
  1794. (minor-y0 (+ axis-y1 minor-tick-len))
  1795. (major-y0 (+ axis-y1 major-tick-len))
  1796. (axis-y0 (axinfo 13))
  1797. (bark-numbers-font (snd-font 2)))
  1798. (lambda (bark-function)
  1799. (if bark-numbers-font (set! (current-font snd chn copy-context) bark-numbers-font))
  1800. (draw-line axis-x0 axis-y1 axis-x0 major-y0 snd chn copy-context cr)
  1801. (let ((i1000 (scale-position bark-function 1000.0))
  1802. (i10000 (scale-position bark-function 10000.0)))
  1803. (draw-line i1000 axis-y1 i1000 major-y0 snd chn copy-context cr)
  1804. (draw-line i10000 axis-y1 i10000 major-y0 snd chn copy-context cr)
  1805. (draw-string "20" axis-x0 major-y0 snd chn copy-context cr)
  1806. (draw-string "1000" (- i1000 12) major-y0 snd chn copy-context cr)
  1807. (draw-string "10000" (- i10000 24) major-y0 snd chn copy-context cr)
  1808. (draw-string (format #f "fft size: ~D" bark-fft-size) (+ axis-x0 10) axis-y0 snd chn copy-context cr)
  1809. (do ((i 100 (+ i 100)))
  1810. ((= i 1000))
  1811. (let ((i100 (scale-position bark-function i)))
  1812. (draw-line i100 axis-y1 i100 minor-y0 snd chn copy-context cr)))
  1813. (do ((i 2000 (+ i 1000)))
  1814. ((= i 10000))
  1815. (let ((i1000 (scale-position bark-function i)))
  1816. (draw-line i1000 axis-y1 i1000 minor-y0 snd chn copy-context cr)))))))))
  1817. (let ((label-pos (round (+ axis-x0 (* .45 (- axis-x1 axis-x0)))))
  1818. (label-height 15)
  1819. (char-width 8))
  1820. ;; bark label/ticks
  1821. (set! (foreground-color snd chn copy-context) color1)
  1822. (if (= bark-tick-function 0) (draw-bark-ticks bark-position))
  1823. (if bark-label-font (set! (current-font snd chn copy-context) bark-label-font))
  1824. (draw-string "bark," label-pos (+ axis-y1 label-height) snd chn copy-context cr)
  1825. ;; mel label/ticks
  1826. (set! (foreground-color snd chn copy-context) color2)
  1827. (if (= bark-tick-function 1) (draw-bark-ticks mel-position))
  1828. (if bark-label-font (set! (current-font snd chn copy-context) bark-label-font))
  1829. (draw-string "mel," (+ (* char-width 6) label-pos) (+ axis-y1 label-height) snd chn copy-context cr)
  1830. ;; erb label/ticks
  1831. (set! (foreground-color snd chn copy-context) color3)
  1832. (if (= bark-tick-function 2) (draw-bark-ticks erb-position))
  1833. (if bark-label-font (set! (current-font snd chn copy-context) bark-label-font))
  1834. (draw-string "erb" (+ (* char-width 11) label-pos) (+ axis-y1 label-height) snd chn copy-context cr)
  1835. (free-cairo cr))
  1836. (set! (foreground-color snd chn copy-context) old-foreground-color)))
  1837. ;; mouse click = move to next scale's ticks
  1838. (define (choose-bark-ticks hook)
  1839. (if (= (hook 'axis) lisp-graph)
  1840. (begin
  1841. (set! bark-tick-function (+ bark-tick-function 1))
  1842. (if (> bark-tick-function 2)
  1843. (set! bark-tick-function 0))
  1844. (update-lisp-graph (hook 'snd) (hook 'chn)))))
  1845. ;; user's view of display-bark-fft function
  1846. (lambda* (off col1 col2 col3)
  1847. (if col1 (set! color1 col1))
  1848. (if col2 (set! color2 col2))
  1849. (if col3 (set! color3 col3))
  1850. (if (not off)
  1851. (begin
  1852. (hook-push lisp-graph-hook display-bark-fft-1)
  1853. (hook-push after-lisp-graph-hook make-bark-labels)
  1854. (hook-push mouse-click-hook choose-bark-ticks)
  1855. (for-each (lambda (snd)
  1856. (do ((c 0 (+ 1 c)))
  1857. ((= c (channels snd)))
  1858. (update-lisp-graph snd c)))
  1859. (sounds)))
  1860. (begin
  1861. (hook-remove lisp-graph-hook display-bark-fft-1)
  1862. (hook-remove after-lisp-graph-hook make-bark-labels)
  1863. (hook-remove mouse-click-hook choose-bark-ticks)
  1864. (for-each (lambda (snd)
  1865. (do ((c 0 (+ 1 c)))
  1866. ((= c (channels snd)))
  1867. (set! (lisp-graph? snd c) #f)))
  1868. (sounds))))))))
  1869. (define (undisplay-bark-fft) (display-bark-fft #t))
  1870. ;;; -------- lpc-coeffs, lpc-predict
  1871. (define lpc-coeffs
  1872. (let ((documentation "(lpc-coeffs data n m) returns 'm' LPC coeffients (in a vector) given 'n' data points in the float-vector 'data'"))
  1873. (lambda (data n m)
  1874. ;; translated and changed to use 0-based arrays from memcof of NRinC
  1875. (let ((d (make-float-vector m))
  1876. (wk1 (make-float-vector n))
  1877. (wk2 (make-float-vector n))
  1878. (wkm (make-float-vector n)))
  1879. (copy data wk1)
  1880. (do ((j 1 (+ j 1))
  1881. (k 0 (+ k 1)))
  1882. ((= j n))
  1883. (float-vector-set! wk2 k (float-vector-ref data j)))
  1884. (do ((k 0 (+ k 1)))
  1885. ((= k m) d)
  1886. (let ((end (- n k 1)))
  1887. (let ((num (dot-product wk1 wk2 end))
  1888. (denom (+ (dot-product wk1 wk1 end) (dot-product wk2 wk2 end))))
  1889. (if (not (= denom 0.0))
  1890. (set! (d k) (/ (* 2.0 num) denom))))
  1891. (let ((d-k (d k)))
  1892. (do ((i 0 (+ i 1))
  1893. (k1 (- k 1) (- k1 1)))
  1894. ((= i k)) ; first time is skipped presumably
  1895. (float-vector-set! d i (- (float-vector-ref wkm i) (* d-k (float-vector-ref wkm k1))))))
  1896. (if (< k (- m 1))
  1897. (let ((end (- n k 2)))
  1898. (copy d wkm 0 (+ k 1))
  1899. (let ((wkm-k (float-vector-ref wkm k))
  1900. (old-wk1 (copy wk1)))
  1901. (do ((j 0 (+ j 1)))
  1902. ((= j end))
  1903. (float-vector-set! wk1 j (- (float-vector-ref wk1 j) (* wkm-k (float-vector-ref wk2 j)))))
  1904. (do ((j 0 (+ j 1))
  1905. (j1 1 (+ j1 1)))
  1906. ((= j end))
  1907. (float-vector-set! wk2 j (- (float-vector-ref wk2 j1) (* wkm-k (float-vector-ref old-wk1 j1))))))))))))))
  1908. (define lpc-predict
  1909. ;; translated and changed to use 0-based arrays from predic of NRinC
  1910. ;; incoming coeffs are assumed to be in a vector (from lpc-coeffs)
  1911. (let ((documentation "(lpc-predict data n coeffs m nf clipped) takes the output of lpc-coeffs ('coeffs', a float-vector) and the length thereof ('m'), \
  1912. 'n' data points of 'data' (a float-vector), and produces 'nf' new data points (in a float-vector) as its prediction. If 'clipped' is #t, the new data \
  1913. is assumed to be outside -1.0 to 1.0."))
  1914. (lambda* (data n coeffs m nf clipped)
  1915. (let ((future (make-float-vector nf))
  1916. (reg (make-float-vector m)))
  1917. (do ((i 0 (+ i 1))
  1918. (j (- n 1) (- j 1)))
  1919. ((= i m))
  1920. (set! (reg i) (data j)))
  1921. (do ((j 0 (+ j 1)))
  1922. ((= j nf) future)
  1923. (let ((sum (dot-product coeffs reg m)))
  1924. (do ((k (- m 1) (- k 1)))
  1925. ((= k 0))
  1926. (set! (reg k) (reg (- k 1))))
  1927. ;; added this block
  1928. (if clipped
  1929. (set! sum (if (> sum 0.0) (max sum 1.0) (min sum -1.0))))
  1930. (set! (reg 0) sum)
  1931. (set! (future j) sum)))))))
  1932. ;;; -------- unclip-channel
  1933. (define unclip-channel
  1934. (let ((documentation "(unclip-channel snd chn) looks for clipped portions and tries to reconstruct the original using LPC"))
  1935. (lambda* (snd chn)
  1936. (let ((clips 0) ; number of clipped portions * 2
  1937. (unclipped-max 0.0)
  1938. (len (framples snd chn))
  1939. (data (channel->float-vector 0 #f snd chn))
  1940. (clip-size 1000)
  1941. (clip-data (make-vector 1000 0)))
  1942. ;; count clipped portions
  1943. (let ((in-clip #f)
  1944. (clip-beg 0))
  1945. (float-vector-abs! data)
  1946. (do ((i 0 (+ i 1)))
  1947. ((= i len))
  1948. (if (> (float-vector-ref data i) .9999) ; this sample is clipped
  1949. (if (not in-clip)
  1950. (begin
  1951. (set! in-clip #t)
  1952. (set! clip-beg i)))
  1953. (begin ; not clipped
  1954. (set! unclipped-max (max unclipped-max (float-vector-ref data i))) ; this is not the same as (float-vector-peak ...)
  1955. (if in-clip
  1956. (begin
  1957. (set! in-clip #f)
  1958. (set! (clip-data clips) clip-beg)
  1959. (set! (clip-data (+ 1 clips)) (- i 1))
  1960. (set! clips (+ clips 2))
  1961. (if (> clips clip-size)
  1962. (let ((new-clip-data (make-vector (* 2 clip-size) 0)))
  1963. (copy clip-data new-clip-data)
  1964. (set! clip-data new-clip-data)
  1965. (set! clip-size (* 2 clip-size))))))))))
  1966. (if (<= clips 0)
  1967. 'no-clips
  1968. ;; try to restore clipped portions
  1969. (let ((max-len 0))
  1970. (as-one-edit
  1971. (lambda ()
  1972. (do ((clip 0 (+ clip 2))) ; so go through all...
  1973. ((>= clip clips))
  1974. (let* ((clip-beg (clip-data clip)) ; clip-beg to clip-end inclusive are clipped
  1975. (clip-end (clip-data (+ 1 clip)))
  1976. (clip-len (- (+ clip-end 1) clip-beg))
  1977. (data-len (max 32 (* clip-len 4))))
  1978. (set! max-len (max max-len clip-len))
  1979. (let ((forward-data-len data-len)
  1980. (backward-data-len data-len)
  1981. (previous-end (if (= clip 0) 0 (clip-data (- clip 1))))
  1982. (next-beg (if (< clip (- clips 3)) (clip-data (+ clip 2)) (framples snd chn))))
  1983. (if (< (- clip-beg data-len) previous-end) ; current beg - data collides with previous
  1984. (set! forward-data-len (max 4 (- clip-beg previous-end))))
  1985. (if (> (+ clip-end data-len) next-beg) ; current end + data collides with next
  1986. (set! backward-data-len (max 4 (- next-beg clip-end))))
  1987. (let ((forward-predict-len (min (max clip-len (floor (/ forward-data-len 2))) forward-data-len))
  1988. (backward-predict-len (min (max clip-len (floor (/ backward-data-len 2))) backward-data-len)))
  1989. ;; use LPC to reconstruct going both forwards and backwards
  1990. (let ((future (let ((data (channel->float-vector (- clip-beg forward-data-len) forward-data-len snd chn)))
  1991. (lpc-predict
  1992. data forward-data-len
  1993. (lpc-coeffs data forward-data-len forward-predict-len)
  1994. forward-predict-len
  1995. clip-len #f)))
  1996. (past (let ((rdata (reverse! (channel->float-vector (+ 1 clip-end) backward-data-len snd chn))))
  1997. (lpc-predict
  1998. rdata backward-data-len
  1999. (lpc-coeffs rdata backward-data-len backward-predict-len)
  2000. backward-predict-len
  2001. clip-len #f)))
  2002. (new-data (make-float-vector clip-len)))
  2003. (if (> clip-len 1)
  2004. (do ((i 0 (+ i 1))
  2005. (j (- clip-len 1) (- j 1)))
  2006. ((= i clip-len))
  2007. (let ((sn (* 0.5 (+ 1.0 (cos (* pi (/ i (- clip-len 1))))))))
  2008. (set! (new-data i) (+ (* sn
  2009. (future i))
  2010. (* (- 1.0 sn)
  2011. (past j))))))
  2012. ;; todo perhaps move this mix dependent on data-lens?
  2013. ;; todo perhaps special case for 2 samps (what if both 1.0 for example?)
  2014. ;; todo perhaps if multichannel and channels are correlated and one is not clipped -- use
  2015. ;; its data to help reconstruct clipped case?
  2016. (set! (new-data 0) ((if (> (future 0) 0.0) max min) (future 0) (past 0))))
  2017. ;; write reconstruction
  2018. (float-vector->channel new-data clip-beg clip-len snd chn))))))))
  2019. (if (> unclipped-max .95) (set! unclipped-max .999))
  2020. (scale-channel (/ unclipped-max (maxamp snd chn)) 0 (framples snd chn) snd chn)
  2021. (list 'max unclipped-max 'clips (/ clips 2) 'max-len max-len)))))))
  2022. (define unclip-sound
  2023. (let ((documentation "(unclip-sound snd) applies unclip-channel to each channel of 'snd'."))
  2024. (lambda* (snd)
  2025. (let ((index (or snd (selected-sound) (car (sounds)))))
  2026. (if (not (sound? index))
  2027. (error 'no-such-sound (list "unclip-sound" snd))
  2028. (do ((chns (channels index))
  2029. (chn 0 (+ 1 chn)))
  2030. ((= chn chns))
  2031. (unclip-channel index chn)))))))
  2032. (define* (kalman-filter-channel (Q 1.0e-5))
  2033. ;; translated from http://www.scipy.org/Cookbook/KalmanFiltering by Andrew Straw (but "R" here is a signal)
  2034. (let ((size (framples))
  2035. (mx (maxamp))
  2036. (data (channel->float-vector 0))
  2037. (xhat 0.0)
  2038. (P 1.0) ; any non-zero value ok here
  2039. (R 0.01) ; first guess
  2040. (Pminus 0.0)
  2041. (frm (make-formant :radius (- 1.0 (/ 2000.0 (srate))) :frequency 1000))
  2042. (del (make-moving-average 256))
  2043. (K 0.0))
  2044. (do ((k 1 (+ k 1)))
  2045. ((= k size))
  2046. (let ((datum (data k))
  2047. (xhatminus xhat))
  2048. (let ((avg (moving-average del (abs (formant frm datum)))))
  2049. (set! R (/ .000001 (+ avg .001))))
  2050. ;; K now goes between say .5 if avg large to almost 0 if avg 0 (R is inverse essentially)
  2051. ;; so filter lp effect increases as apparent true signal decreases
  2052. ;; "truth" here is based on vocal resonances
  2053. (set! (data k) xhatminus) ; filter output
  2054. (set! Pminus (+ P Q))
  2055. (set! K (/ Pminus (+ Pminus R)))
  2056. (set! xhat (+ xhatminus
  2057. (* K (- datum xhatminus))))
  2058. (set! P (* (- 1.0 K) Pminus))))
  2059. (float-vector-scale! data (/ mx (float-vector-peak data)))
  2060. (float-vector->channel data)))
  2061. ;;; -------- Savitzky-Golay filter coefficients (FIR filter -- returns float-vector of coeffs centered at float-vector midpoint)
  2062. ;;;
  2063. ;;; based on Numerical Recipes in C p 652
  2064. (define invert-matrix
  2065. (let ((documentation "(invert-matrix matrix b (zero 1.0e-7)) inverts 'matrix'"))
  2066. (lambda* (matrix b (zero 1.0e-7))
  2067. ;; translated from Numerical Recipes (gaussj)
  2068. ;(format () "~%~%invert-matrix n: ~D, ~S, b: ~A, ~S~%" (length matrix) matrix (and b (length b)) b)
  2069. (call-with-exit
  2070. (lambda (return)
  2071. (let ((n (car (vector-dimensions matrix))))
  2072. (let ((cols (make-vector n 0))
  2073. (rows (make-vector n 0))
  2074. (pivots (make-vector n 0)))
  2075. (do ((i 0 (+ i 1))
  2076. (col 0 0)
  2077. (row 0 0))
  2078. ((= i n))
  2079. (do ((biggest 0.0)
  2080. (j 0 (+ j 1)))
  2081. ((= j n)
  2082. (if (< biggest zero)
  2083. (return #f))) ; this can be fooled (floats...): (invert-matrix (make-share-vector (float-vector 1 2 3 3 2 1 4 5 6) (list 3 3)))
  2084. (if (not (= (pivots j) 1))
  2085. (do ((k 0 (+ k 1)))
  2086. ((= k n))
  2087. (if (= (pivots k) 0)
  2088. (let ((val (abs (matrix j k))))
  2089. (if (> val biggest)
  2090. (begin
  2091. (set! col k)
  2092. (set! row j)
  2093. (set! biggest val))))
  2094. (if (> (pivots k) 1)
  2095. (return #f))))))
  2096. (set! (pivots col) (+ (pivots col) 1))
  2097. (if (not (= row col))
  2098. (let ((temp (if (sequence? b) (b row) 0.0)))
  2099. (if (sequence? b)
  2100. (begin
  2101. (set! (b row) (b col))
  2102. (set! (b col) temp)))
  2103. (do ((k 0 (+ k 1)))
  2104. ((= k n))
  2105. (set! temp (matrix row k))
  2106. (set! (matrix row k) (matrix col k))
  2107. (set! (matrix col k) temp))))
  2108. (set! (cols i) col)
  2109. (set! (rows i) row)
  2110. ;; round-off troubles here
  2111. (if (< (abs (matrix col col)) zero)
  2112. (return #f))
  2113. (let ((inverse-pivot (/ 1.0 (matrix col col))))
  2114. (set! (matrix col col) 1.0)
  2115. (do ((k 0 (+ k 1)))
  2116. ((= k n))
  2117. (set! (matrix col k) (* inverse-pivot (matrix col k))))
  2118. (if b (set! (b col) (* inverse-pivot (b col)))))
  2119. (do ((k 0 (+ k 1)))
  2120. ((= k n))
  2121. (if (not (= k col))
  2122. (let ((scl (matrix k col)))
  2123. (set! (matrix k col) 0.0)
  2124. (do ((m 0 (+ 1 m)))
  2125. ((= m n))
  2126. (set! (matrix k m) (- (matrix k m) (* scl (matrix col m)))))
  2127. (if b (set! (b k) (- (b k) (* scl (b col)))))))))
  2128. (do ((i (- n 1) (- i 1)))
  2129. ((< i 0))
  2130. (if (not (= (rows i) (cols i)))
  2131. (do ((k 0 (+ k 1)))
  2132. ((= k n))
  2133. (let ((temp (matrix k (rows i))))
  2134. (set! (matrix k (rows i)) (matrix k (cols i)))
  2135. (set! (matrix k (cols i)) temp)))))
  2136. (list matrix b))))))))
  2137. (define (matrix-solve A b)
  2138. (cond ((invert-matrix A b) => cadr) (else #f)))
  2139. (define* (make-savitzky-golay-filter size (order 2)) ;assuming symmetric filter (left = right)
  2140. (if (even? size)
  2141. (set! size (+ size 1)))
  2142. (let ((n (/ (- size 1) 2))
  2143. (a (make-float-vector (list (+ 1 order) (+ 1 order)))))
  2144. (do ((i 0 (+ i 1)))
  2145. ((> i (* order 2)))
  2146. (let ((sum (if (= i 0) 1.0 0.0)))
  2147. (if (even? i)
  2148. (do ((k 1 (+ k 1)))
  2149. ((> k n))
  2150. ;(set! sum (+ sum (expt k i) (expt (- k) i))) ; kinda nuts
  2151. (set! sum (+ sum (* 2 (expt k i))))))
  2152. (let ((m i))
  2153. (if (> i (- (* 2 order) i))
  2154. (set! m (- (* 2 order) i)))
  2155. (do ((k (- m) (+ k 2)))
  2156. ((> k m))
  2157. (set! (a (/ (+ i k) 2) (/ (- i k) 2)) sum)))))
  2158. (let ((b (matrix-solve a (let ((f (make-float-vector (+ order 1))))
  2159. (set! (f 0) 1.0) ; set others instead for derivative
  2160. f)))
  2161. (result (make-float-vector size)))
  2162. (do ((k (- n) (+ k 1))
  2163. (i 0 (+ i 1)))
  2164. ((> k n))
  2165. (let ((sum (b 0))
  2166. (fac 1.0))
  2167. (do ((m 1 (+ 1 m)))
  2168. ((> m order))
  2169. (set! fac (* fac k))
  2170. (set! sum (+ sum (* (b m) fac))))
  2171. (set! (result i) sum)))
  2172. (make-fir-filter :order size :xcoeffs result))))
  2173. (define savitzky-golay-filter fir-filter)
  2174. #|
  2175. ;; NRinC examples (2nd ed, p651)
  2176. :(make-savitzky-golay-filter 5 2)
  2177. #<fir-filter: order: 5, xs: [-0.086 0.343 0.486 0.343 -0.086]>
  2178. :(make-savitzky-golay-filter 11 2)
  2179. #<fir-filter: order: 11, xs: [-0.084 0.021 0.103 0.161 0.196 0.207 0.196 0.161...(0: -0.084, 5: 0.207)]>
  2180. :(make-savitzky-golay-filter 11 4)
  2181. #<fir-filter: order: 11, xs: [0.042 -0.105 -0.023 0.140 0.280 0.333 0.280 0.140...(1: -0.105, 5: 0.333)]>
  2182. :(make-savitzky-golay-filter 25 2)
  2183. #<fir-filter: order: 25, xs: [-0.049 -0.027 -0.006 0.012 0.028 0.043 0.055 0.066...(0: -0.049, 12: 0.090)]>
  2184. |#
  2185. ;;; -------- hard and soft clipping
  2186. ;;;
  2187. ;;; from Julius Smith's http://ccrma.stanford.edu/~jos/pasp/Cubic_Soft_Clipper.html
  2188. (define (hard-clipped x)
  2189. (max -1.0 (min 1.0 x)))
  2190. (define (soft-clipped x)
  2191. (max -0.6667 (min 0.6667 (- x (* 0.3333 x x x)))))
  2192. ;;; -------- parallel FM spectrum calculator
  2193. ;(fm-parallel-component 200 2000.0 (list 2000.0 200.0) (list 0.5 1.0) () () #t)
  2194. (define fm-parallel-component
  2195. (let ((documentation "(fm-parallel-component freq carrier modfreqs indices () () with-sines) returns the amplitude of \"freq\" in \
  2196. the multi-modulator FM case described by the list of modulator frequencies and indices"))
  2197. (lambda (freq-we-want wc wms inds ns bs using-sine)
  2198. (if (pair? wms)
  2199. (let ((index (car inds)))
  2200. (let ((sum 0.0)
  2201. (mx (ceiling (* 7 index)))
  2202. (wm (car wms)))
  2203. (do ((k (- mx) (+ k 1)))
  2204. ((>= k mx) sum)
  2205. (set! sum (+ sum (fm-parallel-component freq-we-want (+ wc (* k wm)) (cdr wms) (cdr inds)
  2206. (append ns (list k)) (append bs (list index))
  2207. using-sine))))))
  2208. (if (>= (abs (- freq-we-want (abs wc))) .1)
  2209. 0.0
  2210. (let ((bmult 1.0))
  2211. (for-each
  2212. (lambda (n index)
  2213. (set! bmult (* bmult (bes-jn n index))))
  2214. ns bs)
  2215. (if (and using-sine (< wc 0.0)) (set! bmult (- bmult)))
  2216. bmult))))))
  2217. ;;; this returns the component in FM with complex index (using-sine ignored for now)
  2218. ;;; this needs the Bessel functions (gsl or snd-test.scm)
  2219. (define (fm-complex-component freq-we-want wc wm a b interp using-sine)
  2220. (let ((sum 0.0)
  2221. (mxa (ceiling (* 7 a)))
  2222. (mxb (ceiling (* 7 b))))
  2223. (do ((k (- mxa) (+ k 1)))
  2224. ((>= k mxa))
  2225. (do ((j (- mxb) (+ j 1)))
  2226. ((>= j mxb))
  2227. (if (< (abs (- freq-we-want wc (* k wm) (* j wm))) 0.1)
  2228. (let ((curJI (* (bes-jn k a)
  2229. (bes-in (abs j) b)
  2230. (expt 0.0+1.0i j))))
  2231. (set! sum (+ sum curJI))
  2232. (if (> (magnitude curJI) 0.001)
  2233. (format () ";fm-complex-component add ~,3f from J~D(~A) = ~,3f and I~D(~A) = ~,3f~%"
  2234. curJI
  2235. k a (bes-jn k a)
  2236. j b (bes-in (abs j) b)))))))
  2237. (list sum
  2238. (+ (* (- 1.0 interp) (real-part sum))
  2239. (* interp (imag-part sum))))))
  2240. ;(fm-complex-component 1200 1000 100 1.0 3.0 0.0 #f)
  2241. ;(fm-complex-component 1200 1000 100 1.0 4.0 0.0 #f) hits the commentary
  2242. (define (fm-cascade-component freq-we-want wc wm1 a wm2 b)
  2243. (let ((sum 0.0)
  2244. (mxa (ceiling (* 7 a)))
  2245. (mxb (ceiling (* 7 b))))
  2246. (do ((k (- mxa) (+ k 1)))
  2247. ((>= k mxa))
  2248. (do ((j (- mxb) (+ j 1)))
  2249. ((>= j mxb))
  2250. (if (< (abs (- freq-we-want wc (* k wm1) (* j wm2))) 0.1)
  2251. (let ((curJJ (* (bes-jn k a)
  2252. (bes-jn j (* k b)))))
  2253. (set! sum (+ sum curJJ))
  2254. (if (> (magnitude curJJ) 0.001)
  2255. (format () ";fm-cascade-component add ~,3f from J~D(~A) = ~,3f and J~D(~A) = ~,3f~%"
  2256. curJJ
  2257. k a (bes-jn k a)
  2258. j b (bes-jn j (* k b))))))))
  2259. sum))
  2260. ;(fm-cascade-component 2000 2000 500 1.5 50 1.0)
  2261. ;;; waveshaping harmonic amplitude at a given index
  2262. (define (cheby-hka k a coeffs) ; (coeff 0 = DC)
  2263. (do ((sum 0.0)
  2264. (n (length coeffs))
  2265. (j 0 (+ j 1)))
  2266. ((= j n)
  2267. sum)
  2268. (do ((dsum 0.0)
  2269. (p (+ k (* 2 j)))
  2270. (i 0 (+ i 1)))
  2271. ((>= (+ p (* 2 i)) n)
  2272. (set! sum (+ sum (* dsum
  2273. (expt a p)
  2274. (binomial p j)))))
  2275. (set! dsum (+ dsum (* (expt -1 i)
  2276. (coeffs (+ p (* 2 i)))
  2277. (+ (binomial (+ p i) i)
  2278. (binomial (+ p i -1) (- i 1)))))))))
  2279. #|
  2280. (with-sound ()
  2281. (let ((gen (make-polyshape 1000.0 :partials (list 1 .5 2 .25 3 .125 4 .125))))
  2282. (do ((i 0 (+ i 1)))
  2283. ((= i 88200))
  2284. (outa i (* .5 (polyshape gen 0.25))))))
  2285. (cheby-hka 1 0.25 (float-vector 0 .5 .25 .125 .125))
  2286. |#
  2287. ;;; find not-so-spikey amps for waveshaping
  2288. (define* (flatten-partials any-partials (tries 32))
  2289. (define (cos-fft-to-max n cur-amps)
  2290. (let ((size 1024))
  2291. (do ((fft-rl (make-float-vector size))
  2292. (fft-im (make-float-vector size))
  2293. (i 0 (+ i 1))
  2294. (bin 2 (+ bin 2)))
  2295. ((= i n)
  2296. (float-vector-peak (mus-fft fft-rl fft-im size -1)))
  2297. (set! (fft-rl bin) (cur-amps i)))))
  2298. (let* ((partials (if (list? any-partials)
  2299. (apply float-vector any-partials)
  2300. any-partials))
  2301. (len (length partials))
  2302. (topk 0)
  2303. (DC 0.0)
  2304. (original-sum (do ((sum 0.0)
  2305. (i 0 (+ i 2)))
  2306. ((>= i len) sum)
  2307. (let ((hnum (partials i))
  2308. (amp (partials (+ i 1))))
  2309. (if (= hnum 0)
  2310. (set! DC amp)
  2311. (begin
  2312. (set! topk (max topk hnum))
  2313. (set! sum (+ sum amp)))))))
  2314. (min-sum original-sum)
  2315. (original-partials (do ((v (make-float-vector topk))
  2316. (i 0 (+ i 2)))
  2317. ((>= i len) v)
  2318. (let ((hnum (partials i)))
  2319. (if (not (= hnum 0))
  2320. (set! (v (- hnum 1)) (partials (+ i 1)))))))
  2321. (min-partials (copy original-partials)))
  2322. (if (<= topk (log tries 2))
  2323. (set! tries (floor (expt 2 (- topk 1)))))
  2324. (do ((try 0 (+ 1 try)))
  2325. ((= try tries))
  2326. (let ((new-partials (copy original-partials)))
  2327. (do ((k 0 (+ k 1)))
  2328. ((= k topk))
  2329. (if (> (random 1.0) 0.5)
  2330. (set! (new-partials k) (- (new-partials k)))))
  2331. (let ((new-sum (cos-fft-to-max topk new-partials)))
  2332. (if (< new-sum min-sum)
  2333. (begin
  2334. (set! min-partials (copy new-partials))
  2335. (set! min-sum new-sum))))))
  2336. (let ((new-amps (float-vector-scale! min-partials (/ original-sum min-sum)))
  2337. (new-partials (copy partials)))
  2338. (do ((i 0 (+ i 2)))
  2339. ((>= i len))
  2340. (let ((hnum (new-partials i)))
  2341. (set! (new-partials (+ i 1)) (if (= hnum 0) DC (new-amps (- hnum 1))))))
  2342. new-partials)))
  2343. #|
  2344. (with-sound (:clipped #f :statistics #t :channels 2)
  2345. (let* ((amps (normalize-partials (list 1 .25 2 .5 3 .25)))
  2346. (gen1 (make-polywave 400.0 amps))
  2347. (gen2 (make-polywave 400.0 (flatten-partials amps))))
  2348. (do ((i 0 (+ i 1)))
  2349. ((= i 44100))
  2350. (outa i (polywave gen1))
  2351. (outb i (polywave gen2)))))
  2352. |#
  2353. #|
  2354. ;;; these are standard FFTs for s7
  2355. (define* (fft! rl im n (dir 1))
  2356. (if (not im)
  2357. (let ((clear (copy rl)))
  2358. (fill! clear 0.0)
  2359. (set! im clear)))
  2360. (if (not n)
  2361. (set! n (length rl)))
  2362. (do ((i 0 (+ i 1))
  2363. (j 0))
  2364. ((= i n))
  2365. (if (> j i)
  2366. (let ((tempr (rl j))
  2367. (tempi (im j)))
  2368. (set! (rl j) (rl i))
  2369. (set! (im j) (im i))
  2370. (set! (rl i) tempr)
  2371. (set! (im i) tempi)))
  2372. (let ((m (/ n 2)))
  2373. (do ()
  2374. ((or (< m 2) (< j m)))
  2375. (set! j (- j m))
  2376. (set! m (/ m 2)))
  2377. (set! j (+ j m))))
  2378. (let ((ipow (floor (log n 2)))
  2379. (prev 1))
  2380. (do ((lg 0 (+ lg 1))
  2381. (mmax 2 (* mmax 2))
  2382. (pow (/ n 2) (/ pow 2))
  2383. (theta (* pi dir) (* theta 0.5)))
  2384. ((= lg ipow))
  2385. (let ((wpr (cos theta))
  2386. (wpi (sin theta))
  2387. (wr 1.0)
  2388. (wi 0.0))
  2389. (do ((ii 0 (+ ii 1)))
  2390. ((= ii prev))
  2391. (do ((jj 0 (+ jj 1))
  2392. (i ii (+ i mmax))
  2393. (j (+ ii prev) (+ j mmax)))
  2394. ((>= jj pow))
  2395. (let ((tempr (- (* wr (rl j)) (* wi (im j))))
  2396. (tempi (+ (* wr (im j)) (* wi (rl j)))))
  2397. (set! (rl j) (- (rl i) tempr))
  2398. (set! (rl i) (+ (rl i) tempr))
  2399. (set! (im j) (- (im i) tempi))
  2400. (set! (im i) (+ (im i) tempi))))
  2401. (let ((wtemp wr))
  2402. (set! wr (- (* wr wpr) (* wi wpi)))
  2403. (set! wi (+ (* wi wpr) (* wtemp wpi)))))
  2404. (set! prev mmax))))
  2405. rl)
  2406. (define* (cfft! data n (dir 1))
  2407. (if (not n) (set! n (length data)))
  2408. (do ((i 0 (+ i 1))
  2409. (j 0))
  2410. ((= i n))
  2411. (if (> j i)
  2412. (let ((temp (data j)))
  2413. (set! (data j) (data i))
  2414. (set! (data i) temp)))
  2415. (let ((m (/ n 2)))
  2416. (do ()
  2417. ((or (< m 2) (< j m)))
  2418. (set! j (- j m))
  2419. (set! m (/ m 2)))
  2420. (set! j (+ j m))))
  2421. (let ((ipow (floor (log n 2)))
  2422. (prev 1))
  2423. (do ((lg 0 (+ lg 1))
  2424. (mmax 2 (* mmax 2))
  2425. (pow (/ n 2) (/ pow 2))
  2426. (theta (complex 0.0 (* pi dir)) (* theta 0.5)))
  2427. ((= lg ipow))
  2428. (let ((wpc (exp theta))
  2429. (wc 1.0))
  2430. (do ((ii 0 (+ ii 1)))
  2431. ((= ii prev))
  2432. (do ((jj 0 (+ jj 1))
  2433. (i ii (+ i mmax))
  2434. (j (+ ii prev) (+ j mmax)))
  2435. ((>= jj pow))
  2436. (let ((tc (* wc (data j))))
  2437. (set! (data j) (- (data i) tc))
  2438. (set! (data i) (+ (data i) tc))))
  2439. (set! wc (* wc wpc)))
  2440. (set! prev mmax))))
  2441. data)
  2442. ;;; > (cfft! (list 0.0 1+i 0.0 0.0))
  2443. ;;; (1+1i -1+1i -1-1i 1-1i)
  2444. ;;;
  2445. ;;; > (cfft! (vector 0.0 1+i 0.0 0.0))
  2446. ;;; #(1+1i -1+1i -1-1i 1-1i)
  2447. ;;;
  2448. ;;; ;; check against built-in FFT
  2449. ;;; > (let ((rl (float-vector 0.0 1.0 0.0 0.0))
  2450. ;;; (im (float-vector 0.0 1.0 0.0 0.0)))
  2451. ;;; (mus-fft rl im)
  2452. ;;; (map complex rl im))
  2453. ;;; (1+1i -1+1i -1-1i 1-1i)
  2454. |#