diff --git a/flac-decoder.rkt b/flac-decoder.rkt index 2285205..c52d25b 100644 --- a/flac-decoder.rkt +++ b/flac-decoder.rkt @@ -47,13 +47,12 @@ (channels (hash-ref h 'channels)) (block-size (hash-ref h 'blocksize))) (hash-set! h 'duration (flac-duration handle)) - (let ((buffers (ffi 'get-buffers buffer channels block-size))) - (set! last-buffer buffers) - (set! last-buf-len (hash-ref h 'blocksize)) - (hash-set! kinds type #t) - (when (procedure? cb-audio) - (cb-audio h buffers)) - )) + (set! last-buffer buffer) + (set! last-buf-len block-size) + (hash-set! kinds type #t) + (when (procedure? cb-audio) + (cb-audio h buffer block-size)) + ) #t ) diff --git a/libao-async-ffi.rkt b/libao-async-ffi.rkt index a3ba906..e9c91c0 100644 --- a/libao-async-ffi.rkt +++ b/libao-async-ffi.rkt @@ -15,22 +15,56 @@ ao_bufsize_async ao_clear_async ao_pause_async + make-BufferInfo_t ) +(define _BufferType_t + (_enum '(ao = 1 + flac = 2 + mpg123 = 3 + ao_ogg = 4 + ))) + +;#define AO_FMT_LITTLE 1 +;#define AO_FMT_BIG 2 +;#define AO_FMT_NATIVE 4 + +(define _Endian_t + (_enum '(little-endian = 1 + big-endian = 2 + native-endian = 4 + ) + ) + ) + +(define-cstruct _BufferInfo_t + ( + [type _BufferType_t] + [sample_bits _int] + [sample_rate _int] + [channels _int] + [endiannes _Endian_t] + )) + + (define lib (get-lib '("ao-play-async" "libao-play-async") '(#f))) +;(define lib (ffi-lib "/home/hans/src/racket/racket-sound-lib/lib/linux-x86_64/libao-play-async.so")) (define-ffi-definer define-libao-async lib #:default-make-fail make-not-available) (define _libao-async-handle-pointer (_cpointer 'ao-async-handle)) +;extern int ao_async_version() +(define-libao-async ao_async_version (_fun -> _int)) + ;extern void *ao_create_async(void *ao_device, ); (define-libao-async ao_create_async(_fun _pointer _fpointer -> _libao-async-handle-pointer)) ;extern void ao_stop_async(void *handle); (define-libao-async ao_stop_async(_fun _libao-async-handle-pointer -> _void)) -;extern void ao_play_async(void *handle, double at_second, double music_duration, int buf_size, void *mem); -(define-libao-async ao_play_async(_fun _libao-async-handle-pointer _double _double _uint32 _pointer -> _void)) +;extern void ao_play_async(void *handle, double at_second, double music_duration, int buf_size, void *mem, BufferInfo_t info); +(define-libao-async ao_play_async(_fun _libao-async-handle-pointer _double _double _uint32 _pointer _BufferInfo_t -> _void)) ;extern double ao_is_at_second_async(void *handle); (define-libao-async ao_is_at_second_async(_fun _libao-async-handle-pointer -> _double)) diff --git a/libao-async.rkt b/libao-async.rkt index 4ce0958..e9c10a9 100644 --- a/libao-async.rkt +++ b/libao-async.rkt @@ -14,6 +14,11 @@ ao_bufsize_async ao_clear_async ao_pause_async + make-ao_buf_info + ao_buf_info-type + ao_buf_info-sample-bits + ao_buf_info-sample-rate + ao_buf_info-channels ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -35,6 +40,15 @@ ;; ao-player in os thread ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(define-struct ao_buffer_info + (type + sample-bits + sample-rate + channels + ) + #:transparent + ) + (define-struct ao-shm (mutex device @@ -86,6 +100,7 @@ (duration (caddr elem)) (buf-len (cadddr elem)) (buf (car (cddddr elem))) + (buf-info (cadr (cddddr elem))) ) (mutex-lock (ao-shm-mutex shm)) (set-ao-shm-at-second! shm at-second) @@ -130,7 +145,7 @@ (define (ao_stop_async shm) (mutex-lock (ao-shm-mutex shm)) (ao_clear_async* shm) - (enqueue! (ao-shm-queue shm) (list 'stop 0 0 #f #f)) + (enqueue! (ao-shm-queue shm) (list 'stop 0 0 #f #f #f)) (os-semaphore-post (ao-shm-queue-sem shm)) (mutex-unlock (ao-shm-mutex shm)) (let ((stopped (λ () @@ -149,8 +164,8 @@ ) ) -(define (ao_play_async shm at-second music-duration buf-size buf) - (let ((item (list 'play at-second music-duration buf-size buf))) +(define (ao_play_async shm at-second music-duration buf-size buf buf-info) + (let ((item (list 'play at-second music-duration buf-size buf buf-info))) (mutex-lock (ao-shm-mutex shm)) (let ((bs (ao-shm-bufsize shm))) (set-ao-shm-bufsize! shm (+ bs buf-size))) diff --git a/libao.rkt b/libao.rkt index ca83881..86f1d41 100644 --- a/libao.rkt +++ b/libao.rkt @@ -1,11 +1,8 @@ #lang racket/base -(define libao-async-mode 'ffi) ; 'ffi or 'scheme - (require "libao-ffi.rkt" (prefix-in fin: finalizer) (prefix-in ffi: "libao-async-ffi.rkt") - (prefix-in scm: "libao-async.rkt") ffi/unsafe data/queue "private/utils.rkt" @@ -20,23 +17,12 @@ ao-music-duration ao-bufsize-async ao-clear-async - ao-set-async-mode! - ao-async-mode ao-pause ) (define devices (make-hash)) (define device-number 1) -(define (ao-set-async-mode! mode) - (if (or (eq? mode 'ffi) (eq? mode 'scheme)) - (set! libao-async-mode mode) - (error "mode must be 'ffi or 'scheme")) - mode) - -(define (ao-async-mode) - libao-async-mode) - (define-struct ao-handle (handle-num [bits #:auto #:mutable] [bytes-per-sample #:auto #:mutable] @@ -106,9 +92,7 @@ (set-ao-handle-byte-format! handle endianness) (set-ao-handle-rate! handle rate) (set-ao-handle-channels! handle channels) - (if (eq? libao-async-mode 'ffi) - (set-ao-handle-async-player! handle (ffi:ao_create_async ao-device ao_play_ptr)) - (set-ao-handle-async-player! handle (scm:ao_create_async ao-device))) + (set-ao-handle-async-player! handle (ffi:ao_create_async ao-device ao_play_ptr)) (hash-set! devices handle-num ao-device) (fin:register-finalizer handle (lambda (handle) @@ -136,15 +120,8 @@ 'warning-ao-device-already-closed (begin (set-ao-handle-closed! handle #t) - (if (eq? libao-async-mode 'ffi) - (begin - (ffi:ao_clear_async (ao-handle-async-player handle)) - (ffi:ao_stop_async (ao-handle-async-player handle)) - ) - (begin - (scm:ao_clear_async (ao-handle-async-player handle)) - (scm:ao_stop_async (ao-handle-async-player handle)) - )) + (ffi:ao_clear_async (ao-handle-async-player handle)) + (ffi:ao_stop_async (ao-handle-async-player handle)) (if (eq? ao-device #f) 'error-ao-device-non-existent (let ((r (ao_close ao-device))) @@ -186,84 +163,67 @@ (reverse bytes) bytes)))) -(define (ao-play handle at-time-in-s music-duration-s buffer) +(define (ao-play handle at-time-in-s music-duration-s buffer buf-len buf-type) (let* ((bytes-per-sample (ao-handle-bytes-per-sample handle)) (bits (ao-handle-bits handle)) + (rate (ao-handle-rate handle)) (channels (ao-handle-channels handle)) (endianess (ao-handle-byte-format handle)) - (buf-len (vector-length (car buffer))) - (audio-buf-len (* channels bytes-per-sample buf-len)) - (audio (if (eq? libao-async-mode 'ffi) - (malloc 'atomic audio-buf-len) - (malloc 'atomic audio-buf-len))) ; was: 'raw - (get-sample (lambda (k channel) - (let ((chan-buf (list-ref buffer channel))) - (vector-ref chan-buf k)))) + ;(audio-buf-len (* channels bytes-per-sample buf-len)) + ;(audio (malloc 'atomic audio-buf-len)) + ;(get-sample (lambda (k channel) + ; (let ((chan-buf (list-ref buffer channel))) + ; (vector-ref chan-buf k)))) ) - (letrec ((i 0) - (fill (lambda (k channel) - (if (< k buf-len) - (if (< channel channels) - (let* ((sample (get-sample k channel)) - (bytes (make-sample-bytes sample bytes-per-sample endianess)) - ) - (for-each (lambda (byte) - (ptr-set! audio _byte i byte) - (set! i (+ i 1))) - bytes) - ;; process sample - (fill k (+ channel 1))) - (fill (+ k 1) 0)) - 'filled)) - )) - (fill 0 0) - (if (eq? libao-async-mode 'ffi) - (ffi:ao_play_async (ao-handle-async-player handle) - (exact->inexact at-time-in-s) - (exact->inexact music-duration-s) - audio-buf-len - audio) - (scm:ao_play_async (ao-handle-async-player handle) - (exact->inexact at-time-in-s) - (exact->inexact music-duration-s) - audio-buf-len - audio) - ) + ;(letrec ((i 0) + ; (fill (lambda (k channel) + ; (if (< k buf-len) + ; (if (< channel channels) + ; (let* ((sample (get-sample k channel)) + ; (bytes (make-sample-bytes sample bytes-per-sample endianess)) + ; ) + ; (for-each (lambda (byte) + ; (ptr-set! audio _byte i byte) + ; (set! i (+ i 1))) + ; bytes) + ; ;; process sample + ; (fill k (+ channel 1))) + ; (fill (+ k 1) 0)) + ; 'filled)) + ; )) + ; (fill 0 0) + + (let ((buf-info (ffi:make-BufferInfo_t buf-type bits rate channels endianess))) + ;(displayln "Calling ao_play_async") + (ffi:ao_play_async (ao-handle-async-player handle) + (exact->inexact at-time-in-s) + (exact->inexact music-duration-s) + buf-len + buffer + buf-info) ) - ;(let* ((handle-num (ao-handle-handle-num handle)) - ; (ao-device (hash-ref devices handle-num #f))) - ; (if (eq? ao-device #f) - ; (error "No device for this handle") - ; (ao_play ao-device audio audio-buf-len))) ) ) ) (define (ao-pause handle pause) - (if (eq? libao-async-mode 'ffi) - (ffi:ao_pause_async (ao-handle-async-player handle) (if (eq? pause #f) 0 1)) - (scm:ao_pause_async (ao-handle-async-player handle) pause) - )) + (ffi:ao_pause_async (ao-handle-async-player handle) (if (eq? pause #f) 0 1)) + ) (define (ao-at-second handle) - (if (eq? libao-async-mode 'ffi) - (ffi:ao_is_at_second_async (ao-handle-async-player handle)) - (scm:ao_is_at_second_async (ao-handle-async-player handle)))) - + (ffi:ao_is_at_second_async (ao-handle-async-player handle)) + ) + (define (ao-music-duration handle) - (if (eq? libao-async-mode 'ffi) - (ffi:ao_music_duration_async (ao-handle-async-player handle)) - (scm:ao_music_duration_async (ao-handle-async-player handle)))) + (ffi:ao_music_duration_async (ao-handle-async-player handle)) + ) (define (ao-bufsize-async handle) - (if (eq? libao-async-mode 'ffi) - (ffi:ao_bufsize_async (ao-handle-async-player handle)) - (scm:ao_bufsize_async (ao-handle-async-player handle)))) + (ffi:ao_bufsize_async (ao-handle-async-player handle)) + ) (define (ao-clear-async handle) - (if (eq? libao-async-mode 'ffi) - (ffi:ao_clear_async (ao-handle-async-player handle)) - (scm:ao_clear_async (ao-handle-async-player handle)))) - + (ffi:ao_clear_async (ao-handle-async-player handle)) + ) ;(let* ((handle-num (ao-handle-handle-num handle)) ; (ao-device (hash-ref devices handle-num #f))) diff --git a/play-test.rkt b/play-test.rkt index aa7e7f7..5a26f98 100644 --- a/play-test.rkt +++ b/play-test.rkt @@ -1,6 +1,7 @@ #lang racket/base (require "libao.rkt" "flac-decoder.rkt" + simple-log ;data/queue ;racket-sound ) @@ -15,14 +16,15 @@ ) ) -(ao-set-async-mode! 'ffi) ;(define fmt (ao-mk-format 24 48000 2 'big-endian)) ;(define ao-h (ao-open-live #f fmt)) (define current-seconds 0) (define ao-h #f) -(define (flac-play frame buffer) +(sl-log-to-display) + +(define (flac-play frame buffer buf-len) (let* ((sample (hash-ref frame 'number)) (rate (hash-ref frame 'sample-rate)) (second (/ (* sample 1.0) (* rate 1.0))) @@ -35,8 +37,10 @@ (when (eq? ao-h #f) (let ((fmt (ao-mk-format bits-per-sample rate channels 'big-endian))) (set! ao-h (ao-open-live #f fmt)))) - (ao-play ao-h second duration buffer) - (let ((second-printer (λ () + ;(displayln 'ao-play) + (ao-play ao-h second duration buffer buf-len 'flac) + ;(displayln 'done) + (let ((second-printer (λ (buf-seconds) (let ((s (inexact->exact (round (ao-at-second ao-h))))) (unless (= s current-seconds) (set! current-seconds s) @@ -45,13 +49,14 @@ (tminutes (quotient duration 60)) (tseconds (remainder duration 60)) ) - (displayln (format "At time: ~a:~a (~a:~a)" + (displayln (format "At time: ~a:~a (~a:~a) - ~a" minutes seconds tminutes tseconds + buf-seconds )))))))) (let* ((buf-size (ao-bufsize-async ao-h)) (buf-seconds (exact->inexact (/ buf-size bytes-per-sample-all-channels rate)))) - (second-printer) + (second-printer buf-seconds) (when (> buf-seconds 5) (letrec ((waiter (λ () (let ((buf-seconds-left (exact->inexact @@ -62,7 +67,7 @@ (displayln (format "Seconds in buffer left: ~a" buf-seconds-left)) (begin (sleep 0.5) - (second-printer) + (second-printer buf-seconds) (waiter))))) )) (waiter))))