2022-08-20 22:19:05 -04:00
|
|
|
USING: kernel math math.order combinators combinators.extras generalizations math.bitwise accessors sequences arrays ;
|
2022-07-06 18:13:20 -04:00
|
|
|
USING: flac.format flac.stream ;
|
2020-12-17 22:11:31 -05:00
|
|
|
USING: prettyprint ;
|
|
|
|
|
|
|
|
IN: flac.decoder
|
|
|
|
|
2022-07-06 18:13:20 -04:00
|
|
|
SYMBOL: current-flac-output
|
|
|
|
|
2020-12-17 22:11:31 -05:00
|
|
|
: decode-block-size ( n -- n )
|
|
|
|
dup
|
|
|
|
{
|
2022-07-06 18:13:20 -04:00
|
|
|
{ [ 0b0000 = ] [ drop reserved-block-size ] }
|
|
|
|
{ [ 0b0001 = ] [ drop 192 ] }
|
2020-12-17 22:11:31 -05:00
|
|
|
{ [ 0b0010 0b0101 between? ] [ 2 - 2^ 567 * ] }
|
2023-06-16 21:35:43 -04:00
|
|
|
{ [ 0b0110 = ] [ drop 8 flac-read-uint 1 + ] }
|
|
|
|
{ [ 0b0111 = ] [ drop 16 flac-read-uint 1 + ] }
|
2020-12-17 22:11:31 -05:00
|
|
|
{ [ 0b1000 0b1111 between? ] [ 8 - 2^ 256 * ] }
|
|
|
|
} cond-case ;
|
|
|
|
|
|
|
|
: decode-sample-rate ( n -- n )
|
|
|
|
{
|
2022-07-06 18:13:20 -04:00
|
|
|
{ 0b0000 [ "TODO: GET FROM STREAMINFO" ] }
|
2020-12-17 22:11:31 -05:00
|
|
|
{ 0b0001 [ 88200 ] }
|
|
|
|
{ 0b0010 [ 17640 ] }
|
|
|
|
{ 0b0011 [ 19200 ] }
|
|
|
|
{ 0b0100 [ 8000 ] }
|
|
|
|
{ 0b0101 [ 16000 ] }
|
|
|
|
{ 0b0110 [ 22050 ] }
|
|
|
|
{ 0b0111 [ 24000 ] }
|
|
|
|
{ 0b1000 [ 32000 ] }
|
|
|
|
{ 0b1001 [ 44100 ] }
|
|
|
|
{ 0b1010 [ 48000 ] }
|
|
|
|
{ 0b1011 [ 96000 ] }
|
2023-06-16 21:35:43 -04:00
|
|
|
{ 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
|
2020-12-17 22:11:31 -05:00
|
|
|
{ 0b1111 [ invalid-sample-rate ] }
|
|
|
|
} case ;
|
|
|
|
|
2023-06-16 21:35:43 -04:00
|
|
|
: decode-channel-correlation ( n -- channel-correlation )
|
2020-12-17 22:11:31 -05:00
|
|
|
{
|
2022-07-06 18:13:20 -04:00
|
|
|
{ [ 0b0000 0b0111 between? ] [ 0 ] }
|
|
|
|
{ [ 0b1000 = ] [ 1 ] }
|
|
|
|
{ [ 0b1001 = ] [ 2 ] }
|
|
|
|
{ [ 0b1010 = ] [ 3 ] }
|
|
|
|
[ reserved-channel-assignment ]
|
2023-06-16 21:35:43 -04:00
|
|
|
} cond-case <flac-channel-correlation> ;
|
2022-07-06 18:13:20 -04:00
|
|
|
|
|
|
|
: decode-bits-per-sample ( stream-info n -- n )
|
|
|
|
{
|
|
|
|
{ 0b000 [ 0 ] }
|
|
|
|
{ 0b001 [ 8 ] }
|
|
|
|
{ 0b010 [ 12 ] }
|
|
|
|
{ 0b011 [ reserved-sample-size ] }
|
|
|
|
{ 0b100 [ 16 ] }
|
|
|
|
{ 0b101 [ 20 ] }
|
|
|
|
{ 0b110 [ 24 ] }
|
|
|
|
{ 0b111 [ reserved-sample-size ] }
|
|
|
|
} case
|
|
|
|
dup 0 = [ drop bits-per-sample>> ] [ nip ] if ;
|
|
|
|
|
|
|
|
: read/assert-frame-sync-code ( -- )
|
2023-06-16 21:35:43 -04:00
|
|
|
15 flac-read-uint 0b111111111111100 = [ sync-code-error ] unless ;
|
2022-07-06 18:13:20 -04:00
|
|
|
|
|
|
|
: read-flac-frame-header ( stream-info -- frame-header )
|
2021-11-25 12:18:59 -05:00
|
|
|
[
|
2022-07-06 18:13:20 -04:00
|
|
|
read/assert-frame-sync-code
|
2023-06-16 21:35:43 -04:00
|
|
|
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 [ <flac-channel-assignment> ] [ decode-channel-correlation ] bi
|
2022-07-06 18:13:20 -04:00
|
|
|
] dip
|
2023-06-16 21:35:43 -04:00
|
|
|
3 flac-read-uint decode-bits-per-sample
|
|
|
|
1 flac-read-uint drop ! ignore magic sync for now
|
2022-07-06 18:13:20 -04:00
|
|
|
flac-read-coded-number
|
|
|
|
! decoding blocksize/samplerate potentially reads from end of header
|
|
|
|
[ decode-block-size ] 4dip
|
|
|
|
[ decode-sample-rate ] 3dip
|
|
|
|
8 flac-read
|
|
|
|
flac-frame-header boa ;
|
2021-11-25 12:18:59 -05:00
|
|
|
|
2022-07-06 18:13:20 -04:00
|
|
|
: read-flac-subframe-wasted-bits ( -- k )
|
2023-06-16 21:35:43 -04:00
|
|
|
1 flac-read-uint 1 = [ 0 [ 1 + 1 flac-read-uint 0 = ] loop ] [ 0 ] if ;
|
2022-07-06 18:13:20 -04:00
|
|
|
|
2022-08-20 22:19:05 -04:00
|
|
|
: read-flac-subframe-constant ( blocksize bps -- samples )
|
|
|
|
flac-read-int <repetition> [ ] map ;
|
2020-12-17 22:11:31 -05:00
|
|
|
|
2022-08-20 22:19:05 -04:00
|
|
|
: read-flac-subframe-verbatim ( blocksize bps -- samples )
|
|
|
|
<repetition> [ flac-read-int ] map ;
|
|
|
|
|
|
|
|
: adjust-wasted-bits ( wasted-bits samples -- samples' )
|
|
|
|
[ swap shift ] with map! ;
|
2020-12-17 22:11:31 -05:00
|
|
|
|
2022-07-06 18:13:20 -04:00
|
|
|
: read-residual-coding-method-type ( -- coding-method param-bits param-escape )
|
|
|
|
2 flac-read dup
|
2021-11-25 12:18:59 -05:00
|
|
|
2 > [ reserved-residual-coding-type ] when
|
2022-07-06 18:13:20 -04:00
|
|
|
<flac-entropy-coding-method-type>
|
|
|
|
dup entropy-coding-partitioned-rice = [ 4 0xf ] [ 5 0x1f ] if ;
|
2020-12-17 22:11:31 -05:00
|
|
|
|
2022-08-20 22:19:05 -04:00
|
|
|
: read-partition-order/count ( -- partition-order partitions )
|
|
|
|
4 flac-read dup 2^ ;
|
2020-12-17 22:11:31 -05:00
|
|
|
|
2022-08-20 22:19:05 -04:00
|
|
|
! TODO: even with locals this is pretty gnarly
|
|
|
|
:: read-residuals ( blocksize predictor-order -- residuals )
|
|
|
|
read-residual-coding-method-type :> ( coding-type parameter-bits escape-parameter )
|
|
|
|
read-partition-order/count :> ( partition-order partitions )
|
|
|
|
blocksize partition-order neg shift :> partition-samples
|
|
|
|
{ } :> residuals!
|
2020-12-17 22:11:31 -05:00
|
|
|
|
2022-08-20 22:19:05 -04:00
|
|
|
partitions <iota>
|
|
|
|
[| partition |
|
|
|
|
parameter-bits flac-read :> rice-parameter
|
|
|
|
rice-parameter escape-parameter <
|
|
|
|
[
|
|
|
|
partition 0 = [ partition-samples predictor-order - ] [ partition-samples ] if <iota>
|
|
|
|
[ drop residuals rice-parameter flac-read-rice-signed-int suffix residuals! ] each
|
|
|
|
]
|
|
|
|
[
|
|
|
|
5 flac-read :> num-bits
|
|
|
|
partition-samples partition 0 = [ predictor-order ] [ 0 ] if - <iota>
|
|
|
|
[| order |
|
|
|
|
residuals num-bits 0 = [ 0 suffix ] [ num-bits flac-read-int suffix ] if residuals!
|
|
|
|
] each
|
|
|
|
] if
|
|
|
|
] each
|
|
|
|
residuals ;
|
2021-11-25 12:18:59 -05:00
|
|
|
|
2022-08-20 22:19:05 -04:00
|
|
|
: fixed-coefficients ( -- coefficients ) { { } { 1 } { 2 -1 } { 3 -3 1 } { 4 -6 4 1 } } ;
|
2021-11-25 12:18:59 -05:00
|
|
|
|
2022-08-20 22:19:05 -04:00
|
|
|
: read-warmup-samples ( sample-depth order -- samples )
|
|
|
|
swap <repetition> [ flac-read-int ] map ;
|
2021-11-25 12:18:59 -05:00
|
|
|
|
2022-08-20 22:19:05 -04:00
|
|
|
! TODO: even with locals this is also gnarly
|
|
|
|
:: restore-linear-prediction ( residuals warmup coefficients quantization-level -- samples )
|
|
|
|
coefficients length :> order
|
|
|
|
residuals warmup
|
|
|
|
[| samples residual |
|
|
|
|
samples
|
|
|
|
|
|
|
|
residual
|
|
|
|
|
|
|
|
coefficients
|
|
|
|
samples order tail*
|
|
|
|
0
|
|
|
|
[ * + ] 2reduce
|
|
|
|
|
|
|
|
quantization-level neg shift
|
|
|
|
+
|
|
|
|
|
|
|
|
suffix
|
|
|
|
|
|
|
|
] reduce ;
|
|
|
|
|
|
|
|
:: read-flac-subframe-fixed ( blocksize sample-depth order -- samples )
|
|
|
|
sample-depth order read-warmup-samples :> warmup
|
|
|
|
blocksize order read-residuals :> residuals
|
|
|
|
order fixed-coefficients nth :> coefficients
|
|
|
|
residuals warmup coefficients 0 restore-linear-prediction ;
|
2021-11-25 12:18:59 -05:00
|
|
|
|
2022-08-20 22:19:05 -04:00
|
|
|
: read-qlp-shift ( -- quantization-level )
|
2022-07-06 18:13:20 -04:00
|
|
|
5 flac-read ;
|
2021-11-25 12:18:59 -05:00
|
|
|
|
2022-08-20 22:19:05 -04:00
|
|
|
: read-qlp-coefficient-precision ( -- precision )
|
|
|
|
4 flac-read 1 + ;
|
|
|
|
|
|
|
|
: read-lpc-coefficients ( order precision -- coefficients )
|
|
|
|
<repetition> [ flac-read-int ] map ;
|
|
|
|
|
|
|
|
:: read-flac-subframe-lpc ( blocksize sample-depth order -- samples )
|
|
|
|
sample-depth order read-warmup-samples :> warmup
|
|
|
|
read-qlp-coefficient-precision :> precision
|
|
|
|
read-qlp-shift :> qlp-shift
|
|
|
|
order precision read-lpc-coefficients reverse :> coefficients
|
|
|
|
blocksize order read-residuals :> residuals
|
|
|
|
residuals warmup coefficients qlp-shift restore-linear-prediction ;
|
2021-11-25 12:18:59 -05:00
|
|
|
|
|
|
|
! 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 )
|
2022-07-06 18:13:20 -04:00
|
|
|
6 flac-read dup
|
2020-12-17 22:11:31 -05:00
|
|
|
{
|
2022-08-20 22:19:05 -04:00
|
|
|
{ [ 0b000000 = ] [ drop f subframe-type-constant ] }
|
|
|
|
{ [ 0b000001 = ] [ drop f subframe-type-verbatim ] }
|
|
|
|
{ [ 0b001000 0b001111 between? ] [ 2 0 bit-range subframe-type-fixed ] }
|
|
|
|
{ [ 0b100000 0b111111 between? ] [ 4 0 bit-range 1 + subframe-type-lpc ] }
|
2020-12-17 22:11:31 -05:00
|
|
|
[ drop reserved-subframe-type ]
|
2021-11-25 12:18:59 -05:00
|
|
|
} cond-case swap ;
|
2020-12-17 22:11:31 -05:00
|
|
|
|
2022-07-06 18:13:20 -04:00
|
|
|
: read/assert-flac-subframe-sync ( -- )
|
|
|
|
1 flac-read 1 = [ invalid-subframe-sync ] when ;
|
2021-11-25 12:18:59 -05:00
|
|
|
|
|
|
|
: read-flac-subframe-header ( -- subframe-header )
|
2022-07-06 18:13:20 -04:00
|
|
|
read/assert-flac-subframe-sync
|
2021-11-25 12:18:59 -05:00
|
|
|
read-flac-subframe-type
|
|
|
|
read-flac-subframe-wasted-bits
|
2020-12-17 22:11:31 -05:00
|
|
|
flac-subframe-header boa ;
|
|
|
|
|
2022-08-22 23:20:30 -04:00
|
|
|
: calculate-sample-depth ( bps wasted-bits channel-assignment channel -- sample-depth )
|
2022-07-06 18:13:20 -04:00
|
|
|
[ - ] 2dip swap
|
|
|
|
{
|
|
|
|
{ channel-assignment-left [ 1 = [ 1 ] [ 0 ] if ] }
|
|
|
|
{ channel-assignment-right [ 0 = [ 1 ] [ 0 ] if ] }
|
|
|
|
{ channel-assignment-mid [ 1 = [ 1 ] [ 0 ] if ] }
|
|
|
|
[ 2drop 0 ]
|
|
|
|
} case + ;
|
|
|
|
|
2022-08-20 22:19:05 -04:00
|
|
|
: stereo-decorrelation ( samples channel-assignment -- samples' )
|
|
|
|
{
|
|
|
|
{ channel-assignment-independent [ ] } ! do nothing
|
|
|
|
{
|
|
|
|
channel-assignment-left
|
|
|
|
[ [ first ] [ first ] [ second ] tri [ - ] 2map 2array ]
|
|
|
|
}
|
|
|
|
{
|
|
|
|
channel-assignment-right
|
|
|
|
[ [ second ] [ first ] [ second ] tri [ + ] 2map swap 2array ]
|
|
|
|
}
|
|
|
|
{
|
|
|
|
channel-assignment-mid
|
|
|
|
[
|
|
|
|
[ first ] [ second ] bi
|
|
|
|
{ { } { } }
|
|
|
|
[ [ over ] dip [ [ first ] dip suffix ] [ [ second ] dip suffix ] 2bi* 2array ] 2reduce
|
|
|
|
]
|
|
|
|
}
|
|
|
|
} case ;
|
|
|
|
|
|
|
|
:: read-flac-subframe ( frame-header channel -- samples )
|
2022-07-06 18:13:20 -04:00
|
|
|
read-flac-subframe-header :> subframe-header
|
|
|
|
subframe-header wasted-bits>> :> wasted-bits
|
|
|
|
subframe-header subframe-type>> :> subframe-type
|
2022-08-20 22:19:05 -04:00
|
|
|
subframe-header predictor-order>> :> predictor-order
|
|
|
|
frame-header bits-per-sample>> :> bps
|
2022-07-06 18:13:20 -04:00
|
|
|
frame-header blocksize>> :> blocksize
|
2022-08-20 22:19:05 -04:00
|
|
|
frame-header channel-assignment>> :> channel-assignment
|
2022-08-22 23:20:30 -04:00
|
|
|
bps wasted-bits channel-assignment channel calculate-sample-depth :> sample-depth
|
2022-07-06 18:13:20 -04:00
|
|
|
|
|
|
|
subframe-type
|
|
|
|
{
|
2022-08-20 22:19:05 -04:00
|
|
|
{ subframe-type-constant [ blocksize sample-depth read-flac-subframe-constant ] }
|
|
|
|
{ subframe-type-verbatim [ blocksize sample-depth read-flac-subframe-verbatim ] }
|
|
|
|
{ subframe-type-fixed [ blocksize sample-depth predictor-order read-flac-subframe-fixed ] }
|
|
|
|
{ subframe-type-lpc [ blocksize sample-depth predictor-order read-flac-subframe-lpc ] }
|
|
|
|
} case :> samples!
|
2022-07-06 18:13:20 -04:00
|
|
|
|
2022-08-20 22:19:05 -04:00
|
|
|
wasted-bits samples adjust-wasted-bits ;
|
2020-12-17 22:11:31 -05:00
|
|
|
|
2022-08-20 22:19:05 -04:00
|
|
|
: read-flac-subframes ( frame-header channels -- samples )
|
|
|
|
[ dup channel-assignment>> swap ] dip
|
|
|
|
<iota> [ read-flac-subframe ] with map
|
|
|
|
swap stereo-decorrelation ;
|
|
|
|
!
|
2020-12-17 22:11:31 -05:00
|
|
|
: read-flac-frame-footer ( -- frame-footer )
|
2022-08-20 22:19:05 -04:00
|
|
|
16 flac-read flac-frame-footer boa ;
|
2020-12-17 22:11:31 -05:00
|
|
|
|
2022-07-06 18:13:20 -04:00
|
|
|
: read-flac-frame ( stream-info -- frame )
|
2022-08-20 22:19:05 -04:00
|
|
|
[ read-flac-frame-header dup ] [ channels>> ] bi
|
|
|
|
read-flac-subframes
|
|
|
|
flac-align-to-byte
|
2020-12-17 22:11:31 -05:00
|
|
|
read-flac-frame-footer
|
|
|
|
flac-frame boa ;
|