-
This commit is contained in:
@@ -0,0 +1,189 @@
|
||||
(module mp3-decoder racket/base
|
||||
|
||||
(require ffi/unsafe
|
||||
"libmpg123-ffi.rkt"
|
||||
"private/utils.rkt")
|
||||
|
||||
(provide mp3-open
|
||||
mp3-valid?
|
||||
mp3-read
|
||||
mp3-stop
|
||||
mp3-seek
|
||||
|
||||
flac-valid?
|
||||
flac-read
|
||||
flac-read-meta
|
||||
flac-stream-state
|
||||
flac-stop
|
||||
flac-seek
|
||||
(all-from-out "flac-definitions.rkt")
|
||||
kinds
|
||||
last-buffer last-buf-len
|
||||
)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Functions to do the good stuff
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define (mp3-valid? mp3-file)
|
||||
#t)
|
||||
|
||||
(define (mp3-open mp3-file* cb-stream-info cb-audio)
|
||||
(let ((mp3-file (if (path? mp3-file*) (path->string mp3-file*) mp3-file*)))
|
||||
(if (file-exists? mp3-file)
|
||||
(let (handler (mp3-ffi-
|
||||
|
||||
(define (flac-valid? flac-file*)
|
||||
#t)
|
||||
|
||||
(define (flac-open flac-file* cb-stream-info cb-audio)
|
||||
(let ((flac-file (if (path? flac-file*) (path->string flac-file*) flac-file*)))
|
||||
(if (file-exists? flac-file)
|
||||
(let ((handler (flac-ffi-decoder-handler)))
|
||||
(handler 'new)
|
||||
(handler 'init flac-file)
|
||||
(let ((h (make-flac-handle handler)))
|
||||
(set-flac-handle-cb-stream-info! h cb-stream-info)
|
||||
(set-flac-handle-cb-audio! h cb-audio)
|
||||
h))
|
||||
#f)))
|
||||
|
||||
(define (flac-stream-state handle)
|
||||
((flac-handle-ffi-decoder-handler handle) 'state))
|
||||
|
||||
|
||||
(define kinds (make-hash))
|
||||
(define last-buffer #f)
|
||||
(define last-buf-len #f)
|
||||
|
||||
(define (process-frame handle frame buffer)
|
||||
(let* ((h (flac-ffi-frame-header frame))
|
||||
(cb-audio (flac-handle-cb-audio handle))
|
||||
(ffi (flac-handle-ffi-decoder-handler handle))
|
||||
(type (hash-ref h 'number-type))
|
||||
(channels (hash-ref h 'channels))
|
||||
(block-size (hash-ref h 'blocksize)))
|
||||
(hash-set! h 'duration (flac-duration handle))
|
||||
(let ((sample (hash-ref h 'number)))
|
||||
(hash-set! h 'sample sample))
|
||||
(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
|
||||
)
|
||||
|
||||
(define (process-meta handle meta)
|
||||
(let ((type (FLAC__StreamMetadata-type meta)))
|
||||
(dbg-sound (format " Got metadata type: ~a\n" type))
|
||||
(cond
|
||||
([eq? type 'streaminfo]
|
||||
(let ((mh (flac-ffi-meta meta)))
|
||||
(let ((si (make-flac-stream-info
|
||||
(hash-ref mh 'min-blocksize) (hash-ref mh 'max-blocksize)
|
||||
(hash-ref mh 'min-framesize) (hash-ref mh 'max-framesize)
|
||||
(hash-ref mh 'sample-rate)
|
||||
(hash-ref mh 'channels)
|
||||
(hash-ref mh 'bits-per-sample)
|
||||
(hash-ref mh 'total-samples))))
|
||||
(let ((duration (exact->inexact
|
||||
(/ (hash-ref mh 'total-samples)
|
||||
(hash-ref mh 'sample-rate)))))
|
||||
(hash-set! mh 'duration duration))
|
||||
(set-flac-handle-stream-info! handle si)
|
||||
(let ((cb (flac-handle-cb-stream-info handle)))
|
||||
(when (procedure? cb)
|
||||
(cb mh))))))
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
(define (flac-read handle)
|
||||
(let* ((ffi-handler (flac-handle-ffi-decoder-handler handle))
|
||||
(state (ffi-handler 'state)))
|
||||
(set-flac-handle-stop-reading! handle #f)
|
||||
(set-flac-handle-reading! handle #t)
|
||||
(letrec ((reader (lambda (frame-nr)
|
||||
(if (flac-handle-stop-reading handle)
|
||||
(begin
|
||||
(dbg-sound "handling stop at: ~a" (current-milliseconds))
|
||||
(set-flac-handle-reading! handle #f)
|
||||
'stopped-reading)
|
||||
(let* ((st (ffi-handler 'state)))
|
||||
(ffi-handler 'process-single)
|
||||
(unless (eq? state st)
|
||||
(set! state st)
|
||||
(dbg-sound "Now in state ~a (frame-nr = ~a) (int-state = ~a)"
|
||||
st frame-nr (ffi-handler 'int-state))
|
||||
)
|
||||
(when (ffi-handler 'has-errno?)
|
||||
(err-sound "Error in stream: ~a" (ffi-handler 'errno))
|
||||
)
|
||||
(when (ffi-handler 'has-meta-data?)
|
||||
(ffi-handler 'process-meta-data
|
||||
(lambda (meta) (process-meta handle meta)))
|
||||
)
|
||||
(when (ffi-handler 'has-write-data?)
|
||||
(ffi-handler 'process-write-data
|
||||
(lambda (frame buffer)
|
||||
(process-frame handle frame buffer)))
|
||||
)
|
||||
(if (eq? st 'end-of-stream)
|
||||
(begin
|
||||
(set-flac-handle-reading! handle #f)
|
||||
st)
|
||||
(reader (+ frame-nr 1))))))
|
||||
))
|
||||
(reader 0)
|
||||
; done reading, delete flac encoder
|
||||
(ffi-handler 'delete)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
(define (flac-read-meta handle)
|
||||
(let* ((ffi-handler (flac-handle-ffi-decoder-handler handle))
|
||||
(state (ffi-handler 'state)))
|
||||
(while (not (or (eq? state 'read-metadata)
|
||||
(eq? state 'end-of-stream)
|
||||
(eq? state 'aborted)
|
||||
(eq? state 'memory-allocation-error)
|
||||
(eq? state 'uninitialized)))
|
||||
(ffi-handler 'process-single)
|
||||
(set! state (ffi-handler 'state))
|
||||
state)
|
||||
(if (eq? state 'read-metadata)
|
||||
(begin
|
||||
(ffi-handler 'process-meta-data
|
||||
(lambda (meta) (process-meta handle meta)))
|
||||
(flac-handle-stream-info handle))
|
||||
#f)))
|
||||
|
||||
(define (flac-seek handle percentage)
|
||||
(dbg-sound "seek to percentage ~a" percentage)
|
||||
(let ((ffi-handler (flac-handle-ffi-decoder-handler handle)))
|
||||
(let ((total-samples (flac-total-samples handle)))
|
||||
(unless (eq? total-samples #f)
|
||||
(let ((sample (inexact->exact (round (* (exact->inexact (/ percentage 100.0)) total-samples)))))
|
||||
(ffi-handler 'seek-to-sample sample))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
(define (flac-stop handle)
|
||||
(let ((ct (current-milliseconds)))
|
||||
(dbg-sound "requesting stop at: ~a" ct)
|
||||
(set-flac-handle-stop-reading! handle #t)
|
||||
(while (flac-handle-reading handle)
|
||||
(sleep 0.01))
|
||||
(let ((ct* (current-milliseconds)))
|
||||
(dbg-sound "stop came back at: ~a" ct*)
|
||||
(dbg-sound "flac-stop took: ~a ms" (- ct* ct)))
|
||||
)
|
||||
)
|
||||
|
||||
); end of module
|
||||
Reference in New Issue
Block a user