This commit is contained in:
2026-02-22 23:15:08 +01:00
parent 2cc96f30ae
commit 24b39bee60
8 changed files with 101 additions and 32 deletions

View File

@@ -5,7 +5,10 @@ all:
(cd build; make) (cd build; make)
install: install:
(cd build; cp *.so /usr/local/lib) mkdir -p ../lib
FILES=`ls build/*.so` 2>/dev/null; if [ "$$FILES" != "" ]; then cp $$FILES ../lib; fi
FILES=`ls build/*.dll` 2>/dev/null; if [ "$$FILES" != "" ]; then cp $$FILES ../lib; fi
clean: clean:
rm -rf build rm -rf build

View File

@@ -4,7 +4,7 @@
#include <assert.h> #include <assert.h>
#include <malloc.h> #include <malloc.h>
#include <string.h> #include <string.h>
#include <dlfcn.h> //#include <dlfcn.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@@ -26,15 +26,17 @@ typedef struct _queue_ {
} Queue_t; } Queue_t;
typedef struct { typedef struct {
Queue_t *play_queue; Queue_t *play_queue;
Queue_t *last_frame; Queue_t *last_frame;
ao_device *ao_device; ao_device *ao_device;
pthread_mutex_t mutex; pthread_mutex_t mutex;
pthread_t thread; pthread_t thread;
double at_second; double at_second;
ao_play_func_t ao_play_f;
int buf_size;
} AO_Handle; } AO_Handle;
static int(*ao_play)(void *device, char *samples, uint32_t n) = NULL; //static int(*ao_play)(void *device, char *samples, uint32_t n) = NULL;
static Queue_t *front(AO_Handle *h) static Queue_t *front(AO_Handle *h)
@@ -53,6 +55,7 @@ static Queue_t *get(AO_Handle *h)
} else { } else {
h->play_queue->prev = NULL; h->play_queue->prev = NULL;
} }
h->buf_size -= q->buflen;
return q; return q;
} }
@@ -69,6 +72,7 @@ static void add(AO_Handle *h, Queue_t *elem)
elem->next = NULL; elem->next = NULL;
h->last_frame = elem; h->last_frame = elem;
} }
h->buf_size += elem->buflen;
} }
static Queue_t *new_elem(int command, double at_second, int buf_len, void *buf) static Queue_t *new_elem(int command, double at_second, int buf_len, void *buf)
@@ -125,7 +129,7 @@ static void *run(void *arg)
if (q->command == STOP) { if (q->command == STOP) {
go_on = (1 == 0); go_on = (1 == 0);
} else { } else {
ao_play(handle->ao_device, q->buf, q->buflen); handle->ao_play_f(handle->ao_device, q->buf, q->buflen);
} }
del_elem(q); del_elem(q);
@@ -138,6 +142,7 @@ static void *run(void *arg)
return NULL; return NULL;
} }
/*
static void get_ao_play(void) static void get_ao_play(void)
{ {
char *lib = "libao.so"; char *lib = "libao.so";
@@ -155,11 +160,12 @@ static void get_ao_play(void)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
*/
void *ao_create_async(void *ao_device_yeah) void *ao_create_async(void *ao_device_yeah, void *ao_play_f)
{ {
if (ao_play == NULL) { get_ao_play(); } //if (ao_play == NULL) { get_ao_play(); }
AO_Handle *handle = (AO_Handle *) malloc(sizeof(AO_Handle)); AO_Handle *handle = (AO_Handle *) malloc(sizeof(AO_Handle));
@@ -169,6 +175,8 @@ void *ao_create_async(void *ao_device_yeah)
handle->at_second = -1; handle->at_second = -1;
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
handle->mutex = m; handle->mutex = m;
handle->ao_play_f = ao_play_f;
handle->buf_size = 0;
pthread_create(&handle->thread, NULL, run, handle); pthread_create(&handle->thread, NULL, run, handle);
@@ -202,8 +210,19 @@ void ao_play_async(void *ao_handle, double at_second, int buf_size, void *mem)
double ao_is_at_second_async(void *ao_handle) double ao_is_at_second_async(void *ao_handle)
{ {
AO_Handle *h = (AO_Handle *) ao_handle; AO_Handle *h = (AO_Handle *) ao_handle;
return h->at_second; pthread_mutex_lock(&h->mutex);
double s = h->at_second;
pthread_mutex_unlock(&h->mutex);
return s;
}
int ao_bufsize_async(void *ao_handle)
{
AO_Handle *h = (AO_Handle *) ao_handle;
pthread_mutex_lock(&h->mutex);
int s = h->buf_size;
pthread_mutex_unlock(&h->mutex);
return s;
} }

View File

@@ -1,9 +1,14 @@
#ifndef AO_PLAYASYNC_H #ifndef AO_PLAYASYNC_H
#define AO_PLAYASYNC_H #define AO_PLAYASYNC_H
extern void *ao_create_async(void *ao_handle); #include <stdint.h>
typedef int(*ao_play_func_t)(void *, char *, uint32_t);
extern void *ao_create_async(void *ao_handle, void *ao_play_f);
extern void ao_stop_async(void *handle); extern void ao_stop_async(void *handle);
extern void ao_play_async(void *handle, double at_second, int buf_size, void *mem); extern void ao_play_async(void *handle, double at_second, int buf_size, void *mem);
extern double ao_is_at_second_async(void *handle); extern double ao_is_at_second_async(void *handle);
extern int ao_bufsize_async(void *handle);
#endif // AO_PLAYASYNC_H #endif // AO_PLAYASYNC_H

BIN
libao/lib/libao-play-async.so Executable file

Binary file not shown.

View File

@@ -5,27 +5,32 @@
ffi/unsafe/define ffi/unsafe/define
setup/dirs setup/dirs
"../utils/utils.rkt" "../utils/utils.rkt"
racket/runtime-path
"libao-ffi.rkt"
) )
(provide ao_create_async (provide ao_create_async
ao_stop_async ao_stop_async
ao_play_async ao_play_async
ao_is_at_second_async ao_is_at_second_async
ao_bufsize_async
) )
;(ffi-lib "/usr/local/lib/libao-play-async.so") (define-runtime-path libao-async-path "./lib/libao-play-async")
(define-ffi-definer define-libao-async (define-ffi-definer define-libao-async
(ffi-lib "libao-play-async" '("0" #f) (ffi-lib libao-async-path '("0" #f)
#:get-lib-dirs (lambda () #:get-lib-dirs (λ ()
(cons (build-path ".") (get-lib-search-dirs))) (let ((sp (cons (build-path ".") (get-lib-search-dirs))))
(displayln sp)
sp))
#:fail (λ () (error "Cannot load libao-play-async")) #:fail (λ () (error "Cannot load libao-play-async"))
)) ))
(define _libao-async-handle-pointer (_cpointer 'ao-async-handle)) (define _libao-async-handle-pointer (_cpointer 'ao-async-handle))
;extern void *ao_create_async(void *ao_device); ;extern void *ao_create_async(void *ao_device, );
(define-libao-async ao_create_async(_fun _pointer -> _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))
@@ -35,3 +40,6 @@
;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))
;extern int ao_bufsize_async(void *handle);
(define-libao-async ao_bufsize_async(_fun _libao-async-handle-pointer -> _int))

