mpg123 support

This commit is contained in:
2026-04-22 08:51:04 +02:00
parent d7f2202091
commit bba44733ab
+333
View File
@@ -0,0 +1,333 @@
(module libflac-ffi racket/base
(require ffi/unsafe
ffi/unsafe/define
"private/utils.rkt"
)
(provide mpg123-ffi-decoder-handler
)
(define lib (get-lib '("libmpg123") '("0" #f)))
(define-ffi-definer define-libmpg123 lib
#:default-make-fail make-not-available)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Some MPG123 Constants
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define _size_t _size)
(define SEEK_SET 0)
(define SEEK_CUR 1)
(define SEEK_END 2)
(define _Seek_t
(_enum '(seek-set = 0
seek-cur = 1
seek-end = 2
)
)
)
(define _MPG123_Result
(_enum '(MPG123_DONE = -12 ;/**< Message: Track ended. Stop decoding. */
MPG123_NEW_FORMAT = -11 ;/**< Message: Output format will be different on next call.
; Note that some libmpg123 versions between 1.4.3 and 1.8.0
; insist on you calling mpg123_getformat() after getting this
; message code. Newer verisons behave like advertised:
; You have the chance to call mpg123_getformat(), but you can
; also just continue decoding and get your data. */
MPG123_NEED_MORE = -10 ;/**< Message: For feed reader: "Feed me more!" (call
; mpg123_feed() or mpg123_decode() with some new input data). */
MPG123_ERR = -1 ;/**< Generic Error */
MPG123_OK=0 ;/**< Success */
MPG123_BAD_OUTFORMAT ;/**< Unable to set up output format! */
MPG123_BAD_CHANNEL ;/**< Invalid channel number specified. */
MPG123_BAD_RATE ;/**< Invalid sample rate specified. */
MPG123_ERR_16TO8TABLE ;/**< Unable to allocate memory for 16 to 8 converter table! */
MPG123_BAD_PARAM ;/**< Bad parameter id! */
MPG123_BAD_BUFFER ;/**< Bad buffer given -- invalid pointer or too small size. */
MPG123_OUT_OF_MEM ;/**< Out of memory -- some malloc() failed. */
MPG123_NOT_INITIALIZED ;/**< You didn't initialize the library! */
MPG123_BAD_DECODER ;/**< Invalid decoder choice. */
MPG123_BAD_HANDLE ;/**< Invalid mpg123 handle. */
MPG123_NO_BUFFERS ;/**< Unable to initialize frame buffers (out of memory?). */
MPG123_BAD_RVA ;/**< Invalid RVA mode. */
MPG123_NO_GAPLESS ;/**< This build doesn't support gapless decoding. */
MPG123_NO_SPACE ;/**< Not enough buffer space. */
MPG123_BAD_TYPES ;/**< Incompatible numeric data types. */
MPG123_BAD_BAND ;/**< Bad equalizer band. */
MPG123_ERR_NULL ;/**< Null pointer given where valid storage address needed. */
MPG123_ERR_READER ;/**< Error reading the stream. */
MPG123_NO_SEEK_FROM_END ;/**< Cannot seek from end (end is not known). */
MPG123_BAD_WHENCE ;/**< Invalid 'whence' for seek function.*/
MPG123_NO_TIMEOUT ;/**< Build does not support stream timeouts. */
MPG123_BAD_FILE ;/**< File access error. */
MPG123_NO_SEEK ;/**< Seek not supported by stream. */
MPG123_NO_READER ;/**< No stream opened or no reader callback setup. */
MPG123_BAD_PARS ;/**< Bad parameter handle. */
MPG123_BAD_INDEX_PAR ;/**< Bad parameters to MPG123_index() and MPG123_set_index() */
MPG123_OUT_OF_SYNC ;/**< Lost track in bytestream and did not try to resync. */
MPG123_RESYNC_FAIL ;/**< Resync failed to find valid MPEG data. */
MPG123_NO_8BIT ;/**< No 8bit encoding possible. */
MPG123_BAD_ALIGN ;/**< Stack aligmnent error */
MPG123_NULL_BUFFER ;/**< NULL input buffer with non-zero size... */
MPG123_NO_RELSEEK ;/**< Relative seek not possible (screwed up file offset) */
MPG123_NULL_POINTER ;/**< You gave a null pointer somewhere where you shouldn't have. */
MPG123_BAD_KEY ;/**< Bad key value given. */
MPG123_NO_INDEX ;/**< No frame index in this build. */
MPG123_INDEX_FAIL ;/**< Something with frame index went wrong. */
MPG123_BAD_DECODER_SETUP ;/**< Something prevents a proper decoder setup */
MPG123_MISSING_FEATURE ;/**< This feature has not been built into libmpg123. */
MPG123_BAD_VALUE ;/**< A bad value has been given somewhere. */
MPG123_LSEEK_FAILED ;/**< Low-level seek failed. */
MPG123_BAD_CUSTOM_IO ;/**< Custom I/O not prepared. */
MPG123_LFS_OVERFLOW ;/**< Offset value overflow during translation
; of large file API calls -- your client program
; cannot handle that large file. */
MPG123_INT_OVERFLOW ;/**< Some integer overflow. */
MPG123_BAD_FLOAT ;/**< Floating-point computations work not as expected. */
)
)
)
(define _mpg123_handle _pointer)
; MPG123_EXPORT int mpg123_init (void)
(define-libmpg123 mpg123_init
(_fun -> _MPG123_Result))
; MPG123_EXPORT mpg123_handle *mpg123_new (const char *decoder, int *error)
(define-libmpg123 mpg123_new
(_fun _string/utf-8 (err : (_ptr o _int))
-> (h : _mpg123_handle)
-> (values h err)))
; MPG123_EXPORT size_t mpg123_outblock ( mpg123_handle * mh )
(define-libmpg123 mpg123_outblock
(_fun _mpg123_handle -> _size_t))
; MPG123_EXPORT int mpg123_open (mpg123_handle *mh, const char *path)
(define-libmpg123 mpg123_open
(_fun _mpg123_handle _string/utf-8 -> _MPG123_Result))
; MPG123_EXPORT int mpg123_close (mpg123_handle *mh)
(define-libmpg123 mpg123_close
(_fun _mpg123_handle -> _MPG123_Result))
; MPG123_EXPORT int mpg123_getformat (mpg123_handle *mh, long *rate, int *channels, int *encoding)
(define-libmpg123 mpg123_getformat
(_fun _mpg123_handle
(rate : (_ptr o _long))
(channels : (_ptr o _int))
(encoding : (_ptr o _int))
-> (r : _MPG123_Result)
-> (values r rate channels encoding)))
; MPG123_EXPORT int mpg123_encsize ( int encoding )
(define-libmpg123 mpg123_encsize
(_fun _int -> _int))
; MPG123_EXPORT int mpg123_read (mpg123_handle *mh, void *outmemory, size_t outmemsize, size_t *done)
(define-libmpg123 mpg123_read
(_fun _mpg123_handle
_pointer
_size_t
(done : (_ptr o _size_t))
-> (r : _MPG123_Result)
-> (values r done)))
; MPG123_EXPORT int64_t mpg123_tell64 ( mpg123_handle * mh )
(define-libmpg123 mpg123_tell64
(_fun _mpg123_handle -> _int64))
; MPG123_EXPORT int64_t mpg123_seek64(mpg123_handle * mh, int64_t sampleoff, int whence )
(define-libmpg123 mpg123_seek64
(_fun _mpg123_handle _int64 _Seek_t -> _int64))
; MPG123_EXPORT int mpg123_scan ( mpg123_handle * mh )
(define-libmpg123 mpg123_scan
(_fun _mpg123_handle -> _MPG123_Result))
; MPG123_EXPORT off_t mpg123_length ( mpg123_handle * mh )
(define-libmpg123 mpg123_length64
(_fun _mpg123_handle -> _int64))
#|
#include <ao/ao.h>
#include <mpg123.h>
#define BITS 8
int main(int argc, char *argv[])
{
mpg123_handle *mh;
unsigned char *buffer;
size_t buffer_size;
size_t done;
int err;
int driver;
ao_device *dev;
ao_sample_format format;
int channels, encoding;
long rate;
if(argc < 2)
exit(0);
/* initializations */
ao_initialize();
driver = ao_default_driver_id();
mpg123_init();
mh = mpg123_new(NULL, &err);
buffer_size = mpg123_outblock(mh);
buffer = (unsigned char*) malloc(buffer_size * sizeof(unsigned char));
/* open the file and get the decoding format */
mpg123_open(mh, argv[1]);
mpg123_getformat(mh, &rate, &channels, &encoding);
/* set the output format and open the output device */
format.bits = mpg123_encsize(encoding) * BITS;
format.rate = rate;
format.channels = channels;
format.byte_format = AO_FMT_NATIVE;
format.matrix = 0;
dev = ao_open_live(driver, &format, NULL);
/* decode and play */
while (mpg123_read(mh, buffer, buffer_size, &done) == MPG123_OK)
ao_play(dev, buffer, done);
/* clean up */
free(buffer);
ao_close(dev);
mpg123_close(mh);
mpg123_delete(mh);
mpg123_exit();
ao_shutdown();
return 0;
}
|#
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Our interface for decoding to racket
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (mpg123-ffi-decoder-handler)
#t
#| (define write-data '())
(define meta-data '())
(define error-no -1)
(define fl #f)
(define flac-file #f)
(define client-data #f)
(define (write-callback fl frame buffer client-data)
(set! write-data (append write-data (list (cons frame buffer))))
0)
(define (meta-callback fl meta client-data)
(let ((meta-clone (FLAC__metadata_object_clone meta)))
(unless (eq? meta-clone #f)
(set! meta-data (append meta-data (list meta-clone))))))
(define (error-callback fl errno client-data)
(set! error-no errno)
)
(define (new)
(set! fl (FLAC__stream_decoder_new))
fl)
(define (init file)
(let ((r (FLAC__stream_decoder_init_file
fl
file
write-callback
meta-callback
error-callback
client-data)))
(set! flac-file file)
r))
(define (process-single)
(FLAC__stream_decoder_process_single fl))
(define (int-state)
(FLAC__stream_decoder_get_state fl))
(define (state)
(decoder-state (int-state)))
(define (process-meta-data cb)
(for-each (λ (meta-entry)
(cb meta-entry)
(FLAC__metadata_object_delete meta-entry))
meta-data)
(set! meta-data '()))
(define (process-write-data cb)
(for-each (lambda (d)
(cb (car d) (cdr d)))
write-data)
(set! write-data '()))
(define (buffer->vectorlist buffer channels size)
(letrec ((for-channels
(lambda (channel)
(if (< channel channels)
(letrec ((v (make-vector size 0))
(p (ptr-ref buffer FLAC__int32-pointer channel))
(to-vec (lambda (i)
(when (< i size)
(vector-set! v i (ptr-ref p _int32 i))
(to-vec (+ i 1)))))
)
(to-vec 0)
(cons v (for-channels (+ channel 1))))
'())))
)
(for-channels 0)))
(define (seek-to-sample sample)
(FLAC__stream_decoder_seek_absolute fl sample))
(lambda (cmd . args)
(cond
[(eq? cmd 'write-data) write-data]
[(eq? cmd 'meta-data) meta-data]
[(eq? cmd 'new) (new)]
[(eq? cmd 'init) (init (car args))]
[(eq? cmd 'process-single) (process-single)]
[(eq? cmd 'get-buffers) (buffer->vectorlist (car args) (cadr args) (caddr args))]
[(eq? cmd 'int-state) (int-state)]
[(eq? cmd 'state) (state)]
[(eq? cmd 'has-write-data?) (not (null? write-data))]
[(eq? cmd 'has-meta-data?) (not (null? meta-data))]
[(eq? cmd 'has-errno?) (not (= error-no -1))]
[(eq? cmd 'process-meta-data) (process-meta-data (car args))]
[(eq? cmd 'process-write-data) (process-write-data (car args))]
[(eq? cmd 'errno) error-no]
[(eq? cmd 'seek-to-sample) (seek-to-sample (car args))]
[(eq? cmd 'file) flac-file]
[else (error (format "unknown command ~a" cmd))]
))
|#
)
); end of module