Audio Encoder laag.
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
(module flac-encoder racket/base
|
||||
|
||||
(require "libflac-ffi.rkt"
|
||||
"flac-definitions.rkt")
|
||||
|
||||
(provide flac-encoder-available?
|
||||
flac-encoder-default-settings
|
||||
flac-encoder-prepare-settings
|
||||
flac-encoder-open
|
||||
flac-encoder-write
|
||||
flac-encoder-finish)
|
||||
|
||||
(define (flac-encoder-available?) #t)
|
||||
|
||||
(define (copy-hash h)
|
||||
(let ((out (make-hash)))
|
||||
(for-each (lambda (k) (hash-set! out k (hash-ref h k))) (hash-keys h))
|
||||
out))
|
||||
|
||||
(define (hash-ref/default h k default)
|
||||
(if (hash-has-key? h k) (hash-ref h k) default))
|
||||
|
||||
(define (hash-merge base override)
|
||||
(let ((out (copy-hash base)))
|
||||
(when (hash? override)
|
||||
(for-each (lambda (k) (hash-set! out k (hash-ref override k))) (hash-keys override)))
|
||||
out))
|
||||
|
||||
(define (flac-encoder-default-settings)
|
||||
(make-hash '((compression-level . 5)
|
||||
(verify? . #f)
|
||||
(blocksize . 0))))
|
||||
|
||||
(define (safe-flac-bits bits)
|
||||
(cond [(and (integer? bits) (or (= bits 8) (= bits 12) (= bits 16) (= bits 20) (= bits 24))) bits]
|
||||
[(and (integer? bits) (< bits 16)) 16]
|
||||
[else 24]))
|
||||
|
||||
(define (flac-encoder-prepare-settings settings format)
|
||||
(let* ((base (flac-encoder-default-settings))
|
||||
(h (hash-merge base settings))
|
||||
;; In encoder settings, 'sample-rate means the requested output rate.
|
||||
;; 'target-sample-rate is accepted as an explicit alias for readability.
|
||||
(rate (hash-ref/default h 'target-sample-rate
|
||||
(hash-ref/default h 'sample-rate (hash-ref format 'sample-rate))))
|
||||
(channels (hash-ref/default h 'target-channels
|
||||
(hash-ref/default h 'channels (hash-ref format 'channels))))
|
||||
(bits0 (hash-ref/default h 'target-bits-per-sample
|
||||
(hash-ref/default h 'bits-per-sample
|
||||
(hash-ref/default format 'bits-per-sample 24))))
|
||||
(bits (safe-flac-bits bits0))
|
||||
(total (hash-ref/default h 'total-samples (hash-ref/default format 'total-samples #f))))
|
||||
(hash-set! h 'sample-rate rate)
|
||||
(hash-set! h 'channels channels)
|
||||
(hash-set! h 'bits-per-sample bits)
|
||||
(when (hash-has-key? h 'target-sample-rate) (hash-remove! h 'target-sample-rate))
|
||||
(when (hash-has-key? h 'target-channels) (hash-remove! h 'target-channels))
|
||||
(when (hash-has-key? h 'target-bits-per-sample) (hash-remove! h 'target-bits-per-sample))
|
||||
(when (and total (integer? total) (>= total 0)) (hash-set! h 'total-samples total))
|
||||
(unless (hash-has-key? h 'streamable-subset?) (hash-set! h 'streamable-subset? (<= bits 24)))
|
||||
h))
|
||||
|
||||
(define (flac-encoder-open output-file settings format)
|
||||
(let* ((file (if (path? output-file) (path->string output-file) output-file))
|
||||
(resolved (flac-encoder-prepare-settings settings format))
|
||||
(handler (flac-ffi-encoder-handler)))
|
||||
(handler 'new)
|
||||
(handler 'configure resolved)
|
||||
(handler 'init file)
|
||||
(make-flac-encoder-handle handler resolved format file)))
|
||||
|
||||
(define (flac-encoder-write handle buf-info buffer buf-len)
|
||||
((flac-encoder-handle-ffi-encoder-handler handle) 'write buffer buf-len buf-info))
|
||||
|
||||
(define (flac-encoder-finish handle)
|
||||
(let ((handler (flac-encoder-handle-ffi-encoder-handler handle)))
|
||||
(dynamic-wind
|
||||
void
|
||||
(lambda () (handler 'finish))
|
||||
(lambda () (handler 'delete)))))
|
||||
|
||||
) ; end of module
|
||||
Reference in New Issue
Block a user