#lang racket
(require "../rsound.rkt"
"../util.rkt"
"../network.rkt"
"plot-signal.rkt"
rackunit
rackunit/text-ui
(for-syntax syntax/parse))
(provide the-test-suite)
(define the-test-suite
(test-suite
"utils tests"
(let ()
(check-= (signal-nth (fixed-inputs sine-wave 4) 0)
0.0 (sin (* 2 pi 1/44100 4))
1e-4)
(check-= (signal-nth (fixed-inputs sine-wave 4) 13)
(sin (* 2 pi 13/44100 4)) 1e-4)
(define sw (fixed-inputs square-wave 2))
(check-= (signal-nth sw 0) 1.0 1e-4)
(check-= (signal-nth sw 10) 1.0 1e-4)
(check-= (signal-nth sw 11024) 1.0 1e-4)
(check-= (signal-nth sw 11025) 0.0 1e-4)
(check-= (signal-nth sw 22049) 0.0 1e-4)
(check-= (signal-nth sw 22050) 1.0 1e-4)
(parameterize ([default-sample-rate 500])
(define sw (fixed-inputs square-wave 2))
(check-= (signal-nth sw 0) 1.0 1e-4)
(check-= (signal-nth sw 10) 1.0 1e-4)
(check-= (signal-nth sw 124) 1.0 1e-4)
(check-= (signal-nth sw 125) -1.0 1e-4)
(check-= (signal-nth sw 249) -1.0 1e-4)
(check-= (signal-nth sw 250) 1.0 1e-4)
(check-= (signal-nth sw 166) -1.0 1e-4)
(check-= (signal-nth sw 167) 1.0 1e-4))
(define r (make-tone 882 0.2 44100))
(check-= (rs-ith/left/s16 r 0)
(round (* s16max (* 0.2 (sin (* twopi 882 0/44100))))) 0.0)
(check-equal? (rs-ith/right/s16 r 50) 0)
(check-= (rs-ith/left/s16 r 27)
(round (* s16max (* 0.2 (sin (* twopi 882 27/44100))))) 0.0)
(check-= (rs-ith/left/s16 r 44098)
(round (* s16max (* 0.2 (sin (* twopi 882 44098/44100)))))
1e-7)
(let ()
(define r (make-tone 440 0.2 44100))
(check-= (rs-ith/left/s16 r 0)
(round (* s16max (* 0.2 (sin (* twopi 440 0/44100))))) 0.0)
(check-= (rs-ith/left/s16 r 27)
(round (* s16max (* 0.2 (sin (* twopi 440 27/44100))))) 0.0)
(define (small x) (< x 1e-7))
(for ([i 44100])
(unless (small
(abs
(- (rs-ith/left/s16 r i)
(round (* s16max (* 0.2 (sin (* twopi 440 (/ i 44100)))))))))
(error 'uhoh "failure on sample # ~s" i))))
(let ([r (parameterize ([default-sample-rate 3420])
(make-tone 882 0.2 1000))])
(check-equal? (rsound-sample-rate r) 3420)
(check-= (rs-ith/left/s16 r 27)
(round (* s16max (* 0.2 (sin (* twopi 882 28/44100))))) 4.0))
(define pulse-12.5 (make-pulse-tone 0.125))
(define short-pulse (pulse-12.5 441 0.2 50))
(check-= (rs-ith/left short-pulse 0) 0.2 1e-4)
(check-= (rs-ith/left short-pulse 11) 0.2 1e-4)
(check-= (rs-ith/left short-pulse 13) -0.2 1e-4)
(define shorty (mono 20 t (* 0.01 t)))
(check-= (rs-ith/left shorty 2) 0.02 1e-4)
(check-= (rs-ith/right shorty 9) 0.09 1e-4)
(define shorty2 (rs-overlay shorty shorty))
(check-= (rs-ith/right shorty2 13) 0.26 1e-4)
(define shorty3 (rs-overlay* (list shorty shorty shorty)))
(check-= (rs-ith/left shorty3 6) 0.18 1e-4)
(let ([s (rs-scale 0.75 shorty)])
(check-= (rs-ith/left s 8) 0.06 1e-4))
(let ([r (vectors->rsound (vector 3 4 5) (vector 2 -15 0))]
[s (/ s16max 15)])
(check-equal? (rs-ith/left/s16 r 0) (round (* s 3)))
(check-equal? (rs-ith/right/s16 r 1) (round (* s -15))))
(check-not-exn (lambda () (make-harm3tone 430 0.1 400)))
(time
(for ([i (in-range 100)])
(signal->rsound 44100 (fader 44100))))
(time
(for ([i (in-range 100)])
(signal->rsound 44100 (sine-wave 440))))
(time
(for ([i (in-range 100)])
(signal->rsound 44100 (sawtooth-wave 440))))
(parameterize ([default-sample-rate 1000])
(let ([tr (sawtooth-wave 100)])
(check-= (signal-nth tr 0) 0.0 1e-5)
(check-= (signal-nth tr 1) 0.2 1e-5)
(check-= (signal-nth tr 5) -1.0 1e-5)))
(check-equal? (signal-samples (signal-* (simple-ctr 1 0.5)
(simple-ctr 0 2))
4)
(vector 0 3.0 8.0 15.0))
(check-equal? (signal-samples (signal-+ (simple-ctr 1.0 0.5)
(simple-ctr 0 2))
4)
(vector 1.0 3.5 6.0 8.5))
(let ([s1 (signal->rsound 200 (signal-*s (list (dc-signal 0.5)
(fixed-inputs sine-wave 100))))]
[s2 (time (make-tone 100 0.5 441000))]
[s3 (time (make-tone 100 0.5 441000))])
(check-= (rs-ith/right/s16 s1 73)
(rs-ith/right/s16 s2 73)
1e-2)
(check-= (rs-ith/right/s16 s2 73)
(rs-ith/right/s16 s3 73)
1e-2))
(check-not-exn
(lambda ()
(make-tone 100 0.5 200)
(make-tone 100 0.5 400)))
(let* ([tone (make-tone 147 1.0 4800)]
[fft (rsound-fft/left tone)])
(check-= (magnitude (vector-ref fft 15)) 0.0 1e-2)
(check-= (magnitude (vector-ref fft 16)) 2400.0 1e-2)
(check-= (magnitude (vector-ref fft 17)) 0.0 1e-2))
(check-= (signal-nth (frisellinator 100) 0) 0.0 1e-4)
(check-= (signal-nth (frisellinator 100) 100) 1.0 1e-4)
(check-= (signal-nth (frisellinator 100) 50) 0.5 1e-4)
(check-equal? (binary-logn 4096) 12)
(check-equal? (binary-logn 4095) #f)
(check-equal? ((signal (lambda (t b c) (+ t b c)) 3 4) 1) 8)
(check-= (midi-note-num->pitch 69) 440.0 1e-4)
(check-= (midi-note-num->pitch 57) 220.0 1e-4)
(check-= (midi-note-num->pitch 56) (/ 220 (expt 2 1/12)) 1e-4)
(check-exn (lambda (exn)
(regexp-match #px"^midi-note-num->pitch: " (exn-message exn)))
(lambda ()
(midi-note-num->pitch (list 34 24))))
(check-= (signal-nth (indexed-signal (lambda (x) (* x 3))) 4)
12
1e-4)
(check-= ((rsound->signal/left
(mono 100 x (/ x 1000))) 23)
0.023
1e-4)
(check-= ((rsound->signal/left
(mono 100 x (/ x 1000))) 150)
0.0
1e-4)
(check-exn exn:fail? (lambda () (rsound->signal/left 14)))
(check-= ((rsound->signal/right
(mono 100 x (/ x 1000))) 23)
0.023
1e-4)
(check-exn exn:fail? (lambda () (rsound->signal/right 14)))
(check-= (thresh 1.0 7.0) 1.0 1e-4)
(check-= (thresh 2.0 -1.2) -1.2 1e-4)
(check-= (thresh 2.0 -6.0) -2.0 1e-4)
(check-= (thresh -2.5 3.4) 2.5 1e-4)
(let* ([f (indexed-signal (lambda (t) (* 2 (sin (* t twopi 1 1/12)))))]
[vf (clip&volume 0.5 f)]
[sf (signal-scale 4.0 f)])
(check-= (signal-nth f 0) 0 1e-4)
(check-= (signal-nth f 6) 0 1e-4)
(check-= (signal-nth f 3) 2.0 1e-4)
(check-= (signal-nth vf 0) 0 1e-4)
(check-= (signal-nth vf 3) 0.5 1e-4)
(check-= (signal-nth sf 3) 8.0 1e-4))
(let ()
(define s (noise 100))
(define t (rearrange 100 (lambda (x) (- 99 x)) s))
(for/and ([i (in-range 100)])
(and (equal? (rs-ith/left/s16 s i) (rs-ith/left/s16 t (- 99 i)))
(equal? (rs-ith/right/s16 s i) (rs-ith/right/s16 t (- 99 i))))))
(define (within a b tol)
(< (abs (- a b)) tol))
(let ()
(define s (noise 50))
(define t (rs-map/idx (lambda (s i)
(* s (/ i 50)))
s))
(check-true
(for/and ([i (in-range 50)])
(and (within (* (/ i 50) (rs-ith/left s i))
(rs-ith/left t i)
1e-2)
(within (* (/ i 50) (rs-ith/right s i))
(rs-ith/right t i)
1e-2)))))
(let ()
(define s (noise 50))
(define t (noise 50))
(define u (rs-mult s t))
(for/and ([i (in-range 1)])
(check-= (rs-ith/left u i) (* (rs-ith/left s i) (rs-ith/left t i)) 1e-2)
(check-= (rs-ith/right u i)
(* (rs-ith/right s i)
(rs-ith/right t i)) 1e-2)))
(let ()
(define s (noise 12))
(define t (tile-to-len s 41))
(for/and ([i (in-range 41)])
(check-equal? (rs-ith/left/s16 t i)
(rs-ith/left/s16 s (modulo i 12)))
(check-equal? (rs-ith/right/s16 t i)
(rs-ith/right/s16 s (modulo i 12)))))
(let ()
(define s1 (fader-snd 11025 150))
(check-= (rs-ith/left s1 149)
(expt (expt 0.001 (/ 1 11025)) 149)
1e-3))
(let ()
(define s1 (noise 50))
(define s2 (resample 0.25 s1))
(check-equal? (rs-frames s2) 200)
(check-equal? (rs-ith/right s2 156)
(rs-ith/right s1 39))
(check-equal? (rs-ith/left s2 157)
(rs-ith/left s1 39))
(check-equal? (rs-ith/right s2 158)
(rs-ith/right s1 39))
(check-equal? (rs-ith/left s2 159)
(rs-ith/left s1 39)))
(let ()
(define s1 (noise 50))
(define s2 (resample/interp 0.25 s1))
(check-equal? (rs-frames s2) 200)
(check-equal? (rs-ith/right s2 156)
(rs-ith/right s1 39))
(check-= (rs-ith/left s2 157)
(+ (* 0.75 (rs-ith/left s1 39))
(* 0.25 (rs-ith/left s1 40)))
1e-4)
(check-= (rs-ith/right s2 158)
(+ (* 0.5 (rs-ith/right s1 39))
(* 0.5 (rs-ith/right s1 40)))
1e-4)
(check-= (rs-ith/left s2 159)
(+ (* 0.25 (rs-ith/left s1 39))
(* 0.75 (rs-ith/left s1 40)))
1e-4))
(let ([sample-sound (make-tone 2000 0.15 10)])
(check-= (/ (rs-largest-sample sample-sound) s16max) 0.15 1))
(define test-rsound (noise 200))
(check-equal? (rsound-start test-rsound) 0)
(check-equal? (rsound-stop test-rsound) 200)
(let ([shorter-test (clip test-rsound 30 60)])
(check-equal? (rsound-start shorter-test) 30)
(check-equal? (rsound-stop shorter-test) 60)
(check-equal? (rs-frames shorter-test) 30)
(check-equal? (rsound-sample-rate shorter-test) 44100)
(check-equal? (rs-ith/left/s16 shorter-test 6)
(rs-ith/left/s16 test-rsound 36)))
)))
(module+ test
(require rackunit/text-ui)
(run-tests the-test-suite))