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))
(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
)

View File

@@ -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))

View File

@@ -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)))

134
libao.rkt
View File

@@ -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)))

View File

@@ -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))))