update
parent
83cb49a158
commit
18455eae10
|
@ -1,6 +1,6 @@
|
|||
! Copyright (C) 2009 Daniel Ehrenberg
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: kernel system destructors accessors byte-arrays math locals io.files io.encodings.binary combinators sequences namespaces ;
|
||||
USING: kernel system destructors accessors byte-arrays math math.functions locals io.files io.encodings.binary combinators sequences namespaces ;
|
||||
QUALIFIED: bitstreams
|
||||
QUALIFIED: io
|
||||
USING: prettyprint ;
|
||||
|
@ -35,9 +35,19 @@ M: flac-stream-reader dispose stream>> dispose ;
|
|||
[ 8 * flac-input-stream get bitstream>> bitstreams:seek ]
|
||||
[ io:seek-relative flac-input-stream get stream>> io:stream-seek ] bi ;
|
||||
|
||||
: flac-read-sint ( n -- n )
|
||||
! TODO: this isn't rightt
|
||||
dup flac-read-uint dup . dup 1 - neg shift swap shift ;
|
||||
:: flac-read-sint ( n -- n )
|
||||
n flac-read-uint :> val
|
||||
val val n 1 - neg shift n shift - ;
|
||||
|
||||
: flac-read-utf8-uint ( -- n )
|
||||
8 flac-read-uint
|
||||
[ dup 0b11000000 >= ] [ 8 flac-read-uint drop 2^ 0xff bitand ] while ;
|
||||
|
||||
: flac-read-rice-sint ( param -- n )
|
||||
0 [ 1 flac-read-uint 0 = ] [ 1 + ] while
|
||||
[ swap shift ] [ flac-read-uint ] bi bitor
|
||||
[ -1 shift ] [ 1 bitand neg ] bi ^ ;
|
||||
|
||||
|
||||
: with-flac-stream-reader* ( flac-bitstream quot -- )
|
||||
flac-input-stream swap with-variable ; inline
|
||||
|
|
|
@ -1,63 +1,19 @@
|
|||
! 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 ;
|
||||
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
|
||||
|
||||
! : unary-code ( q -- bit-array )
|
||||
! on-bits 1 shift integer>bit-array ;
|
||||
!
|
||||
! :: truncated-binary-code ( r m -- bit-array )
|
||||
! m log2 :> b
|
||||
! b 1 + 2^ m - :> cutoffs
|
||||
! r cutoffs <
|
||||
! [ r b <bits> ] [ r cutoffs + b 1 + <bits> ] if
|
||||
! >bit-array ;
|
||||
|
||||
:: rice-encode ( n m -- bit-array )
|
||||
n m / >integer :> q
|
||||
n m mod :> r
|
||||
|
||||
q on-bits 1 shift integer>bit-array :> qcode
|
||||
|
||||
m log2 :> b
|
||||
b 1 + 2^ m - :> cutoffs
|
||||
r cutoffs <
|
||||
[ r b <bits> ] [ r cutoffs + b 1 + <bits> ] if >bit-array :> rcode
|
||||
|
||||
rcode qcode append ;
|
||||
|
||||
|
||||
! : rice-encode ( s k -- bit-array )
|
||||
! [ dup [ 2^ 1 - bitand ] dip <bits> >bit-array ]
|
||||
! [ -1 * shift unary integer>bit-array ] 2bi append ;
|
||||
! s k 2^ 1 - bitand k <bits> >bit-array
|
||||
! s k -1 * shift unary integer>bit-array append ;
|
||||
|
||||
:: inverted-unary ( n -- bit-array )
|
||||
n 2^ integer>bit-array :> coding
|
||||
coding set-bits
|
||||
f n coding set-nth
|
||||
coding ;
|
||||
|
||||
: read-utf8-uint ( -- n )
|
||||
0 [ 1 flac-read-uint 1 = ] [ 1 + ] while
|
||||
dup [ 7 swap - flac-read-uint ] dip
|
||||
<iota> [
|
||||
drop
|
||||
2 flac-read-uint drop
|
||||
6 shift 6 flac-read-uint bitor
|
||||
] each ;
|
||||
|
||||
: decode-block-size ( n -- n )
|
||||
dup
|
||||
{
|
||||
{ [ 0b0000 = ] [ drop reserved-block-size ] }
|
||||
{ [ 0b0001 = ] [ drop 192 ] }
|
||||
{ [ 0b0010 0b0101 between? ] [ 2 - 2^ 567 * ] }
|
||||
{ [ 0b0110 0b0111 between? ] [ ] }
|
||||
{ [ 0b0110 = ] [ drop 8 flac-read-uint 1 + ] }
|
||||
{ [ 0b0111 = ] [ drop 16 flac-read-uint 1 + ] }
|
||||
{ [ 0b1000 0b1111 between? ] [ 8 - 2^ 256 * ] }
|
||||
} cond-case ;
|
||||
|
||||
|
@ -66,11 +22,11 @@ IN: flac.decoder
|
|||
{ 0b000 [ "TODO" ] }
|
||||
{ 0b001 [ 8 ] }
|
||||
{ 0b010 [ 12 ] }
|
||||
{ 0b011 [ "TODO" ] }
|
||||
{ 0b011 [ reserved-sample-size ] }
|
||||
{ 0b100 [ 16 ] }
|
||||
{ 0b101 [ 20 ] }
|
||||
{ 0b110 [ 24 ] }
|
||||
{ 0b111 [ "TODO" ] }
|
||||
{ 0b111 [ reserved-sample-size ] }
|
||||
} case ;
|
||||
|
||||
: decode-sample-rate ( n -- n )
|
||||
|
@ -87,9 +43,9 @@ IN: flac.decoder
|
|||
{ 0b1001 [ 44100 ] }
|
||||
{ 0b1010 [ 48000 ] }
|
||||
{ 0b1011 [ 96000 ] }
|
||||
{ 0b1100 [ 8 flac-read-uint 1000 * ] }
|
||||
{ 0b1101 [ 16 flac-read-uint ] }
|
||||
{ 0b1110 [ 16 flac-read-uint 10 * ] }
|
||||
{ 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 ;
|
||||
|
||||
|
@ -102,62 +58,119 @@ IN: flac.decoder
|
|||
} cond swap
|
||||
<flac-channel-assignment> ;
|
||||
|
||||
: read-flac-subframe-verbatim ( frame-header subframe-header -- verbatim-subframe )
|
||||
[ [ blocksize>> ] [ bits-per-sample>> ] bi ] dip wasted-bits>> - <repetition>
|
||||
[ flac-read-uint ] map
|
||||
flac-subframe-constant boa ;
|
||||
|
||||
: read-flac-subframe-constant ( frame-header subframe-header -- constant-subframe )
|
||||
drop bits-per-sample>> flac-read-uint flac-subframe-constant boa ;
|
||||
[ [ blocksize>> ] [ bits-per-sample>> ] bi ] dip wasted-bits>> - flac-read-uint <repetition> [ ] 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 <array> [
|
||||
! dup .
|
||||
! flac-read-uint :> param
|
||||
! param 0b1111 =
|
||||
! [ 5 flac-read-uint :> numbits samples numbits <array> [ flac-read-uint ] map drop "dicks" . param ]
|
||||
! [ samples param <array> [ 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 <iota>
|
||||
[
|
||||
|
||||
]
|
||||
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-entropy-coding-method-type> ;
|
||||
|
||||
:: 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 <array> [
|
||||
dup .
|
||||
flac-read-uint :> param
|
||||
param 0b1111 =
|
||||
[ 5 flac-read-uint :> numbits samples numbits <array> [ flac-read-uint ] map drop "dicks" . param ]
|
||||
[ samples param <array> [ 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-rice2 ( frame-header subframe-header -- rice residual )
|
||||
2drop flac-entropy-coding-method-partitioned-rice-contents new f ;
|
||||
|
||||
: read-flac-residuals ( frame-header subframe-header -- entropy-coding-method residual )
|
||||
: flac-read-residuals ( frame-header subframe-header -- entropy-coding-method residual )
|
||||
read-residual-coding-method-type
|
||||
[ [ read-residual-partitioned-rice ] [ read-residual-partitioned-rice2 ] if ] keep swap
|
||||
flac-entropy-coding-method boa dup . ;
|
||||
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 )
|
||||
[ bits-per-sample>> ] [ pre-order>> ] bi* swap <repetition> [ flac-read-uint ] map ;
|
||||
! TODO: handle wasted bits...
|
||||
[ bits-per-sample>> ] [ predictor-order>> ] bi* swap <repetition> [ flac-read-uint ] map ;
|
||||
|
||||
: read-flac-subframe-fixed ( frame-header subframe-header -- fixed-subframe )
|
||||
2dup [ read-flac-subframe-warmup-samples ] [ read-flac-residuals ] 2bi*
|
||||
2dup [ read-flac-subframe-warmup-samples ] [ flac-read-residuals ] 2bi*
|
||||
flac-subframe-fixed boa ;
|
||||
|
||||
: decode-flac-subframe-type ( n -- type order )
|
||||
dup
|
||||
: 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 <repetition> [ 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
|
||||
{
|
||||
{ [ 0 = ] [ drop f 0 ] }
|
||||
{ [ 1 = ] [ drop f 1 ] }
|
||||
{ [ 8 12 between? ] [ 8 - 2 ] }
|
||||
! { [ 8 12 between? ] [ -1 shift 7 bitand 2 ] }
|
||||
{ [ 32 63 between? ] [ -1 shift 31 bitand 3 ] } ! TODO: is this right?
|
||||
{ [ 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
|
||||
<flac-subframe-type> swap ;
|
||||
} 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 )
|
||||
1 flac-read-uint 1 = [ invalid-subframe-sync ] when
|
||||
6 flac-read-uint decode-flac-subframe-type
|
||||
1 flac-read-uint
|
||||
read-flac-subframe-sync
|
||||
read-flac-subframe-type
|
||||
read-flac-subframe-wasted-bits
|
||||
flac-subframe-header boa ;
|
||||
|
||||
: read-flac-subframe ( frame-header -- subframe )
|
||||
|
@ -166,7 +179,9 @@ IN: flac.decoder
|
|||
subframe-type>>
|
||||
{
|
||||
{ subframe-type-constant [ read-flac-subframe-constant ] }
|
||||
{ subframe-type-fixed [ read-flac-subframe-fixed ] }
|
||||
{ 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 ;
|
||||
|
@ -174,25 +189,22 @@ IN: flac.decoder
|
|||
: read-flac-subframes ( frame-header -- seq )
|
||||
dup channels>> swap <repetition> [ 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 )
|
||||
14 flac-read-uint drop ! ignore sync
|
||||
1 flac-read-uint drop ! reserved
|
||||
1 flac-read-uint
|
||||
4 flac-read-uint
|
||||
4 flac-read-uint
|
||||
4 flac-read-uint
|
||||
3 flac-read-uint
|
||||
read-flac-sync-frame
|
||||
1 flac-read-uint <flac-frame-blocking-strategy>
|
||||
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
|
||||
read-utf8-uint
|
||||
[
|
||||
{
|
||||
[ <flac-frame-number-type> ]
|
||||
[ decode-block-size ]
|
||||
[ decode-sample-rate ]
|
||||
[ decode-channels ]
|
||||
[ decode-bits-per-sample ]
|
||||
} spread
|
||||
] dip
|
||||
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 ;
|
||||
|
||||
|
|
|
@ -24,10 +24,15 @@ ERROR: not-a-flac-file ;
|
|||
ERROR: sync-code-error ;
|
||||
ERROR: invalid-channel-assignment ;
|
||||
ERROR: reserved-block-size ;
|
||||
ERROR: reserved-sample-size ;
|
||||
ERROR: invalid-sample-rate ;
|
||||
ERROR: reserved-subframe-type ;
|
||||
ERROR: invalid-subframe-sync ;
|
||||
ERROR: reserved-residual-coding-type ;
|
||||
ERROR: invalid-blocksize/rice-partitions
|
||||
|
||||
ENUM: flac-frame-blocking-strategy
|
||||
fixed-blocksize variable-blocksize ;
|
||||
|
||||
ENUM: flac-frame-number-type
|
||||
frame-number-type-frame
|
||||
|
@ -47,7 +52,7 @@ ENUM: flac-channel-assignment
|
|||
channels-mid ;
|
||||
|
||||
TUPLE: flac-frame-header
|
||||
{ number-type maybe{ frame-number-type-frame frame-number-type-sample } }
|
||||
{ blocking-strategy maybe{ fixed-blocksize variable-blocksize } }
|
||||
{ blocksize integer }
|
||||
{ sample-rate integer }
|
||||
{ channels integer }
|
||||
|
@ -79,8 +84,7 @@ ENUM: flac-entropy-coding-method-type
|
|||
|
||||
TUPLE: flac-entropy-coding-method-partitioned-rice-contents
|
||||
{ parameters sequence }
|
||||
{ raw-bits integer }
|
||||
{ capacity-by-order integer } ;
|
||||
{ raw-bits sequence } ;
|
||||
|
||||
TUPLE: flac-entropy-coding-method-partitioned-rice
|
||||
{ order integer }
|
||||
|
@ -92,10 +96,10 @@ TUPLE: flac-entropy-coding-method
|
|||
{ data flac-entropy-coding-method-partitioned-rice } ;
|
||||
|
||||
TUPLE: flac-subframe-constant
|
||||
{ value integer } ;
|
||||
{ data sequence } ;
|
||||
|
||||
TUPLE: flac-subframe-verbatim
|
||||
{ data byte-array } ;
|
||||
{ data sequence } ;
|
||||
|
||||
TUPLE: flac-subframe-fixed
|
||||
{ warmup sequence }
|
||||
|
@ -107,8 +111,8 @@ TUPLE: flac-subframe-lpc
|
|||
entropy-coding-partitioned-rice2 } }
|
||||
{ qlp-coeff-precision integer }
|
||||
{ quantization-level integer }
|
||||
{ qlp-coeff integer }
|
||||
{ warmup integer }
|
||||
{ qlp-coeff sequence }
|
||||
{ warmup sequence }
|
||||
residual ;
|
||||
|
||||
TUPLE: flac-subframe-header
|
||||
|
@ -116,7 +120,7 @@ TUPLE: flac-subframe-header
|
|||
subframe-type-verbatim
|
||||
subframe-type-fixed
|
||||
subframe-type-lpc } }
|
||||
{ pre-order maybe{ integer } }
|
||||
{ predictor-order maybe{ integer } }
|
||||
{ wasted-bits integer } ;
|
||||
|
||||
TUPLE: flac-subframe
|
||||
|
|
Loading…
Reference in New Issue