View File

@@ -13,6 +13,7 @@
ao_driver_id ao_driver_id
ao_open_live ao_open_live
ao_play ao_play
ao_play_ptr
ao_close ao_close
ao_shutdown ao_shutdown
ao_append_option ao_append_option
@@ -26,15 +27,18 @@
) )
(define-ffi-definer define-libao (define ao_lib (ffi-lib "libao" '("3" "4" "5" #f)
(ffi-lib "libao" '("3" "4" "5" #f) #:get-lib-dirs (λ ()
#:get-lib-dirs (lambda () (let ((sp (cons (build-path ".") (get-lib-search-dirs))))
(cons (build-path ".") (get-lib-search-dirs))) (displayln sp)
#:fail (lambda () sp))
(ffi-lib (get-lib-path "libao-4.dll"))) #:fail (λ ()
)) (ffi-lib (get-lib-path "libao-4.dll")))
))
(define-ffi-definer define-libao ao_lib)
(define _libao-pointer (_cpointer 'ao_device)) (define _libao-pointer (_cpointer 'ao_device))
(define-cstruct _ao_sample_format ( (define-cstruct _ao_sample_format (
[bits _int] ; bits per sample [bits _int] ; bits per sample
@@ -66,6 +70,10 @@
; int ao_play(ao_device *device, char *output_samples, uint_32 num_bytes); ; int ao_play(ao_device *device, char *output_samples, uint_32 num_bytes);
(define-libao ao_play (_fun _libao-pointer _pointer _uint32 -> _int)) (define-libao ao_play (_fun _libao-pointer _pointer _uint32 -> _int))
(define ao_play_ptr (get-ffi-obj "ao_play" ao_lib _fpointer
(λ () (error 'ao_lib "libao does not provide 'ao_play'"))
))
; int ao_close(ao_device *device); ; int ao_close(ao_device *device);
(define-libao ao_close (_fun _libao-pointer -> _int)) (define-libao ao_close (_fun _libao-pointer -> _int))

View File

@@ -16,14 +16,36 @@
(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)))
(bits-per-sample (hash-ref frame 'bits-per-sample))
(bytes-per-sample (/ bits-per-sample 8))
(channels (hash-ref frame 'channels))
(bytes-per-sample-all-channels (* channels bytes-per-sample))
) )
(ao-play ao-h second buffer) (ao-play ao-h second buffer)
(let ((second-printer (λ ()
(let ((s (inexact->exact (round (ao-at-second ao-h)))))
(when (> s current-seconds)
(set! current-seconds s)
(displayln (format "At second: ~a" s)))))))
(let* ((buf-size (ao-bufsize-async ao-h))
(buf-seconds (exact->inexact (/ buf-size bytes-per-sample-all-channels rate))))
(second-printer)
(when (> buf-seconds 5)
(letrec ((waiter (λ ()
(let ((buf-seconds-left (exact->inexact
(/ (ao-bufsize-async ao-h)
bytes-per-sample-all-channels
rate))))
(if (< buf-seconds-left 2.0)
(displayln (format "Seconds in buffer left: ~a" buf-seconds-left))
(begin
(sleep 0.5)
(second-printer)
(waiter)))))
))
(waiter))))
)
) )
(let ((s (inexact->exact (round (ao-at-second ao-h)))))
(when (> s current-seconds)
(set! current-seconds s)
(displayln (format "At second: ~a" (ao-at-second ao-h)))
))
) )
(define (flac-meta meta) (define (flac-meta meta)

View File

@@ -57,6 +57,10 @@
try1 try1
try2) try2)
)] )]
[(eq? platform 'unix)
(let ((try1 (build-path (current-directory) "lib" lib)))
(when (file-exists? try1)
try1))]
[else [else
(error (format "Install the shared library: ~a" lib))] (error (format "Install the shared library: ~a" lib))]
))) )))