| PasteRack.org | ||
| Paste # 15193 | ||
| 2016-02-25 16:28:36 | ||
Fork as a new paste. | ||
Paste viewed 487 times. | ||
Tweet | ||
Embed: | ||
#lang racket
(require portaudio/s16vec-play ffi/vector racket/stxparam)
(require (for-syntax racket/base syntax/stx racket/syntax racket/trace))
(define channels 2)
(begin-for-syntax
(define (stx-append . rest)
(apply append (map stx->list rest)))
(struct synth-def (states sr-form) #:constructor-name make-synth-def #:prefab)
(define (fun->synth-def sl-stx fun args)
(let ([args (map sl->synth-def (stx->list args))])
(make-synth-def (apply append (map synth-def-states args))
(datum->syntax sl-stx
(cons fun (map synth-def-sr-form args))
sl-stx))))
(define (sl->synth-def sl-stx)
(define sl (syntax-e sl-stx))
(cond [(number? sl) (make-synth-def '() sl-stx)]
[(symbol? sl) (make-synth-def '() sl-stx)]
[(list? sl)
(syntax-case sl-stx (lt hold push saw)
[(lt ([var expr-stx] ...) body-stx ...)
(let ([formals (stx-map (λ (f) (cons (stx-car f) (sl->synth-def (stx-cdr f))))
#'((var . expr-stx) ...))]
[body (stx-map sl->synth-def #'(body-stx ...))])
(make-synth-def (apply append (map synth-def-states (append body (map cdr formals))))
#`(let #,(map (λ (f) (list (car f) (synth-def-sr-form (cdr f)))) formals)
#,@(map synth-def-sr-form body))))]
[(hold ([var init] ...) body-stx ...)
(let ([body (stx-map sl->synth-def #'(body-stx ...))])
(make-synth-def (apply append (stx-map (λ (i) (list (stx-car i) (eval (stx-cdr i)))) #'((var . init) ...))
(map synth-def-states body))
(cons #'begin (map synth-def-sr-form body))))]
[(push holder arg-sl)
(let ([arg (sl->synth-def #'arg-sl)])
(make-synth-def (synth-def-states arg) #`(set! holder #,(synth-def-sr-form arg))))]
[(saw freq phase)
(sl->synth-def
#'(hold ([acc 0.0])
(lt ([result (+ acc phase)])
(push acc (+ acc (* 1/44100 freq)))
(- result (floor result)))))]
[(fun . args) (fun->synth-def sl-stx #'fun #'args)])]))
(trace sl->synth-def)
)
(define-syntax (play stx)
(syntax-case stx ()
[(_ sl secs)
(let ([sd (sl->synth-def #'sl)])
#`(let ([v (make-s16vector (* channels 44100 secs))]
#,@(synth-def-states sd))
(for ([i (in-range (* 44100 secs))])
(define sample #,(synth-def-sr-form sd))
(cond [(number? sample) (set! sample (vector sample sample))]
[(list? sample) (set! sample
(vector (first sample)
(if (empty? (cdr sample))
(first sample)
(second sample))))]
[(vector? sample) (when (< (vector-length sample) 2)
(set! sample
(vector (vector-ref sample 0)
(vector-ref sample 0))))])
(s16vector-set! v (* i channels) (inexact->exact (round (* 32767 (vector-ref sample 0)))))
(s16vector-set! v (add1 (* i channels)) (inexact->exact (round (* 32767 (vector-ref sample 1))))))
(s16vec-play v 0 #f 44100)))]))
(define-syntax-rule (saw-err freq phase)
(hold ([acc 0.0])
(lt ([result (+ acc phase)])
(push acc (+ acc (* 1/44100 freq)))
(- result (floor result)))))