! Copyright (C) 2020 . ! See http://factorcode.org/license.txt for BSD license. USING: math io.encodings.binary kernel io io.files locals endian bit-arrays math.intervals combinators combinators.extras math.order math.bits sequences namespaces accessors byte-arrays math.bitwise arrays generalizations ; USING: prettyprint ; USING: flac.bitstream flac.metadata flac.format ; IN: flac.decoder : decode-block-size ( n -- n ) dup { { [ 0b0000 = ] [ drop reserved-block-size ] } { [ 0b0001 = ] [ drop 192 ] } { [ 0b0010 0b0101 between? ] [ 2 - 2^ 567 * ] } { [ 0b0110 = ] [ drop 8 flac-read-uint 1 + ] } { [ 0b0111 = ] [ drop 16 flac-read-uint 1 + ] } { [ 0b1000 0b1111 between? ] [ 8 - 2^ 256 * ] } } cond-case ; : decode-bits-per-sample ( n -- n ) { { 0b000 [ "TODO" ] } { 0b001 [ 8 ] } { 0b010 [ 12 ] } { 0b011 [ reserved-sample-size ] } { 0b100 [ 16 ] } { 0b101 [ 20 ] } { 0b110 [ 24 ] } { 0b111 [ reserved-sample-size ] } } case ; : decode-sample-rate ( n -- n ) { { 0b0000 [ "TODO" ] } { 0b0001 [ 88200 ] } { 0b0010 [ 17640 ] } { 0b0011 [ 19200 ] } { 0b0100 [ 8000 ] } { 0b0101 [ 16000 ] } { 0b0110 [ 22050 ] } { 0b0111 [ 24000 ] } { 0b1000 [ 32000 ] } { 0b1001 [ 44100 ] } { 0b1010 [ 48000 ] } { 0b1011 [ 96000 ] } { 0b1100 [ 8 flac-read-uint 1000 * ] } ! sample rate in kHz { 0b1101 [ 16 flac-read-uint ] } ! sample rate in Hz { 0b1110 [ 16 flac-read-uint 10 * ] } ! sample rate in tens of Hz { 0b1111 [ invalid-sample-rate ] } } case ; : decode-channels ( n -- channels channel-assignment ) dup { { [ dup 0b0000 0b0111 between? ] [ 1 + ] } { [ 0b1000 0b1010 between? ] [ 2 ] } [ invalid-channel-assignment ] } cond swap ; : read-flac-subframe-verbatim ( frame-header subframe-header -- verbatim-subframe ) [ [ blocksize>> ] [ bits-per-sample>> ] bi ] dip wasted-bits>> - [ flac-read-uint ] map flac-subframe-constant boa ; : read-flac-subframe-constant ( frame-header subframe-header -- constant-subframe ) [ [ blocksize>> ] [ bits-per-sample>> ] bi ] dip wasted-bits>> - flac-read-uint [ ] map ; ! :: read-residual-partitioned-rice ( frame-header subframe-header -- rice residual ) ! 4 flac-read-uint :> partition-order ! partition-order . ! frame-header blocksize>> -1 partition-order * shift :> samples ! samples . ! 1 partition-order shift 4 [ ! dup . ! flac-read-uint :> param ! param 0b1111 = ! [ 5 flac-read-uint :> numbits samples numbits [ flac-read-uint ] map drop "dicks" . param ] ! [ samples param [ flac-read-uint ] map first . "balls" . param dup . ] if ! ] map :> parameters ! parameters . ! partition-order ! flac-entropy-coding-method-partitioned-rice-contents new ! flac-entropy-coding-method-partitioned-rice boa parameters ; :: read-residual-partitioned-rice ( frame-header subframe-header -- rice residual ) frame-header blocksize>> :> blocksize 4 flac-read-uint :> partition-order partition-order 2^ :> partitions blocksize mod partitions 0 = [ invalid-blocksize/rice-partitions ] unless partitions [ ] 2drop flac-entropy-coding-method-partitioned-rice-contents new f ; : read-residual-partitioned-rice2 ( frame-header subframe-header -- rice residual ) 2drop flac-entropy-coding-method-partitioned-rice-contents new f ; : read-residual-coding-method-type ( -- coding-method ) 2 flac-read-uint dup 2 > [ reserved-residual-coding-type ] when ; : flac-read-residuals ( frame-header subframe-header -- entropy-coding-method residual ) read-residual-coding-method-type dup { { entropy-coding-partitioned-rice [ read-residual-partitioned-rice ] } { entropy-coding-partitioned-rice2 [ read-residual-partitioned-rice2 ] } [ reserved-residual-coding-type ] } case flac-entropy-coding-method boa ; : read-flac-subframe-warmup-samples ( frame-header subframe-header -- seq ) ! TODO: handle wasted bits... [ bits-per-sample>> ] [ predictor-order>> ] bi* swap [ flac-read-uint ] map ; : read-flac-subframe-fixed ( frame-header subframe-header -- fixed-subframe ) 2dup [ read-flac-subframe-warmup-samples ] [ flac-read-residuals ] 2bi* flac-subframe-fixed boa ; : read-flac-subframe-qlp-coeff-precision ( -- precision ) 4 flac-read-uint 1 + ; : read-flac-qlp-shift ( -- quantization-level ) 5 flac-read-uint ; : read-flac-qlp-coeff ( subframe-header coeff-precision -- seq ) [ predictor-order>> ] dip [ flac-read-uint ] map ; : read-flac-subframe-lpc ( frame-header subframe-header -- lpc-subframe ) 2drop 1 ; ! : read-flac-subframe-lpc ( frame-header subframe-header -- lpc-subframe ) ! [ read-flac-subframe-warmup-samples ] 2keep ! [ ! nip ! read-flac-subframe-qlp-coeff-precision dup ! read-flac-qlp-shift ! [ swap read-flac-qlp-coeff ] dip ! ] ! [ flac-read-residuals ] 2tri ! flac-subframe boa ; : read-flac-subframe-sync ( -- ) 1 flac-read-uint 1 = [ invalid-subframe-sync ] when ; ! 000000 constant ! 000001 verbatim ! 00001x reserved ! 0001xx reserved ! 001xxx if xxx <= 4 fixed, xxx = order ; else reserved ! 01xxxx reserved ! 1xxxxx lpc : read-flac-subframe-type ( -- subframe-type order ) 6 flac-read-uint dup { { [ 0b0 = ] [ drop f subframe-type-constant ] } { [ 0b1 = ] [ drop f subframe-type-verbatim ] } { [ 0b1000 0b1100 between? ] [ 3 clear-bit subframe-type-fixed ] } { [ 0b100000 0b111111 between? ] [ 5 clear-bit 1 + subframe-type-lpc ] } [ drop reserved-subframe-type ] } cond-case swap ; : read-flac-subframe-wasted-bits ( -- k ) 1 flac-read-uint 1 = [ [ flac-read-uint dup 0 = ] [ 1 + ] while ] [ 0 ] if* ; : read-flac-subframe-header ( -- subframe-header ) read-flac-subframe-sync read-flac-subframe-type read-flac-subframe-wasted-bits flac-subframe-header boa ; : read-flac-subframe ( frame-header -- subframe ) read-flac-subframe-header dup dup [ subframe-type>> { { subframe-type-constant [ read-flac-subframe-constant ] } { subframe-type-verbatim [ read-flac-subframe-verbatim ] } { subframe-type-fixed [ read-flac-subframe-fixed ] } { subframe-type-lpc [ read-flac-subframe-lpc ] } } case ] dip swap flac-subframe boa ; : read-flac-subframes ( frame-header -- seq ) dup channels>> swap [ read-flac-subframe ] map ; : read-flac-sync-frame ( -- ) 14 flac-read-uint drop ! sync 1 flac-read-uint drop ; ! TODO: handle unparsable frame : read-flac-frame-header ( -- frame-header ) read-flac-sync-frame 1 flac-read-uint 4 flac-read-uint ! blocksize code 4 flac-read-uint ! sample rate code 4 flac-read-uint decode-channels 3 flac-read-uint decode-bits-per-sample 1 flac-read-uint drop ! ignore magic sync for now flac-read-utf8-uint ! decoding blocksize/samplerate potentially reads from end of header [ decode-block-size ] 5 ndip [ decode-sample-rate ] 4dip 8 flac-read-uint flac-frame-header boa ; : read-flac-frame-footer ( -- frame-footer ) 16 flac-read-uint flac-frame-footer boa ; : read-flac-frame ( -- frame ) read-flac-frame-header dup read-flac-subframes read-flac-frame-footer flac-frame boa ; : read-flac-file ( filename -- flac-stream ) [ read-flac-metadata drop read-flac-frame drop read-flac-frame drop read-flac-frame drop read-flac-frame ] with-flac-file-reader ;