#lang racket
(require racket/flonum
"network.rkt")
(provide
(contract-out [build-wavetable (-> procedure?
flvector?)]
[wavetable-build-sample-rate number?]
[make-table-based-wavefun
(-> flvector? (-> number? number? signal?))]))
(define (build-wavetable fun)
(define sigfun (network-init (fun 1 wavetable-build-sample-rate)))
(let ([newvec (make-flvector wavetable-build-sample-rate)])
(for ([i (in-range wavetable-build-sample-rate)])
(flvector-set! newvec i (exact->inexact (sigfun))))
newvec))
(define ((make-table-based-wavefun vec) pitch sample-rate)
(unless (<= (flvector-length vec) wavetable-build-sample-rate)
(raise-argument-error 'make-table-based-wavefun
(format "wavetable vector of length ~s"
wavetable-build-sample-rate)
0 vec))
(define relative-pitch (* pitch (/ wavetable-build-sample-rate sample-rate)))
(define skip-rate (inexact->exact (round relative-pitch)))
(define index-net (loop-ctr wavetable-build-sample-rate skip-rate))
(network ()
(idx (index-net))
(out (flvector-ref vec idx))))
(define wavetable-build-sample-rate 44100)
(module+ test
(require rackunit)
(define wtvec (build-wavetable (lambda (pitch sample-rate) random)))
(define wavefun ((make-table-based-wavefun wtvec) 33 22100))
(check-equal? (signal-nth wavefun 0) (flvector-ref wtvec 0))
(check-equal? (signal-nth wavefun 5) (flvector-ref wtvec (* 33 2 5)))
)