2020-06-08 03:29:51 +03:00
package flac
import (
"encoding/binary"
"math/bits"
2021-08-17 13:06:32 +03:00
"github.com/wader/fq/format"
"github.com/wader/fq/format/registry"
"github.com/wader/fq/internal/num"
2021-11-24 23:20:46 +03:00
"github.com/wader/fq/pkg/checksum"
2021-08-17 13:06:32 +03:00
"github.com/wader/fq/pkg/decode"
2021-12-02 00:48:25 +03:00
"github.com/wader/fq/pkg/scalar"
2020-06-08 03:29:51 +03:00
)
func init ( ) {
2021-11-17 18:46:10 +03:00
registry . MustRegister ( decode . Format {
2020-06-08 03:29:51 +03:00
Name : format . FLAC_FRAME ,
Description : "FLAC frame" ,
DecodeFn : frameDecode ,
} )
}
2021-12-06 00:03:39 +03:00
const (
SampleRateStreaminfo = 0b0000
)
const (
SampleSizeStreaminfo = 0b000
)
2020-06-08 03:29:51 +03:00
const (
2021-11-05 17:04:26 +03:00
BlockingStrategyFixed = 0
BlockingStrategyVariable = 1
2020-06-08 03:29:51 +03:00
)
2021-12-02 00:48:25 +03:00
var BlockingStrategyNames = scalar . UToSymStr {
2021-12-06 00:03:39 +03:00
BlockingStrategyFixed : "fixed" ,
BlockingStrategyVariable : "variable" ,
2020-06-08 03:29:51 +03:00
}
const (
2021-12-06 00:03:39 +03:00
BlockSizeEndOfHeader8 = 0b0110
BlockSizeEndOfHeader16 = 0b0111
2020-06-08 03:29:51 +03:00
)
2021-12-06 00:03:39 +03:00
const (
SampeleRateEndOfHeader8 = 0b1100
SampeleRateEndOfHeader16 = 0b1101
SampeleRateEndOfHeader160 = 0b1110
)
const (
SubframeConstant = "constant"
SubframeVerbatim = "verbatim"
SubframeFixed = "fixed"
SubframeLPC = "lpc"
SubframeReserved = "reserved"
)
2020-06-08 03:29:51 +03:00
const (
ChannelLeftSide = 0b1000
ChannelSideRight = 0b1001
ChannelMidSide = 0b1010
)
2021-11-05 17:04:26 +03:00
const (
ResidualCodingMethodRice = 0b00
ResidualCodingMethodRice2 = 0b01
)
2021-12-02 00:48:25 +03:00
var ResidualCodingMethodMap = scalar . UToScalar {
ResidualCodingMethodRice : scalar . S { Sym : uint64 ( 4 ) , Description : "rice" } ,
ResidualCodingMethodRice2 : scalar . S { Sym : uint64 ( 5 ) , Description : "rice2" } ,
2021-11-05 17:04:26 +03:00
}
2020-06-08 03:29:51 +03:00
// TODO: generic enough?
func utf8Uint ( d * decode . D ) uint64 {
n := d . U8 ( )
// leading ones, bit negate and count zeroes
c := bits . LeadingZeros8 ( ^ uint8 ( n ) )
2021-09-29 12:48:30 +03:00
// 0b0xxxxxxx 1 byte
// 0b110xxxxx 2 byte
// 0b1110xxxx 3 byte
// 0b11110xxx 4 byte
2020-06-08 03:29:51 +03:00
switch c {
case 0 :
// nop
2021-09-29 12:48:30 +03:00
case 2 , 3 , 4 :
2020-06-08 03:29:51 +03:00
n = n & ( ( 1 << ( 8 - c - 1 ) ) - 1 )
for i := 1 ; i < c ; i ++ {
n = n << 6 | d . U8 ( ) & 0x3f
}
2021-09-29 12:48:30 +03:00
default :
2021-11-17 18:26:13 +03:00
d . Errorf ( "invalid UTF8Uint" )
2020-06-08 03:29:51 +03:00
}
return n
}
// in argument is an optional FlacFrameIn struct with stream info
func frameDecode ( d * decode . D , in interface { } ) interface { } {
2021-10-28 02:44:09 +03:00
var inStreamInfo * format . FlacStreamInfo
2020-06-08 03:29:51 +03:00
ffi , ok := in . ( format . FlacFrameIn )
if ok {
inStreamInfo = & ffi . StreamInfo
}
frameStart := d . Pos ( )
blockSize := 0
2021-12-06 00:03:39 +03:00
channelAssignment := uint64 ( 0 )
channels := 0
sampleSize := 0
2020-06-08 03:29:51 +03:00
sideChannelIndex := - 1
2021-11-05 17:04:26 +03:00
d . FieldStruct ( "header" , func ( d * decode . D ) {
2020-06-08 03:29:51 +03:00
// <14> 11111111111110
2021-12-02 00:48:25 +03:00
d . FieldU14 ( "sync" , d . AssertU ( 0b11111111111110 ) , scalar . Bin )
2020-06-08 03:29:51 +03:00
// <1> Reserved
// 0 : mandatory value
// 1 : reserved for future use
2021-11-05 17:04:26 +03:00
d . FieldU1 ( "reserved0" , d . AssertU ( 0 ) )
2020-06-08 03:29:51 +03:00
// <1> Blocking strategy:
// 0 : fixed-blocksize stream; frame header encodes the frame number
// 1 : variable-blocksize stream; frame header encodes the sample number
2021-12-02 00:48:25 +03:00
blockingStrategy := d . FieldU1 ( "blocking_strategy" , BlockingStrategyNames )
2020-06-08 03:29:51 +03:00
// <4> Block size in inter-channel samples:
// 0000 : reserved
// 0001 : 192 samples
// 0010-0101 : 576 * (2^(n-2)) samples, i.e. 576/1152/2304/4608
// 0110 : get 8 bit (blocksize-1) from end of header
// 0111 : get 16 bit (blocksize-1) from end of header
// 1000-1111 : 256 * (2^(n-8)) samples, i.e. 256/512/1024/2048/4096/8192/16384/32768
2021-12-06 00:03:39 +03:00
var blockSizeMap = scalar . UToScalar {
0b0000 : { Description : "reserved" } ,
0b0001 : { Sym : uint64 ( 192 ) } ,
0b0010 : { Sym : uint64 ( 576 ) } ,
0b0011 : { Sym : uint64 ( 1152 ) } ,
0b0100 : { Sym : uint64 ( 2304 ) } ,
0b0101 : { Sym : uint64 ( 4608 ) } ,
0b0110 : { Description : "end of header (8 bit)" } ,
0b0111 : { Description : "end of header (16 bit)" } ,
0b1000 : { Sym : uint64 ( 256 ) } ,
0b1001 : { Sym : uint64 ( 512 ) } ,
0b1010 : { Sym : uint64 ( 1024 ) } ,
0b1011 : { Sym : uint64 ( 2048 ) } ,
0b1100 : { Sym : uint64 ( 4096 ) } ,
0b1101 : { Sym : uint64 ( 8192 ) } ,
0b1110 : { Sym : uint64 ( 16384 ) } ,
0b1111 : { Sym : uint64 ( 32768 ) } ,
}
blockSizeS := d . FieldScalarU4 ( "block_size" , blockSizeMap , scalar . Bin )
if blockSizeS . Sym != nil {
blockSize = int ( blockSizeS . SymU ( ) )
}
2020-06-08 03:29:51 +03:00
// <4> Sample rate:
// 0000 : get from STREAMINFO metadata block
// 0001 : 88.2kHz
// 0010 : 176.4kHz
// 0011 : 192kHz
// 0100 : 8kHz
// 0101 : 16kHz
// 0110 : 22.05kHz
// 0111 : 24kHz
// 1000 : 32kHz
// 1001 : 44.1kHz
// 1010 : 48kHz
// 1011 : 96kHz
// 1100 : get 8 bit sample rate (in kHz) from end of header
// 1101 : get 16 bit sample rate (in Hz) from end of header
// 1110 : get 16 bit sample rate (in tens of Hz) from end of header
// 1111 : invalid, to prevent sync-fooling string of 1s
2021-12-06 00:03:39 +03:00
var sampleRateMap = scalar . UToScalar {
0b0000 : { Description : "from streaminfo" } ,
0b0001 : { Sym : uint64 ( 88200 ) } ,
0b0010 : { Sym : uint64 ( 176400 ) } ,
0b0011 : { Sym : uint64 ( 192000 ) } ,
0b0100 : { Sym : uint64 ( 8000 ) } ,
0b0101 : { Sym : uint64 ( 16000 ) } ,
0b0110 : { Sym : uint64 ( 22050 ) } ,
0b0111 : { Sym : uint64 ( 24000 ) } ,
0b1000 : { Sym : uint64 ( 32000 ) } ,
0b1001 : { Sym : uint64 ( 44100 ) } ,
0b1010 : { Sym : uint64 ( 48000 ) } ,
0b1011 : { Sym : uint64 ( 96000 ) } ,
0b1100 : { Description : "end of header (8 bit*1000)" } ,
0b1101 : { Description : "end of header (16 bit)" } ,
0b1110 : { Description : "end of header (16 bit*10)" } ,
0b1111 : { Description : "invalid" } ,
}
sampleRateS := d . FieldScalarU4 ( "sample_rate" , sampleRateMap , scalar . Bin )
switch sampleRateS . ActualU ( ) {
case SampleRateStreaminfo :
if inStreamInfo == nil {
d . Fatalf ( "streaminfo required for sample rate" )
2020-06-08 03:29:51 +03:00
}
2021-12-06 00:03:39 +03:00
}
2020-06-08 03:29:51 +03:00
// <4> Channel assignment
// 0000-0111 : (number of independent channels)-1. Where defined, the channel order follows SMPTE/ITU-R recommendations. The assignments are as follows:
// 1 channel: mono
// 2 channels: left, right
// 3 channels: left, right, center
// 4 channels: front left, front right, back left, back right
// 5 channels: front left, front right, front center, back/surround left, back/surround right
// 6 channels: front left, front right, front center, LFE, back/surround left, back/surround right
// 7 channels: front left, front right, front center, LFE, back center, side left, side right
// 8 channels: front left, front right, front center, LFE, back left, back right, side left, side right
// 1000 : left/side stereo: channel 0 is the left channel, channel 1 is the side(difference) channel
// 1001 : right/side stereo: channel 0 is the side(difference) channel, channel 1 is the right channel
// 1010 : mid/side stereo: channel 0 is the mid(average) channel, channel 1 is the side(difference) channel
// 1011-1111 : reserved
2021-11-05 17:04:26 +03:00
// TODO: extract to tables and cleanup
2021-12-06 00:03:39 +03:00
var channelAssignmentMap = scalar . UToScalar {
0 : { Sym : uint64 ( 1 ) , Description : "mono" } ,
1 : { Sym : uint64 ( 2 ) , Description : "lr" } ,
2 : { Sym : uint64 ( 3 ) , Description : "lrc" } ,
3 : { Sym : uint64 ( 4 ) , Description : "fl,fr,bl,br" } ,
4 : { Sym : uint64 ( 5 ) , Description : "fl,fr,fc,back/surround left,back/surround right" } ,
5 : { Sym : uint64 ( 6 ) , Description : "fl,fr,fc,lfe,back/surround left,back/surround right" } ,
6 : { Sym : uint64 ( 7 ) , Description : "fl,fr,fc,lfe,back center,sl,sr" } ,
7 : { Sym : uint64 ( 8 ) , Description : "fl,fr,fc,lfe,back left,br,sl,sr" } ,
0b1000 : { Sym : uint64 ( 2 ) , Description : "left/side stereo" } ,
0b1001 : { Sym : uint64 ( 2 ) , Description : "right/side stereo" } ,
0b1010 : { Sym : uint64 ( 2 ) , Description : "mid/side stereo" } ,
0b1011 : { Sym : nil , Description : "reserved" } ,
0b1100 : { Sym : nil , Description : "reserved" } ,
0b1101 : { Sym : nil , Description : "reserved" } ,
0b1111 : { Sym : nil , Description : "reserved" } ,
}
channelAssignmentS := d . FieldScalarU4 ( "channel_assignment" , channelAssignmentMap )
if channelAssignmentS . Sym == nil {
2021-11-17 18:26:13 +03:00
d . Fatalf ( "unknown number of channels" )
2021-09-24 17:25:34 +03:00
}
2021-12-06 00:03:39 +03:00
channelAssignment = channelAssignmentS . ActualU ( )
channels = int ( channelAssignmentS . SymU ( ) )
switch channelAssignmentS . ActualU ( ) {
case ChannelLeftSide :
sideChannelIndex = 1
case ChannelSideRight :
sideChannelIndex = 0
case ChannelMidSide :
sideChannelIndex = 1
}
if sideChannelIndex != - 1 {
d . FieldValueU ( "side_channel_index" , uint64 ( sideChannelIndex ) )
}
2020-06-08 03:29:51 +03:00
// <3> Sample size in bits:
// 000 : get from STREAMINFO metadata block
// 001 : 8 bits per sample
// 010 : 12 bits per sample
// 011 : reserved
// 100 : 16 bits per sample
// 101 : 20 bits per sample
// 110 : 24 bits per sample
// 111 : reserved
2021-12-06 00:03:39 +03:00
var sampleSizeMap = scalar . UToScalar {
0b000 : { Description : "from streaminfo" } ,
0b001 : { Sym : uint64 ( 8 ) } ,
0b010 : { Sym : uint64 ( 12 ) } ,
0b011 : { Description : "reserved" } ,
0b100 : { Sym : uint64 ( 16 ) } ,
0b101 : { Sym : uint64 ( 20 ) } ,
0b110 : { Sym : uint64 ( 24 ) } ,
0b111 : { Description : "reserved" } ,
}
sampleSizeS := d . FieldScalarU3 ( "sample_size" , sampleSizeMap , scalar . Bin )
switch sampleSizeS . ActualU ( ) {
case SampleSizeStreaminfo :
if inStreamInfo == nil {
d . Fatalf ( "streaminfo required for sample size" )
2020-06-08 03:29:51 +03:00
}
2021-12-06 00:03:39 +03:00
sampleSize = int ( inStreamInfo . BitPerSample )
default :
if sampleSizeS . Sym != nil {
sampleSize = int ( sampleSizeS . SymU ( ) )
}
}
2020-06-08 03:29:51 +03:00
// <1> Reserved:
// 0 : mandatory value
// 1 : reserved for future use
2021-11-05 17:04:26 +03:00
d . FieldU1 ( "reserved1" , d . AssertU ( 0 ) )
2020-06-08 03:29:51 +03:00
2021-11-05 17:04:26 +03:00
d . FieldStruct ( "end_of_header" , func ( d * decode . D ) {
2020-06-08 03:29:51 +03:00
// if(variable blocksize)
// <8-56>:"UTF-8" coded sample number (decoded number is 36 bits) [4]
// else
// <8-48>:"UTF-8" coded frame number (decoded number is 31 bits) [4]
2021-12-06 00:03:39 +03:00
// 0 : fixed-blocksize stream; frame header encodes the frame number
// 1 : variable-blocksize stream; frame header encodes the sample number
2020-06-08 03:29:51 +03:00
switch blockingStrategy {
case BlockingStrategyVariable :
2021-11-05 17:04:26 +03:00
d . FieldUFn ( "sample_number" , utf8Uint )
2020-06-08 03:29:51 +03:00
case BlockingStrategyFixed :
2021-11-05 17:04:26 +03:00
d . FieldUFn ( "frame_number" , utf8Uint )
2020-06-08 03:29:51 +03:00
}
// if(blocksize bits == 011x)
// 8/16 bit (blocksize-1)
2021-12-06 00:03:39 +03:00
// 0110 : get 8 bit (blocksize-1) from end of header
// 0111 : get 16 bit (blocksize-1) from end of header
switch blockSizeS . ActualU ( ) {
case BlockSizeEndOfHeader8 :
2021-12-02 00:48:25 +03:00
blockSize = int ( d . FieldU8 ( "block_size" , scalar . UAdd ( 1 ) ) )
2021-12-06 00:03:39 +03:00
case BlockSizeEndOfHeader16 :
2021-12-02 00:48:25 +03:00
blockSize = int ( d . FieldU16 ( "block_size" , scalar . UAdd ( 1 ) ) )
2020-06-08 03:29:51 +03:00
}
// if(sample rate bits == 11xx)
// 8/16 bit sample rate
2021-12-06 00:03:39 +03:00
// 1100 : get 8 bit sample rate (in kHz) from end of header
// 1101 : get 16 bit sample rate (in Hz) from end of header
// 1110 : get 16 bit sample rate (in tens of Hz) from end of header
switch sampleRateS . ActualU ( ) {
case SampeleRateEndOfHeader8 :
2021-11-05 17:04:26 +03:00
d . FieldUFn ( "sample_rate" , func ( d * decode . D ) uint64 { return d . U8 ( ) * 1000 } )
2021-12-06 00:03:39 +03:00
case SampeleRateEndOfHeader16 :
d . FieldU16 ( "sample_rate" )
case SampeleRateEndOfHeader160 :
2021-11-05 17:04:26 +03:00
d . FieldUFn ( "sample_rate" , func ( d * decode . D ) uint64 { return d . U16 ( ) * 10 } )
2020-06-08 03:29:51 +03:00
}
} )
2021-11-24 23:20:46 +03:00
headerCRC := & checksum . CRC { Bits : 8 , Table : checksum . ATM8Table }
2021-11-18 03:17:41 +03:00
d . MustCopy ( headerCRC , d . BitBufRange ( frameStart , d . Pos ( ) - frameStart ) )
2021-12-02 00:48:25 +03:00
d . FieldU8 ( "crc" , d . ValidateUBytes ( headerCRC . Sum ( nil ) ) , scalar . Hex )
2020-06-08 03:29:51 +03:00
} )
var channelSamples [ ] [ ] int64
2021-11-05 17:04:26 +03:00
d . FieldArray ( "subframes" , func ( d * decode . D ) {
2021-12-06 00:03:39 +03:00
for channelIndex := 0 ; channelIndex < channels ; channelIndex ++ {
2021-11-05 17:04:26 +03:00
d . FieldStruct ( "subframe" , func ( d * decode . D ) {
2020-06-08 03:29:51 +03:00
// <1> Zero bit padding, to prevent sync-fooling string of 1s
2021-11-05 17:04:26 +03:00
d . FieldU1 ( "zero_bit" , d . AssertU ( 0 ) )
2020-06-08 03:29:51 +03:00
// <6> Subframe type:
// 000000 : SUBFRAME_CONSTANT
// 000001 : SUBFRAME_VERBATIM
// 00001x : reserved
// 0001xx : reserved
// 001xxx : if(xxx <= 4) SUBFRAME_FIXED, xxx=order ; else reserved
// 01xxxx : reserved
// 1xxxxx : SUBFRAME_LPC, xxxxx=order-1
2021-12-06 00:03:39 +03:00
lpcOrder := - 1
var subframeTypeRangeMap = scalar . URangeToScalar {
2021-12-06 21:33:17 +03:00
{ Range : [ 2 ] uint64 { 0b000000 , 0b000000 } , S : scalar . S { Sym : SubframeConstant } } ,
{ Range : [ 2 ] uint64 { 0b000001 , 0b000001 } , S : scalar . S { Sym : SubframeVerbatim } } ,
{ Range : [ 2 ] uint64 { 0b000010 , 0b000011 } , S : scalar . S { Sym : SubframeReserved } } ,
{ Range : [ 2 ] uint64 { 0b000100 , 0b000111 } , S : scalar . S { Sym : SubframeReserved } } ,
{ Range : [ 2 ] uint64 { 0b001000 , 0b001100 } , S : scalar . S { Sym : SubframeFixed } } ,
{ Range : [ 2 ] uint64 { 0b001101 , 0b001111 } , S : scalar . S { Sym : SubframeReserved } } ,
{ Range : [ 2 ] uint64 { 0b010000 , 0b011111 } , S : scalar . S { Sym : SubframeReserved } } ,
{ Range : [ 2 ] uint64 { 0b100000 , 0b111111 } , S : scalar . S { Sym : SubframeLPC } } ,
2021-12-06 00:03:39 +03:00
}
subframeTypeS := d . FieldScalarU6 ( "subframe_type" , subframeTypeRangeMap , scalar . Bin )
switch subframeTypeS . SymStr ( ) {
case SubframeFixed :
lpcOrder = int ( subframeTypeS . ActualU ( ) & 0b111 )
case SubframeLPC :
lpcOrder = int ( ( subframeTypeS . ActualU ( ) & 0b11111 ) + 1 )
}
if lpcOrder != - 1 {
2021-11-05 17:04:26 +03:00
d . FieldValueU ( "lpc_order" , uint64 ( lpcOrder ) )
2021-12-06 00:03:39 +03:00
}
2020-06-08 03:29:51 +03:00
// 'Wasted bits-per-sample' flag:
// 0 : no wasted bits-per-sample in source subblock, k=0
// 1 : k wasted bits-per-sample in source subblock, k-1 follows, unary coded; e.g. k=3 => 001 follows, k=7 => 0000001 follows.
wastedBitsFlag := d . FieldU1 ( "wasted_bits_flag" )
var wastedBitsK int
if wastedBitsFlag != 0 {
2021-12-02 00:48:25 +03:00
wastedBitsK = int ( d . FieldUnary ( "wasted_bits_k" , 0 , scalar . UAdd ( 1 ) ) )
2020-06-08 03:29:51 +03:00
}
subframeSampleSize := sampleSize - wastedBitsK
if subframeSampleSize < 0 {
2021-11-17 18:26:13 +03:00
d . Fatalf ( "negative subframeSampleSize %d" , subframeSampleSize )
2020-06-08 03:29:51 +03:00
}
// if channel is side, add en extra sample bit
// https://github.com/xiph/flac/blob/37e675b777d4e0de53ac9ff69e2aea10d92e729c/src/libFLAC/stream_decoder.c#L2040
if channelIndex == sideChannelIndex {
subframeSampleSize ++
}
2021-11-05 17:04:26 +03:00
d . FieldValueU ( "subframe_sample_size" , uint64 ( subframeSampleSize ) )
2020-06-08 03:29:51 +03:00
2021-10-19 18:27:05 +03:00
decodeWarmupSamples := func ( samples [ ] int64 , n int , sampleSize int ) {
2021-10-20 14:55:34 +03:00
if len ( samples ) < n {
2021-11-17 18:26:13 +03:00
d . Fatalf ( "decodeWarmupSamples outside block size" )
2021-10-20 14:55:34 +03:00
}
2021-11-05 17:04:26 +03:00
d . FieldArray ( "warmup_samples" , func ( d * decode . D ) {
2020-06-08 03:29:51 +03:00
for i := 0 ; i < n ; i ++ {
2021-10-19 18:27:05 +03:00
samples [ i ] = d . FieldS ( "value" , sampleSize )
2020-06-08 03:29:51 +03:00
}
} )
}
2021-10-19 18:27:05 +03:00
decodeResiduals := func ( samples [ ] int64 ) {
2021-10-20 14:55:34 +03:00
samplesLen := len ( samples )
2021-10-19 18:27:05 +03:00
n := 0
2020-06-08 03:29:51 +03:00
// <2> Residual coding method:
// 00 : partitioned Rice coding with 4-bit Rice parameter; RESIDUAL_CODING_METHOD_PARTITIONED_RICE follows
// 01 : partitioned Rice coding with 5-bit Rice parameter; RESIDUAL_CODING_METHOD_PARTITIONED_RICE2 follows
// 10-11 : reserved
var riceEscape int
2021-11-05 17:04:26 +03:00
var riceBits int
2021-12-02 00:48:25 +03:00
residualCodingMethod := d . FieldU2 ( "residual_coding_method" , scalar . UToScalar {
0b00 : scalar . S { Sym : uint64 ( 4 ) , Description : "rice" } ,
0b01 : scalar . S { Sym : uint64 ( 5 ) , Description : "rice2" } ,
} )
2021-11-05 17:04:26 +03:00
switch residualCodingMethod {
case ResidualCodingMethodRice :
riceEscape = 0b1111
riceBits = 4
case ResidualCodingMethodRice2 :
riceEscape = 0b11111
riceBits = 5
}
2020-06-08 03:29:51 +03:00
// <4> Partition order.
partitionOrder := int ( d . FieldU4 ( "partition_order" ) )
// There will be 2^order partitions.
ricePartitions := 1 << partitionOrder
2021-11-05 17:04:26 +03:00
d . FieldValueU ( "rice_partitions" , uint64 ( ricePartitions ) )
2020-06-08 03:29:51 +03:00
2021-11-05 17:04:26 +03:00
d . FieldArray ( "partitions" , func ( d * decode . D ) {
2020-06-08 03:29:51 +03:00
for i := 0 ; i < ricePartitions ; i ++ {
2021-11-05 17:04:26 +03:00
d . FieldStruct ( "partition" , func ( d * decode . D ) {
2020-06-08 03:29:51 +03:00
// Encoding parameter:
// <4(+5)> Encoding parameter:
// 0000-1110 : Rice parameter.
// 1111 : Escape code, meaning the partition is in unencoded binary form using n bits per sample; n follows as a 5-bit number.
// Or:
// <5(+5)> Encoding parameter:
// 00000-11110 : Rice parameter.
// 11111 : Escape code, meaning the partition is in unencoded binary form using n bits per sample; n follows as a 5-bit number.
// Encoded residual. The number of samples (n) in the partition is determined as follows:
// if the partition order is zero, n = frame's blocksize - predictor order
// else if this is not the first partition of the subframe, n = (frame's blocksize / (2^partition order))
// else n = (frame's blocksize / (2^partition order)) - predictor order
var count int
if partitionOrder == 0 {
count = blockSize - lpcOrder
} else if i != 0 {
count = blockSize / ricePartitions
} else {
count = ( blockSize / ricePartitions ) - lpcOrder
}
2021-11-05 17:04:26 +03:00
d . FieldValueU ( "count" , uint64 ( count ) )
2020-06-08 03:29:51 +03:00
riceParameter := int ( d . FieldU ( "rice_parameter" , riceBits ) )
2021-10-20 14:55:34 +03:00
if samplesLen < n + count {
2021-11-17 18:26:13 +03:00
d . Fatalf ( "decodeResiduals outside block size" )
2021-10-20 14:55:34 +03:00
}
2020-06-08 03:29:51 +03:00
if riceParameter == riceEscape {
escapeSampleSize := int ( d . FieldU5 ( "escape_sample_size" ) )
2021-11-05 17:04:26 +03:00
d . FieldRawLen ( "samples" , int64 ( count * escapeSampleSize ) )
2020-06-08 03:29:51 +03:00
} else {
samplesStart := d . Pos ( )
for j := 0 ; j < count ; j ++ {
high := d . Unary ( 0 )
_ = high
low := d . U ( riceParameter )
_ = low
2021-10-19 18:27:05 +03:00
samples [ n ] = num . ZigZag ( high << riceParameter | low )
n ++
2020-06-08 03:29:51 +03:00
}
samplesStop := d . Pos ( )
2021-11-05 17:04:26 +03:00
d . RangeFn ( samplesStart , samplesStop - samplesStart , func ( d * decode . D ) {
d . FieldRawLen ( "samples" , d . BitsLeft ( ) )
} )
2020-06-08 03:29:51 +03:00
}
} )
}
} )
}
// modifies input samples slice and returns it
2021-10-19 18:27:05 +03:00
decodeLPC := func ( lpcOrder int , samples [ ] int64 , coeffs [ ] int64 , shift int64 ) {
2020-06-08 03:29:51 +03:00
for i := lpcOrder ; i < len ( samples ) ; i ++ {
r := int64 ( 0 )
for j := 0 ; j < len ( coeffs ) ; j ++ {
c := coeffs [ j ]
s := samples [ i - j - 1 ]
r += c * s
}
samples [ i ] = samples [ i ] + ( r >> shift )
}
}
2021-10-19 18:27:05 +03:00
var samples [ ] int64
2021-12-06 00:03:39 +03:00
switch subframeTypeS . SymStr ( ) {
2020-06-08 03:29:51 +03:00
case SubframeConstant :
samples = make ( [ ] int64 , blockSize )
// <n> Unencoded constant value of the subblock, n = frame's bits-per-sample.
v := d . FieldS ( "value" , subframeSampleSize )
for i := 0 ; i < blockSize ; i ++ {
samples [ i ] = v
}
case SubframeVerbatim :
samples = make ( [ ] int64 , blockSize )
// <n*i> Unencoded subblock; n = frame's bits-per-sample, i = frame's blocksize.
// TODO: refactor into some kind of FieldBitBufLenFn?
2021-11-05 17:04:26 +03:00
d . RangeFn ( d . Pos ( ) , int64 ( blockSize * subframeSampleSize ) , func ( d * decode . D ) {
d . FieldRawLen ( "samples" , d . BitsLeft ( ) )
} )
2020-06-08 03:29:51 +03:00
for i := 0 ; i < blockSize ; i ++ {
samples [ i ] = d . S ( subframeSampleSize )
}
case SubframeFixed :
2021-10-19 18:27:05 +03:00
samples = make ( [ ] int64 , blockSize )
2020-06-08 03:29:51 +03:00
// <n> Unencoded warm-up samples (n = frame's bits-per-sample * predictor order).
2021-10-19 18:27:05 +03:00
decodeWarmupSamples ( samples , lpcOrder , subframeSampleSize )
2020-06-08 03:29:51 +03:00
// Encoded residual
2021-10-19 18:27:05 +03:00
decodeResiduals ( samples [ lpcOrder : ] )
2020-06-08 03:29:51 +03:00
// http://www.hpl.hp.com/techreports/1999/HPL-1999-144.pdf
fixedCoeffs := [ ] [ ] int64 {
{ } ,
{ 1 } ,
{ 2 , - 1 } ,
{ 3 , - 3 , 1 } ,
{ 4 , - 6 , 4 , - 1 } ,
}
coeffs := fixedCoeffs [ lpcOrder ]
2021-10-19 18:27:05 +03:00
decodeLPC ( lpcOrder , samples , coeffs , 0 )
2020-06-08 03:29:51 +03:00
case SubframeLPC :
2021-10-19 18:27:05 +03:00
samples = make ( [ ] int64 , blockSize )
2020-06-08 03:29:51 +03:00
// <n> Unencoded warm-up samples (n = frame's bits-per-sample * lpc order).
2021-10-19 18:27:05 +03:00
decodeWarmupSamples ( samples , lpcOrder , subframeSampleSize )
2020-06-08 03:29:51 +03:00
// <4> (Quantized linear predictor coefficients' precision in bits)-1 (1111 = invalid).
2021-12-02 00:48:25 +03:00
precision := int ( d . FieldU4 ( "precision" , scalar . UAdd ( 1 ) ) )
2020-06-08 03:29:51 +03:00
// <5> Quantized linear predictor coefficient shift needed in bits (NOTE: this number is signed two's-complement).
shift := d . FieldS5 ( "shift" )
if shift < 0 {
2021-11-17 18:26:13 +03:00
d . Fatalf ( "negative LPC shift %d" , shift )
2020-06-08 03:29:51 +03:00
}
// <n> Unencoded predictor coefficients (n = qlp coeff precision * lpc order) (NOTE: the coefficients are signed two's-complement).
var coeffs [ ] int64
2021-11-05 17:04:26 +03:00
d . FieldArray ( "coefficients" , func ( d * decode . D ) {
2020-06-08 03:29:51 +03:00
for i := 0 ; i < lpcOrder ; i ++ {
coeffs = append ( coeffs , d . FieldS ( "value" , precision ) )
}
} )
// Encoded residual
2021-10-19 18:27:05 +03:00
decodeResiduals ( samples [ lpcOrder : ] )
decodeLPC ( lpcOrder , samples , coeffs , shift )
2020-06-08 03:29:51 +03:00
}
if wastedBitsK != 0 {
for i := 0 ; i < len ( samples ) ; i ++ {
samples [ i ] <<= wastedBitsK
}
}
channelSamples = append ( channelSamples , samples )
} )
}
} )
// <?> Zero-padding to byte alignment.
2021-11-05 17:04:26 +03:00
d . FieldU ( "byte_align" , d . ByteAlignBits ( ) , d . AssertU ( 0 ) )
2020-06-08 03:29:51 +03:00
// <16> CRC-16 (polynomial = x^16 + x^15 + x^2 + x^0, initialized with 0) of everything before the crc, back to and including the frame header sync code
2021-11-24 23:20:46 +03:00
footerCRC := & checksum . CRC { Bits : 16 , Table : checksum . ANSI16Table }
2021-11-18 03:17:41 +03:00
d . MustCopy ( footerCRC , d . BitBufRange ( frameStart , d . Pos ( ) - frameStart ) )
2021-12-02 00:48:25 +03:00
d . FieldRawLen ( "footer_crc" , 16 , d . ValidateBitBuf ( footerCRC . Sum ( nil ) ) , scalar . RawHex )
2020-06-08 03:29:51 +03:00
streamSamples := len ( channelSamples [ 0 ] )
for j := 0 ; j < len ( channelSamples ) ; j ++ {
if streamSamples > len ( channelSamples [ j ] ) {
2021-11-17 18:26:13 +03:00
d . Fatalf ( "different amount of samples in channels %d != %d" , streamSamples , len ( channelSamples [ j ] ) )
2020-06-08 03:29:51 +03:00
}
}
// Transform mid/side channels into left, right
// mid = (left + right)/2
// side = left - right
switch channelAssignment {
case ChannelLeftSide :
for i := 0 ; i < len ( channelSamples [ 0 ] ) ; i ++ {
channelSamples [ 1 ] [ i ] = channelSamples [ 0 ] [ i ] - channelSamples [ 1 ] [ i ]
}
case ChannelSideRight :
for i := 0 ; i < len ( channelSamples [ 0 ] ) ; i ++ {
channelSamples [ 0 ] [ i ] = channelSamples [ 1 ] [ i ] + channelSamples [ 0 ] [ i ]
}
case ChannelMidSide :
for i := 0 ; i < len ( channelSamples [ 0 ] ) ; i ++ {
m := channelSamples [ 0 ] [ i ]
s := channelSamples [ 1 ] [ i ]
m = m << 1 | s & 1
channelSamples [ 0 ] [ i ] = ( m + s ) >> 1
channelSamples [ 1 ] [ i ] = ( m - s ) >> 1
}
default :
2021-10-19 02:52:59 +03:00
// not stereo or no side channel
2020-06-08 03:29:51 +03:00
}
2021-10-19 02:52:59 +03:00
outSampleSize := sampleSize + ( sampleSize % 8 )
bytesPerSample := outSampleSize / 8
2020-06-08 03:29:51 +03:00
p := 0
le := binary . LittleEndian
interleavedSamplesBuf := ffi . SamplesBuf
interleavedSamplesBufLen := len ( channelSamples ) * streamSamples * bytesPerSample
2021-09-14 19:54:59 +03:00
// TODO: decode read buffer?
2020-06-08 03:29:51 +03:00
// reuse buffer if possible
if interleavedSamplesBuf == nil || len ( interleavedSamplesBuf ) < interleavedSamplesBufLen {
interleavedSamplesBuf = make ( [ ] byte , interleavedSamplesBufLen )
}
// TODO: speedup by using more cache friendly memory layout for samples
for i := 0 ; i < streamSamples ; i ++ {
for j := 0 ; j < len ( channelSamples ) ; j ++ {
s := channelSamples [ j ] [ i ]
2021-10-19 02:52:59 +03:00
switch outSampleSize {
2020-06-08 03:29:51 +03:00
case 8 :
interleavedSamplesBuf [ p ] = byte ( s )
case 16 :
le . PutUint16 ( interleavedSamplesBuf [ p : ] , uint16 ( s ) )
case 24 :
interleavedSamplesBuf [ p ] = byte ( s )
le . PutUint16 ( interleavedSamplesBuf [ p + 1 : ] , uint16 ( s >> 8 ) )
case 32 :
le . PutUint32 ( interleavedSamplesBuf [ p : ] , uint32 ( s ) )
}
p += bytesPerSample
}
}
return format . FlacFrameOut {
SamplesBuf : interleavedSamplesBuf ,
Samples : uint64 ( streamSamples ) ,
2021-12-06 00:03:39 +03:00
Channels : channels ,
2021-10-19 02:52:59 +03:00
BitsPerSample : outSampleSize ,
2020-06-08 03:29:51 +03:00
}
}