not quite right but close

main
Steve Ayerhart 2022-08-12 01:28:11 -04:00
parent 9965f317b1
commit f2a62a3990
No known key found for this signature in database
GPG Key ID: 4CB33EB9BB156C97
4 changed files with 194 additions and 88 deletions

View File

@ -0,0 +1,88 @@
(define-module (flac)
#:use-module (flac reader)
#:use-module (flac decoder)
#:use-module (flac metadata)
#:use-module (flac format)
#:use-module (bytestructures guile)
#:use-module (rnrs bytevectors)
#:use-module (ice-9 binary-ports)
#:export (decode-flac-file))
(define header-struct
(bs:struct `((filetype ,(bs:string 4 'utf8))
(filesize ,uint32)
(filetype-header ,(bs:string 4 'utf8))
(format-chunk-marker ,(bs:string 4 'utf8))
(format-chunk-length ,uint32)
(format-type ,uint16)
(num-channels ,uint16)
(sample-freq ,uint32)
(bytes/sec ,uint32)
(block-alignment ,uint16)
(bits-per-sample ,uint16)
(data-chunk-header ,(bs:string 4 'utf8))
(data-chunk-size ,uint32))))
(define (write-frame frame channels)
(let* ((header (frame-header frame))
(total-bytes (floor-quotient (frame-header-bits-per-sample header) 8))
(addend (if (= 8 (frame-header-bits-per-sample header)) 128 0))
(data-bv (make-bytevector 4)))
(for-each
(lambda (block)
(for-each
(lambda (channel)
(bytevector-s32-set! data-bv
0
(+ addend (list-ref (list-ref (frame-samples frame) channel) block))
(endianness little))
(put-bytevector (current-output-port) data-bv))
(iota channels)))
(iota (frame-header-blocksize header)))))
(define (decode-flac-file infile outfile)
(with-input-from-file infile
(λ ()
(with-flac-input-port (current-input-port)
(λ ()
(let* ((stream-info (flac-metadata-stream-info (read-flac-metadata)))
(sample-data-length (* (stream-info-samples stream-info)
(stream-info-channels stream-info)
(floor-quotient (stream-info-bits-per-sample stream-info) 8)))
(wav-header (bytestructure
header-struct
`((filetype "RIFF")
(filesize ,(+ 36 (* (stream-info-samples stream-info)
(stream-info-channels stream-info)
(floor-quotient (stream-info-bits-per-sample stream-info) 8))))
(filetype-header "WAVE")
(format-chunk-marker "fmt ")
(format-chunk-length 16)
(format-type #x0001)
(num-channels ,(stream-info-channels stream-info))
(sample-freq ,(stream-info-sample-rate stream-info))
(bytes/sec ,(* (stream-info-sample-rate stream-info)
(stream-info-channels stream-info)
(floor-quotient (stream-info-bits-per-sample stream-info) 8)))
(block-alignment ,(* (stream-info-channels stream-info)
(floor-quotient (stream-info-bits-per-sample stream-info) 8)))
(bits-per-sample ,(stream-info-bits-per-sample stream-info))
(data-chunk-header "data")
(data-chunk-size ,(* (stream-info-samples stream-info)
(stream-info-channels stream-info)
(floor-quotient (stream-info-bits-per-sample stream-info) 8)))))))
(format #t "SAMPLES: ~a\n" (stream-info-samples stream-info))
(with-output-to-file outfile
(lambda ()
(put-bytevector (current-output-port) (bytestructure-unwrap wav-header))
(let frame-loop ((frame-number 0)
(frame (read-flac-frame stream-info)))
(if (= (stream-info-samples stream-info) frame-number)
#t
(begin
(write-frame frame (stream-info-channels stream-info))
(frame-loop (+ 1 frame-number)
(read-flac-frame stream-info))))))
#:binary #t)))))))

View File

@ -9,7 +9,8 @@
#:use-module (rnrs arithmetic bitwise)
#:use-module (ice-9 match)
#:use-module (ice-9 receive))
#:use-module (ice-9 receive)
#:export (read-flac-frame))
(define (read/assert-frame-sync-code)
(unless (= #b111111111111100 (flac-read-uint 15))
@ -25,50 +26,50 @@
(enum-lookup
flac-channel-assignment-type
(cond
[(between? raw #b0000 #b0111) 0]
[(= raw #b1000) 1]
[(= raw #b1001) 2]
[(= raw #b1010) 3]
[else #f])))
((between? raw #b0000 #b0111) 0)
((= raw #b1000) 1)
((= raw #b1001) 2)
((= raw #b1010) 3)
(else #f))))
(define (decode-block-size raw)
(cond
[(= raw #b0000) 'reserved]
[(= raw #b0001) 192]
[(between? raw #b0010 #b0101) (* 576 (expt 2 (- raw 2)))]
[(= raw #b0110) (+ 1 (flac-read-uint 8))]
[(= raw #b0111) (+ 1 (flac-read-uint 16))]
[(between? raw #b1000 #b1111) (* 256 (expt 2 (- raw 8)))]))
((= raw #b0000) 'reserved)
((= raw #b0001) 192)
((between? raw #b0010 #b0101) (* 576 (expt 2 (- raw 2))))
((= raw #b0110) (+ 1 (flac-read-uint 8)))
((= raw #b0111) (+ 1 (flac-read-uint 16)))
((between? raw #b1000 #b1111) (* 256 (expt 2 (- raw 8))))))
(define (decode-sample-rate stream-info raw)
(case raw
[(#b0000) (stream-info-sample-rate stream-info)]
[(#b0001) 88200]
[(#b0010) 17640]
[(#b0011) 19200]
[(#b0100) 8000]
[(#b0101) 16000]
[(#b0110) 22050]
[(#b0111) 24000]
[(#b1000) 32000]
[(#b1001) 44100]
[(#b1010) 48000]
[(#b1011) 96000]
[(#b1100) (* 1000 (flac-read-uint 8))] ; sample rate in kHz
[(#b1101) (flac-read-uint 16)] ; sample rate in Hz
[(#b1110) (* 10 (flac-read-uint 16))] ; sample rate in tens of Hz
[(#b1111) 'invalid]))
((#b0000) (stream-info-sample-rate stream-info))
((#b0001) 88200)
((#b0010) 17640)
((#b0011) 19200)
((#b0100) 8000)
((#b0101) 16000)
((#b0110) 22050)
((#b0111) 24000)
((#b1000) 32000)
((#b1001) 44100)
((#b1010) 48000)
((#b1011) 96000)
((#b1100) (* 1000 (flac-read-uint 8)) ; sample rate in kHz
((#b1101) (flac-read-uint 16)) ; sample rate in Hz
((#b1110) (* 10 (flac-read-uint 16))) ; sample rate in tens of Hz
((#b1111) 'invalid))))
(define (decode-bits-per-sample stream-info raw)
(case raw
[(#b000) (stream-info-bits-per-sample stream-info)]
[(#b001) 8]
[(#b010) 12]
[(#b011) 'reserved]
[(#b100) 16]
[(#b101) 20]
[(#b110) 24]
[(#b111) 'reserved]))
((#b000) (stream-info-bits-per-sample stream-info))
((#b001) 8)
((#b010) 12)
((#b011) 'reserved)
((#b100) 16)
((#b101) 20)
((#b110) 24)
((#b111) 'reserved)))
(define (read/assert-subframe-sync)
(when (= 1 (flac-read-uint 1))
@ -92,12 +93,12 @@
(define (read-subframe-constant blocksize sample-depth wasted-bits)
(let ((subframe (%make-subframe-constant (make-list blocksize (bitwise-arithmetic-shift (flac-read-sint sample-depth) wasted-bits)))))
(list subframe (subframe-constant-value subframe))))
(values subframe (subframe-constant-value subframe))))
(define (read-subframe-verbatim blocksize sample-depth wasted-bits)
(let ((subframe (%make-subframe-verbatim
(list-ec (: b blocksize) (bitwise-arithmetic-shift (flac-read-sint sample-depth) wasted-bits)))))
(list subframe (subframe-verbatim-value subframe))))
(values subframe (subframe-verbatim-value subframe))))
(define (read-entropy-coding-method-info)
(values (case (flac-read-uint 2) [(#b00) 'rice] [(#b01) 'rice2]) (flac-read-uint 4)))
@ -144,7 +145,7 @@
(let ((warmup (list-ec (: o predictor-order) (flac-read-sint sample-depth)))
(fixed-coefficients '(() (1) (2 -1) (3 -3 1) (4 -6 4 -1))))
(let-values (((entropy-coding-method residual) (read-residual-partiioned-rice blocksize predictor-order)))
(list
(values
(%make-subframe-fixed entropy-coding-method predictor-order warmup residual)
(restore-linear-prediction warmup residual (list-ref fixed-coefficients predictor-order) predictor-order 0)))))
@ -154,7 +155,7 @@
(shift (flac-read-sint 5))
(coefs (reverse (list-ec (: o lpc-order) (flac-read-sint precision)))))
(let-values (((entropy-coding-method residual) (read-residual-partiioned-rice blocksize lpc-order)))
(list
(values
(%make-subframe-lpc entropy-coding-method lpc-order precision shift coefs warmup residual)
(restore-linear-prediction warmup residual coefs lpc-order shift)))))
@ -182,12 +183,12 @@
;;; 01xxxx reserved
;;; 1xxxxx lpc xxxxx = order - 1
(define (read-subframe-type)
(let ([raw (flac-read-uint 6)])
(let ((raw (flac-read-uint 6)))
(cond
[(= raw #b000000) (values #f 'constant)]
[(= raw #b000001) (values #f 'verbatim)]
[(between? raw #b001000 #b001100) (values (bit-extract raw 0 3) 'fixed)]
[(between? raw #b100000 #b111111) (values (+ 1 (bit-extract raw 0 5)) 'lpc)]
((= raw #b000000) (values #f 'constant))
((= raw #b000001) (values #f 'verbatim))
((between? raw #b001000 #b001100) (values (bit-extract raw 0 3) 'fixed))
((between? raw #b100000 #b111111) (values (+ 1 (bit-extract raw 0 5)) 'lpc))
(else (values #f #f)))))
(define (read-subframe-header)
@ -197,45 +198,60 @@
(%make-subframe-header type order (read-subframe-wasted-bits))))
(define (read-subframe frame-header channel)
(let* ([subframe-header (read-subframe-header)]
[wasted-bits (subframe-header-wasted-bits subframe-header)]
[predictor-order (subframe-header-predictor-order subframe-header)]
[sample-depth (calculate-sample-depth
(let* ((subframe-header (read-subframe-header))
(wasted-bits (subframe-header-wasted-bits subframe-header))
(predictor-order (subframe-header-predictor-order subframe-header))
(sample-depth (calculate-sample-depth
(frame-header-bits-per-sample frame-header)
wasted-bits
(frame-header-channel-assignment frame-header)
channel)]
[blocksize (frame-header-blocksize frame-header)])
(%make-subframe
subframe-header
(match (subframe-header-subframe-type subframe-header)
('constant (read-subframe-constant blocksize sample-depth wasted-bits))
('verbatim (read-subframe-verbatim blocksize sample-depth wasted-bits))
('fixed (read-subframe-fixed predictor-order blocksize sample-depth))
('lpc (read-subframe-lpc predictor-order blocksize sample-depth))))))
channel))
(blocksize (frame-header-blocksize frame-header)))
(let-values (((subframe samples)
(match (subframe-header-subframe-type subframe-header)
('constant (read-subframe-constant blocksize sample-depth wasted-bits))
('verbatim (read-subframe-verbatim blocksize sample-depth wasted-bits))
('fixed (read-subframe-fixed predictor-order blocksize sample-depth))
('lpc (read-subframe-lpc predictor-order blocksize sample-depth)))))
(values
(%make-subframe subframe-header subframe)
samples))))
(define (read-subframes stream-info frame-header)
(let* ([channels (stream-info-channels stream-info)]
[subframes (map
(λ (header channel)
(read-subframe header channel))
(make-list channels frame-header)
(iota channels))])
(align-to-byte)
subframes))
(let ((channels (stream-info-channels stream-info)))
(let subframe-loop ((channel 0)
(subframes '())
(samples '()))
(if (>= channel channels)
(begin
(align-to-byte)
(values subframes samples))
(let-values (((subframe subframe-samples)
(read-subframe frame-header channel)))
(subframe-loop (+ 1 channel)
(cons subframe subframes)
(cons subframe-samples samples)))))))
; (subframes (map
; (λ (header channel)
; (read-subframe header channel))
; (make-list channels frame-header)
; (iota channels))))
; (align-to-byte)
; subframes))
(define-public (read-frame-header stream-info)
(read/assert-frame-sync-code)
(let* ([blocking-strategy (decode-blocking-strategy (flac-read-uint 1))]
[raw-blocksize (flac-read-uint 4)]
[raw-sample-rate (flac-read-uint 4)]
[channel-assignment (decode-channel-assignment (flac-read-uint 4))]
[bits-per-sample (decode-bits-per-sample stream-info (flac-read-uint 3))]
[ignore-reserved (flac-read-uint 1)]
[frame/sample-number (flac-read-coded-number)]
[blocksize (decode-block-size raw-blocksize)]
[sample-rate (decode-sample-rate stream-info raw-sample-rate)]
[crc (flac-read-uint 8)])
(let* ((blocking-strategy (decode-blocking-strategy (flac-read-uint 1)))
(raw-blocksize (flac-read-uint 4))
(raw-sample-rate (flac-read-uint 4))
(channel-assignment (decode-channel-assignment (flac-read-uint 4)))
(bits-per-sample (decode-bits-per-sample stream-info (flac-read-uint 3)))
(ignore-reserved (flac-read-uint 1))
(frame/sample-number (flac-read-coded-number))
(blocksize (decode-block-size raw-blocksize))
(sample-rate (decode-sample-rate stream-info raw-sample-rate))
(crc (flac-read-uint 8)))
(make-frame-header
blocking-strategy
blocksize
@ -249,8 +265,8 @@
(define (read-frame-footer)
(flac-read-uint 16))
(define-public (read-flac-frame stream-info)
(let* ([header (read-frame-header stream-info)]
[subframes (read-subframes stream-info header)]
[footer (read-frame-footer)])
(%make-frame header subframes footer)))
(define (read-flac-frame stream-info)
(let ((header (read-frame-header stream-info)))
(let-values (((subframes samples) (read-subframes stream-info header)))
(let ((footer (read-frame-footer)))
(%make-frame header subframes footer samples)))))

View File

@ -19,7 +19,8 @@
frame-header-frame/sample-number frame-header-crc
%make-subframe
subframe-header subframe-data
subframe?
subframe-header subframe-data subframe-samples
%make-subframe-header
subframe-header-subframe-type subframe-header-predictor-order subframe-header-wasted-bits
@ -28,7 +29,7 @@
frame-footer-crc
%make-frame
frame-header frame-subframes frame-footer
frame-header frame-subframes frame-footer frame-samples
%make-subframe-constant
subframe-constant-value
@ -48,7 +49,6 @@
entropy-coding-method-partitioned-rice-contents-parameters
entropy-coding-method-partitioned-rice-contents-raw-bits
entropy-coding-method-partitioned-rice-contents?
entropy-codi
%make-subframe-fixed
subframe-fixed-entropy-coding-method
@ -62,7 +62,7 @@
metadata-block-header-length
make-metadata-padding
make-metadata-stream-info metadata-stream-info?
make-metadata-stream-info metadata-stream-info?
stream-info-min-block-size stream-info-max-block-size
stream-info-min-frame-size stream-info-max-frame-size
stream-info-sample-rate stream-info-channels
@ -120,6 +120,7 @@ make-metadata-stream-info metadata-stream-info?
(header subframe-header)
(data subframe-data))
(define-record-type <subframe-lpc>
(%make-subframe-lpc entropy-coding-method order qlp-coefficient-precision quantization-level qlp-coefficients warmup residual)
subframe-lpc?
@ -186,11 +187,12 @@ make-metadata-stream-info metadata-stream-info?
(crc frame-footer-crc))
(define-record-type <frame>
(%make-frame header subframes footer)
(%make-frame header subframes footer samples)
frame?
(header frame-header)
(subframes frame-subframes)
(footer frame-footer))
(footer frame-footer)
(samples frame-samples))
; metadata

View File

@ -8,7 +8,7 @@
#:use-module (rnrs bytevectors)
#:use-module (srfi srfi-1)
#:export (flac-metadata flac-file-metadata))
#:export (read-flac-metadata flac-metadata flac-file-metadata))
(define (read-metadata-block-header)
(make-metadata-block-header