diff --git a/Makefile b/Makefile index c1da169..9505770 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ all: cmake -S ao-play-async -B build (cd build; make) -install: +install: all SUBDIR=`racket -e "(display (format \"~a-~a\" (system-type 'os*) (system-type 'arch)))"`; \ mkdir -p lib/$$SUBDIR SUBDIR=`racket -e "(display (format \"~a-~a\" (system-type 'os*) (system-type 'arch)))"`; \ @@ -13,7 +13,7 @@ install: SUBDIR=`racket -e "(display (format \"~a-~a\" (system-type 'os*) (system-type 'arch)))"`; \ FILES=`ls build/*.dll` 2>/dev/null; if [ "$$FILES" != "" ]; then cp $$FILES lib/$$SUBDIR; fi -zip: +zip: install SUBDIR=`racket -e "(display (format \"~a-~a\" (system-type 'os*) (system-type 'arch)))"`; \ (cd lib; zip -y -r -9 $$SUBDIR.zip $$SUBDIR) SUBDIR=`racket -e "(display (format \"~a-~a\" (system-type 'os*) (system-type 'arch)))"`; \ diff --git a/ao-play-async/ao_playasync.c b/ao-play-async/ao_playasync.c index e35dae2..9557eef 100644 --- a/ao-play-async/ao_playasync.c +++ b/ao-play-async/ao_playasync.c @@ -30,12 +30,14 @@ #include #include #include +#include typedef enum { PLAY = 1, STOP = 2 } Command_t; + typedef void * ao_device; typedef struct _queue_ { @@ -189,6 +191,11 @@ static DWORD run(LPVOID arg) #endif } +int ao_async_version() +{ + return VERSION; +} + void *ao_create_async(void *ao_device_yeah, void *ao_play_f) { //if (ao_play == NULL) { get_ao_play(); } @@ -242,10 +249,135 @@ void ao_stop_async(void *ao_handle) free(h); } -void ao_play_async(void *ao_handle, double at_second, double music_duration, int buf_size, void *mem) +/* +(define (abs x) (if (>= x 0) x (* x -1))) + +(define (make-sample-bytes sample bytes-per-sample endianess) + (letrec ((mk (lambda (i d) + (if (< i bytes-per-sample) + (cons (bitwise-and d 255) + (mk (+ i 1) (arithmetic-shift d -8))) + '())))) + (let ((bytes (mk 0 sample))) + (if (eq? endianess 'big-endian) + (reverse bytes) + bytes)))) + + ;(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) + +*/ + +#define AO_FMT_LITTLE 1 +#define AO_FMT_BIG 2 +#define AO_FMT_NATIVE 4 + +static inline void make_sample_bytes(int32_t sample, int bytes_per_sample, int endianess, unsigned char b[4]) +{ + int i; + for (i = 0; i < bytes_per_sample; i++) { + b[i] = sample&0xff; + sample = sample >> 8; + } + if (endianess == AO_FMT_BIG) { + unsigned char b1[4] = { 0, 0, 0, 0 }; + for(i = 0; i < bytes_per_sample; i++) { + b1[bytes_per_sample - i - 1] = b[i]; + } + for(i = 0; i < bytes_per_sample; i++) { + b[i] = b1[i]; + } + } +} + +void *convertFlac(void *mem, int buf_len, BufferInfo_t *info, int *audio_size) +{ + // buf_size equals number of samples of 32bit for all channels. So buf_size for flac = 4 * buf_len * channels + + int bytes = info->sample_bits / 8; + int endianness = info->endiannes; + int store_size = info->channels * bytes * buf_len; + unsigned char *new_mem = (unsigned char *) malloc(store_size); + *audio_size = store_size; + int32_t **buffer = (int32_t **) mem; + int i, k, channel; + + i = 0; + for(k = 0; k < buf_len; k++) { + for(channel = 0; channel < info->channels; channel++) { + int32_t *chan = buffer[channel]; + int32_t sample = chan[k]; + unsigned char b[4]; + make_sample_bytes(sample, bytes, endianness, b); + for(int j = 0; j < bytes; j++) { + new_mem[i++] = b[j]; + } + } + } + + return (void *) new_mem; +} + +void ao_play_async(void *ao_handle, double at_second, double music_duration, int buf_size, void *mem, BufferInfo_t info) { AO_Handle *h = (AO_Handle *) ao_handle; - Queue_t *q = new_elem(PLAY, at_second, music_duration, buf_size, mem); + + fprintf(stderr, "ao_play_async: %lf %lf %d %d\n", at_second, music_duration, buf_size, info.type); + + Queue_t *q = NULL; + + switch(info.type) { + case flac: { + int store_size = 0; + void *store_mem = convertFlac(mem, buf_size, &info, &store_size); + q = new_elem(PLAY, at_second, music_duration, store_size, store_mem); + free(store_mem); + fprintf(stderr, "flac made\n"); + } + break; + case ao: { + q = new_elem(PLAY, at_second, music_duration, buf_size, mem); + } + break; + case mpg123: { + static int warned = 0; + if (!warned) { + warned = 1; + fprintf(stderr, "format mpg123 not supported yet\n"); + } + return; + } + break; + case ao_ogg: { + static int warned = 0; + if (!warned) { + warned = 1; + fprintf(stderr, "format ao_ogg not supported yet\n"); + } + return; + } + break; + } + MUTEX_LOCK(h->mutex); add(h, q); MUTEX_UNLOCK(h->mutex); diff --git a/ao-play-async/ao_playasync.h b/ao-play-async/ao_playasync.h index 4352ed9..a0b69d0 100644 --- a/ao-play-async/ao_playasync.h +++ b/ao-play-async/ao_playasync.h @@ -11,9 +11,27 @@ #define AOPLAYASYNC_EXPORT extern #endif +#define VERSION 1 + +typedef enum { + ao = 1, + flac = 2, + mpg123 = 3, + ao_ogg = 4 +} BufferType_t; + +typedef struct { + BufferType_t type; + int sample_bits; + int sample_rate; + int channels; + int endiannes; +} BufferInfo_t; + +AOPLAYASYNC_EXPORT int ao_async_version(void); AOPLAYASYNC_EXPORT void *ao_create_async(void *ao_handle, void *ao_play_f); AOPLAYASYNC_EXPORT void ao_stop_async(void *handle); -AOPLAYASYNC_EXPORT void ao_play_async(void *handle, double at_second, double music_duration, int buf_size, void *mem); +AOPLAYASYNC_EXPORT void ao_play_async(void *handle, double at_second, double music_duration, int buf_size, void *mem, BufferInfo_t info); AOPLAYASYNC_EXPORT void ao_clear_async(void *handle); AOPLAYASYNC_EXPORT double ao_is_at_second_async(void *handle); diff --git a/lib/linux-x86_64.zip b/lib/linux-x86_64.zip index 1399825..541413f 100644 Binary files a/lib/linux-x86_64.zip and b/lib/linux-x86_64.zip differ