diff options
-rw-r--r-- | chickadee/audio/vorbis.scm | 317 |
1 files changed, 157 insertions, 160 deletions
diff --git a/chickadee/audio/vorbis.scm b/chickadee/audio/vorbis.scm index ab85187..74dd768 100644 --- a/chickadee/audio/vorbis.scm +++ b/chickadee/audio/vorbis.scm @@ -21,11 +21,10 @@ (define-module (chickadee audio vorbis) #:use-module (chickadee config) + #:use-module (chickadee data bytestruct) #:use-module (ice-9 format) #:use-module (ice-9 match) #:use-module (rnrs bytevectors) - #:use-module (srfi srfi-9) - #:use-module (srfi srfi-9 gnu) #:use-module (system foreign) #:export (vorbis-open vorbis-clear @@ -56,134 +55,153 @@ (define name (vorbis-func return-type func-name arg-types))) -(define ogg-sync-state - (list '* ; data - int ; storage - int ; fill - int ; returned - int ; unsynced - int ; headerbytes - int ; bodybytes - )) - -(define ogg-stream-state - (list '* ; body_data - long ; body_storage - long ; body_fill - long ; body_returned - '* ; lacing_vals - '* ; granule_vals - long ; lacing_storage - long ; lacing_fill - long ; lacing_packet - long ; lacing_returned - (make-list 282 uint8) ; header - int ; header_fill - int ; e_o_s - int ; b_o_s - long ; serialno - long ; pageno - int64 ; packetno - int64 ; granulepos - )) - -(define oggpack-buffer - (list long ; endbyte - int ; endbit - '* ; buffer - '* ; ptr - long ; storage - )) - -(define vorbis-dsp-state - (list int ; analysisp - '* ; vi - '* ; pcm - '* ; pcmret - int ; pcm_storage - int ; pcm_current - int ; pcm_returned - int ; preextrapolate - int ; eofflag - long ; lW - long ; W - long ; nW - long ; centerW - int64 ; granulepos - int64 ; sequence - int64 ; glue_bits - int64 ; time_bits - int64 ; floor_bits - int64 ; res_bits - '* ; backend_state - )) - -(define vorbis-block - (list '* ; pcm - oggpack-buffer ; opb - long ; lW - long ; W - long ; nW - int ; pcmend - int ; mode - int ; eofflag - int64 ; granulepos - int64 ; sequence - '* ; vd - '* ; localstore - long ; localtop - long ; localalloc - long ; totaluse - '* ; reap - long ; glue_bits - long ; time_bits - long ; floor_bits - long ; res_bits - '* ; internal - )) - -(define %vorbis-info - (list int ; version - int ; channels - long ; rate - long ; bitrate_upper - long ; bitrate_nominal - long ; bitrate_lower - long ; bitrate_window - '* ; codec_setup - )) - -(define ov-callbacks - (list '* ; read_func - '* ; seek_func - '* ; close_func - '* ; tell_func - )) - -(define ogg-vorbis-file - (list '* ; datasource - int ; seekable - int64 ; offset - int64 ; end - ogg-sync-state ; oy - int ; links - '* ; offsets - '* ; dataoffsets - '* ; serialnos - '* ; pcmlengths - '* ; vi - '* ; vc - int64 ; pcm_offset - int ; ready_state - long ; current_serialno - int ; current_link - double ; bittrack - double ; samptrack - ogg-stream-state ; os - vorbis-dsp-state ; vd - vorbis-block ; vb - ov-callbacks ; callbacks - )) +(define-bytestruct <ogg-sync-state> + (struct + (data (* u8)) + (storage int) + (fill int) + (returned int) + (unsynced int) + (headerbytes int) + (bodybytes int))) + +(define-bytestruct <ogg-stream-state> + (struct + (body-data (* u8)) + (body-storage long) + (body-fill long) + (body-returned long) + (lacing-vals (* int)) + (granule-vals (* s64)) + (lacing-storage long) + (lacing-fill long) + (lacing-packet long) + (lacing-returned long) + (header (array 282 u8)) + (header-fill int) + (e_o_s int) + (b_o_s int) + (serialno long) + (pageno long) + (packetno s64) + (granulepos s64))) + +(define-bytestruct <oggpack-buffer> + (struct + (endbyte long) + (endbit int) + (buffer (* u8)) + (ptr (* u8)) + (storage long))) + +(define-bytestruct <vorbis-info> + (struct + (version int) + (channels int) + (rate long) + (bitrate-upper long) + (bitrate-nominal long) + (bitrate-lower long) + (bitrate-window long) + (codec-setup (* void)))) + +(define-bytestruct-predicate vorbis-info? <vorbis-info>) +(define-bytestruct-getter vorbis-info-version <vorbis-info> (version)) +(define-bytestruct-getter vorbis-info-channels <vorbis-info> (channels)) +(define-bytestruct-getter vorbis-info-sample-rate <vorbis-info> (rate)) + +(define-bytestruct <vorbis-comment> + (struct + (user-comments (* (* u8))) + (comment-lengths (* int)) + (comments int) + (vendor (* u8)))) + +(define-bytestruct <vorbis-dsp-state> + (struct + (analysisp int) + (vi (* <vorbis-info>)) + (pcm (* (* f32))) + (prcmret (* (* f32))) + (pcm-storage int) + (pcm-current int) + (pcm-returned int) + (preextrapolate int) + (eofflag int) + (lW long) + (W long) + (nW long) + (centerW long) + (granulepos s64) + (sequence s64) + (glue-bits s64) + (time-bits s64) + (floor-bits s64) + (res-bits s64) + (backend-state (* void)))) + +(define-bytestruct <alloc-chain> + (struct + (ptr (* void)) + (next (* <alloc-chain>)))) + +(define-bytestruct <vorbis-block> + (struct + (pcm (* (* f32))) + (opb <oggpack-buffer>) + (lW long) + (W long) + (nW long) + (pcmend int) + (mode int) + (eofflag int) + (granulepos s64) + (sequence s64) + (vd (* <vorbis-dsp-state>)) + (localstore (* void)) + (localtop long) + (localalloc long) + (totaluse long) + (reap (* <alloc-chain>)) + (glue-bits long) + (time-bits long) + (floor-bits long) + (res-bits long) + (internal (* void)))) + +(define-bytestruct <ov-callbacks> + (struct + ;; These are actually function pointers, but we don't use them so + ;; void pointers are fine. + (read-func (* void)) + (seek-func (* void)) + (close-func (* void)) + (tell-func (* void)))) + +(define-bytestruct <ogg-vorbis-file> + (struct + (datasource (* void)) + (seekable int) + (offset s64) + (end s64) + (oy <ogg-sync-state>) + (links int) + (offsets (* s64)) + (dataoffsets (* s64)) + (serialnos (* long)) + (pcmlengths (* s64)) + (vi (* <vorbis-info>)) + (vc (* <vorbis-comment>)) + (pcm-offset s64) + (ready-state int) + (current-seialno long) + (current-link int) + (bittrack f64) + (samptrack f64) + (os <ogg-stream-state>) + (vd <vorbis-dsp-state>) + (vb <vorbis-block>) + (callbacks <ov-callbacks>))) (define OV_FALSE -1) (define OV_EOF -2) @@ -235,49 +253,28 @@ ;;; High-level public API ;;; -(define-record-type <vorbis-file> - (wrap-vorbis-file bv ptr) - vorbis-file? - (bv vorbis-file-bv) - (ptr unwrap-vorbis-file)) - -(define (display-vorbis-file vf port) - (format port "#<vorbis-file ~x>" (pointer-address (unwrap-vorbis-file vf)))) - -(set-record-type-printer! <vorbis-file> display-vorbis-file) - (define (vorbis-open file-name) "Open the OGG Vorbis audio file located at FILE-NAME." - (let* ((bv (make-bytevector (sizeof ogg-vorbis-file))) - (ptr (bytevector->pointer bv))) - (ov-fopen (string->pointer file-name) ptr) - (wrap-vorbis-file bv ptr))) + (let ((vf (bytestruct-alloc <ogg-vorbis-file>))) + (ov-fopen (string->pointer file-name) + (bytestruct->pointer <ogg-vorbis-file> vf)) + vf)) (define (vorbis-clear vf) "Clear the buffers of the Vorbis file VF." - (ov-clear (unwrap-vorbis-file vf))) - -(define-record-type <vorbis-info> - (make-vorbis-info version channels sample-rate) - vorbis-info? - (version vorbis-info-version) - (channels vorbis-info-channels) - (sample-rate vorbis-info-sample-rate)) + (ov-clear (bytestruct->pointer <ogg-vorbis-file> vf))) (define (vorbis-info vf) - (match (parse-c-struct (ov-info (unwrap-vorbis-file vf) -1) - %vorbis-info) - ((version channels sample-rate _ _ _ _ _) - (make-vorbis-info version channels sample-rate)))) + (pointer->bytestruct <vorbis-info> (bytestruct-ref <ogg-vorbis-file> (vi) vf))) (define (vorbis-time-total vf) - (ov-time-total (unwrap-vorbis-file vf) -1)) + (ov-time-total (bytestruct->pointer <ogg-vorbis-file> vf) -1)) (define (vorbis-time-seek vf t) - (ov-time-seek (unwrap-vorbis-file vf) t)) + (ov-time-seek (bytestruct->pointer <ogg-vorbis-file> vf) t)) (define* (vorbis-read vf buffer #:optional (start 0)) - (ov-read (unwrap-vorbis-file vf) + (ov-read (bytestruct->pointer <ogg-vorbis-file> vf) (bytevector->pointer buffer start) (- (bytevector-length buffer) start) 0 ; little endian |