#lang racket
(require ffi/unsafe
ffi/vector
"private/portaudio.rkt")
(define channels 2)
(define twopi (* 2 pi))
(define max-s16 #x7fff)
(define (play-buffer buffer frames sample-rate)
(define seconds (/ frames sample-rate))
(let* ([stream (pa-open-default-stream 0 channels 'paInt16 (exact->inexact sample-rate) 0 #f #f)] )
(pa-start-stream stream)
(let outer-loop ()
(let ([this-buffer buffer]
[this-frames frames])
(let loop ([buf-offset 0]
[sleep-time 0.005])
(if (< buf-offset this-frames) (let ([available-space (pa-get-stream-write-available stream)])
(printf "available-space: ~v\n" available-space)
(if (= available-space 0)
(begin
(sleep sleep-time)
(loop buf-offset sleep-time))
(let ([frames-to-write (min available-space (- this-frames buf-offset))])
(pa-write-stream stream
(ptr-add (s16vector->cpointer this-buffer) (* channels buf-offset) _sint16)
frames-to-write)
(loop (+ buf-offset frames-to-write)
(/ (/ frames-to-write sample-rate) 2)))))
(printf "done.\n")))))
(pa-stop-stream stream)
(pa-close-stream stream)))
(define (sine-wave pitch sample-rate volume)
(let ([scalar (* twopi pitch)])
(lambda (i)
(let ([t (/ i sample-rate)])
(* max-s16 (* volume (sin (* scalar t))))))))
(define (make-block frames f)
(let* ([cblock (make-s16vector (* 4 channels frames))])
(for ([i (in-range frames)])
(let* ([offset (* 2 i)]
[sample (inexact->exact (round (f i)))])
(s16vector-set! cblock offset sample)
(s16vector-set! cblock (add1 offset) sample)))
cblock))
(define the-block (make-block 44100 (sine-wave 440 44100 0.25)))
(play-buffer the-block 44100 44100)
(sleep 3)