changed async library. Flac conversion in C

This commit is contained in:
2026-04-10 08:32:55 +02:00
parent f3b6fc9669
commit 7aa77436bb
5 changed files with 119 additions and 106 deletions

View File

@@ -47,13 +47,12 @@
(channels (hash-ref h 'channels)) (channels (hash-ref h 'channels))
(block-size (hash-ref h 'blocksize))) (block-size (hash-ref h 'blocksize)))
(hash-set! h 'duration (flac-duration handle)) (hash-set! h 'duration (flac-duration handle))
(let ((buffers (ffi 'get-buffers buffer channels block-size))) (set! last-buffer buffer)
(set! last-buffer buffers) (set! last-buf-len block-size)
(set! last-buf-len (hash-ref h 'blocksize))
(hash-set! kinds type #t) (hash-set! kinds type #t)
(when (procedure? cb-audio) (when (procedure? cb-audio)
(cb-audio h buffers)) (cb-audio h buffer block-size))
)) )
#t #t
) )

View File

@@ -15,22 +15,56 @@
ao_bufsize_async ao_bufsize_async
ao_clear_async ao_clear_async
ao_pause_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 (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 (define-ffi-definer define-libao-async lib
#:default-make-fail make-not-available) #:default-make-fail make-not-available)
(define _libao-async-handle-pointer (_cpointer 'ao-async-handle)) (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, ); ;extern void *ao_create_async(void *ao_device, );
(define-libao-async ao_create_async(_fun _pointer _fpointer -> _libao-async-handle-pointer)) (define-libao-async ao_create_async(_fun _pointer _fpointer -> _libao-async-handle-pointer))
;extern void ao_stop_async(void *handle); ;extern void ao_stop_async(void *handle);
(define-libao-async ao_stop_async(_fun _libao-async-handle-pointer -> _void)) (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); ;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 -> _void)) (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); ;extern double ao_is_at_second_async(void *handle);
(define-libao-async ao_is_at_second_async(_fun _libao-async-handle-pointer -> _double)) (define-libao-async ao_is_at_second_async(_fun _libao-async-handle-pointer -> _double))

View File

@@ -14,6 +14,11 @@
ao_bufsize_async ao_bufsize_async
ao_clear_async ao_clear_async
ao_pause_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 ;; ao-player in os thread
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-struct ao_buffer_info
(type
sample-bits
sample-rate
channels
)
#:transparent
)
(define-struct ao-shm (define-struct ao-shm
(mutex (mutex
device device
@@ -86,6 +100,7 @@
(duration (caddr elem)) (duration (caddr elem))
(buf-len (cadddr elem)) (buf-len (cadddr elem))
(buf (car (cddddr elem))) (buf (car (cddddr elem)))
(buf-info (cadr (cddddr elem)))
) )
(mutex-lock (ao-shm-mutex shm)) (mutex-lock (ao-shm-mutex shm))
(set-ao-shm-at-second! shm at-second) (set-ao-shm-at-second! shm at-second)
@@ -130,7 +145,7 @@
(define (ao_stop_async shm) (define (ao_stop_async shm)
(mutex-lock (ao-shm-mutex shm)) (mutex-lock (ao-shm-mutex shm))
(ao_clear_async* 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)) (os-semaphore-post (ao-shm-queue-sem shm))
(mutex-unlock (ao-shm-mutex shm)) (mutex-unlock (ao-shm-mutex shm))
(let ((stopped (λ () (let ((stopped (λ ()
@@ -149,8 +164,8 @@
) )
) )
(define (ao_play_async shm 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))) (let ((item (list 'play at-second music-duration buf-size buf buf-info)))
(mutex-lock (ao-shm-mutex shm)) (mutex-lock (ao-shm-mutex shm))
(let ((bs (ao-shm-bufsize shm))) (let ((bs (ao-shm-bufsize shm)))
(set-ao-shm-bufsize! shm (+ bs buf-size))) (set-ao-shm-bufsize! shm (+ bs buf-size)))

110
libao.rkt
View File

@@ -1,11 +1,8 @@
#lang racket/base #lang racket/base
(define libao-async-mode 'ffi) ; 'ffi or 'scheme
(require "libao-ffi.rkt" (require "libao-ffi.rkt"
(prefix-in fin: finalizer) (prefix-in fin: finalizer)
(prefix-in ffi: "libao-async-ffi.rkt") (prefix-in ffi: "libao-async-ffi.rkt")
(prefix-in scm: "libao-async.rkt")
ffi/unsafe ffi/unsafe
data/queue data/queue
"private/utils.rkt" "private/utils.rkt"
@@ -20,23 +17,12 @@
ao-music-duration ao-music-duration
ao-bufsize-async ao-bufsize-async
ao-clear-async ao-clear-async
ao-set-async-mode!
ao-async-mode
ao-pause ao-pause
) )
(define devices (make-hash)) (define devices (make-hash))
(define device-number 1) (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 (define-struct ao-handle (handle-num
[bits #:auto #:mutable] [bits #:auto #:mutable]
[bytes-per-sample #:auto #:mutable] [bytes-per-sample #:auto #:mutable]
@@ -106,9 +92,7 @@
(set-ao-handle-byte-format! handle endianness) (set-ao-handle-byte-format! handle endianness)
(set-ao-handle-rate! handle rate) (set-ao-handle-rate! handle rate)
(set-ao-handle-channels! handle channels) (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 (ffi:ao_create_async ao-device ao_play_ptr))
(set-ao-handle-async-player! handle (scm:ao_create_async ao-device)))
(hash-set! devices handle-num ao-device) (hash-set! devices handle-num ao-device)
(fin:register-finalizer handle (fin:register-finalizer handle
(lambda (handle) (lambda (handle)
@@ -136,15 +120,8 @@
'warning-ao-device-already-closed 'warning-ao-device-already-closed
(begin (begin
(set-ao-handle-closed! handle #t) (set-ao-handle-closed! handle #t)
(if (eq? libao-async-mode 'ffi)
(begin
(ffi:ao_clear_async (ao-handle-async-player handle)) (ffi:ao_clear_async (ao-handle-async-player handle))
(ffi:ao_stop_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))
))
(if (eq? ao-device #f) (if (eq? ao-device #f)
'error-ao-device-non-existent 'error-ao-device-non-existent
(let ((r (ao_close ao-device))) (let ((r (ao_close ao-device)))
@@ -186,84 +163,67 @@
(reverse bytes) (reverse bytes)
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)) (let* ((bytes-per-sample (ao-handle-bytes-per-sample handle))
(bits (ao-handle-bits handle)) (bits (ao-handle-bits handle))
(rate (ao-handle-rate handle))
(channels (ao-handle-channels handle)) (channels (ao-handle-channels handle))
(endianess (ao-handle-byte-format handle)) (endianess (ao-handle-byte-format handle))
(buf-len (vector-length (car buffer))) ;(audio-buf-len (* channels bytes-per-sample buf-len))
(audio-buf-len (* channels bytes-per-sample buf-len)) ;(audio (malloc 'atomic audio-buf-len))
(audio (if (eq? libao-async-mode 'ffi) ;(get-sample (lambda (k channel)
(malloc 'atomic audio-buf-len) ; (let ((chan-buf (list-ref buffer channel)))
(malloc 'atomic audio-buf-len))) ; was: 'raw ; (vector-ref chan-buf k))))
(get-sample (lambda (k channel)
(let ((chan-buf (list-ref buffer channel)))
(vector-ref chan-buf k))))
) )
(letrec ((i 0) ;(letrec ((i 0)
(fill (lambda (k channel) ; (fill (lambda (k channel)
(if (< k buf-len) ; (if (< k buf-len)
(if (< channel channels) ; (if (< channel channels)
(let* ((sample (get-sample k channel)) ; (let* ((sample (get-sample k channel))
(bytes (make-sample-bytes sample bytes-per-sample endianess)) ; (bytes (make-sample-bytes sample bytes-per-sample endianess))
) ; )
(for-each (lambda (byte) ; (for-each (lambda (byte)
(ptr-set! audio _byte i byte) ; (ptr-set! audio _byte i byte)
(set! i (+ i 1))) ; (set! i (+ i 1)))
bytes) ; bytes)
;; process sample ; ;; process sample
(fill k (+ channel 1))) ; (fill k (+ channel 1)))
(fill (+ k 1) 0)) ; (fill (+ k 1) 0))
'filled)) ; 'filled))
)) ; ))
(fill 0 0) ; (fill 0 0)
(if (eq? libao-async-mode 'ffi)
(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) (ffi:ao_play_async (ao-handle-async-player handle)
(exact->inexact at-time-in-s) (exact->inexact at-time-in-s)
(exact->inexact music-duration-s) (exact->inexact music-duration-s)
audio-buf-len buf-len
audio) buffer
(scm:ao_play_async (ao-handle-async-player handle) buf-info)
(exact->inexact at-time-in-s)
(exact->inexact music-duration-s)
audio-buf-len
audio)
) )
) )
;(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) (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)) (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) )
))
(define (ao-at-second handle) (define (ao-at-second handle)
(if (eq? libao-async-mode 'ffi)
(ffi:ao_is_at_second_async (ao-handle-async-player handle)) (ffi:ao_is_at_second_async (ao-handle-async-player handle))
(scm:ao_is_at_second_async (ao-handle-async-player handle)))) )
(define (ao-music-duration handle) (define (ao-music-duration handle)
(if (eq? libao-async-mode 'ffi)
(ffi:ao_music_duration_async (ao-handle-async-player handle)) (ffi:ao_music_duration_async (ao-handle-async-player handle))
(scm:ao_music_duration_async (ao-handle-async-player handle)))) )
(define (ao-bufsize-async handle) (define (ao-bufsize-async handle)
(if (eq? libao-async-mode 'ffi)
(ffi:ao_bufsize_async (ao-handle-async-player handle)) (ffi:ao_bufsize_async (ao-handle-async-player handle))
(scm:ao_bufsize_async (ao-handle-async-player handle)))) )
(define (ao-clear-async handle) (define (ao-clear-async handle)
(if (eq? libao-async-mode 'ffi)
(ffi:ao_clear_async (ao-handle-async-player handle)) (ffi:ao_clear_async (ao-handle-async-player handle))
(scm:ao_clear_async (ao-handle-async-player handle)))) )
;(let* ((handle-num (ao-handle-handle-num handle)) ;(let* ((handle-num (ao-handle-handle-num handle))
; (ao-device (hash-ref devices handle-num #f))) ; (ao-device (hash-ref devices handle-num #f)))

View File

@@ -1,6 +1,7 @@
#lang racket/base #lang racket/base
(require "libao.rkt" (require "libao.rkt"
"flac-decoder.rkt" "flac-decoder.rkt"
simple-log
;data/queue ;data/queue
;racket-sound ;racket-sound
) )
@@ -15,14 +16,15 @@
) )
) )
(ao-set-async-mode! 'ffi)
;(define fmt (ao-mk-format 24 48000 2 'big-endian)) ;(define fmt (ao-mk-format 24 48000 2 'big-endian))
;(define ao-h (ao-open-live #f fmt)) ;(define ao-h (ao-open-live #f fmt))
(define current-seconds 0) (define current-seconds 0)
(define ao-h #f) (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)) (let* ((sample (hash-ref frame 'number))
(rate (hash-ref frame 'sample-rate)) (rate (hash-ref frame 'sample-rate))
(second (/ (* sample 1.0) (* rate 1.0))) (second (/ (* sample 1.0) (* rate 1.0)))
@@ -35,8 +37,10 @@
(when (eq? ao-h #f) (when (eq? ao-h #f)
(let ((fmt (ao-mk-format bits-per-sample rate channels 'big-endian))) (let ((fmt (ao-mk-format bits-per-sample rate channels 'big-endian)))
(set! ao-h (ao-open-live #f fmt)))) (set! ao-h (ao-open-live #f fmt))))
(ao-play ao-h second duration buffer) ;(displayln 'ao-play)
(let ((second-printer (λ () (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))))) (let ((s (inexact->exact (round (ao-at-second ao-h)))))
(unless (= s current-seconds) (unless (= s current-seconds)
(set! current-seconds s) (set! current-seconds s)
@@ -45,13 +49,14 @@
(tminutes (quotient duration 60)) (tminutes (quotient duration 60))
(tseconds (remainder 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 minutes seconds
tminutes tseconds tminutes tseconds
buf-seconds
)))))))) ))))))))
(let* ((buf-size (ao-bufsize-async ao-h)) (let* ((buf-size (ao-bufsize-async ao-h))
(buf-seconds (exact->inexact (/ buf-size bytes-per-sample-all-channels rate)))) (buf-seconds (exact->inexact (/ buf-size bytes-per-sample-all-channels rate))))
(second-printer) (second-printer buf-seconds)
(when (> buf-seconds 5) (when (> buf-seconds 5)
(letrec ((waiter (λ () (letrec ((waiter (λ ()
(let ((buf-seconds-left (exact->inexact (let ((buf-seconds-left (exact->inexact
@@ -62,7 +67,7 @@
(displayln (format "Seconds in buffer left: ~a" buf-seconds-left)) (displayln (format "Seconds in buffer left: ~a" buf-seconds-left))
(begin (begin
(sleep 0.5) (sleep 0.5)
(second-printer) (second-printer buf-seconds)
(waiter))))) (waiter)))))
)) ))
(waiter)))) (waiter))))