945 lines
20 KiB
Go
945 lines
20 KiB
Go
package packetizer
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"github.com/icza/bitio"
|
|
"golang.org/x/exp/slices"
|
|
"io"
|
|
)
|
|
|
|
type FLACHeaderPacket struct {
|
|
Capture [4]byte
|
|
MinimumBlockSize uint16
|
|
MaximumBlockSize uint16
|
|
MinimumFrameSize uint32
|
|
MaximumFrameSize uint32
|
|
SampleRate uint32
|
|
ChannelCount uint8
|
|
BitsPerSample uint8
|
|
TotalSamples uint64
|
|
Hash [128 / 8]byte
|
|
MetadataBlocks [][]byte
|
|
}
|
|
|
|
func (p *FLACHeaderPacket) KeepMode() KeepMode {
|
|
return Keep
|
|
}
|
|
|
|
func (p *FLACHeaderPacket) GetStartSampleNumber() int64 {
|
|
return 0
|
|
}
|
|
|
|
func (p *FLACHeaderPacket) GetEndSampleNumber() int64 {
|
|
return 0
|
|
}
|
|
|
|
func (p *FLACHeaderPacket) GetData() []byte {
|
|
data := bytes.NewBuffer(make([]byte, 0, 1024))
|
|
buf := bitio.NewWriter(data)
|
|
if _, err := buf.Write(p.Capture[:]); err != nil {
|
|
return nil
|
|
}
|
|
for _, b := range p.MetadataBlocks {
|
|
if buf.WriteByte(b[0]) != nil {
|
|
return nil
|
|
}
|
|
if err := buf.WriteBits(uint64(len(b)-1), 24); err != nil {
|
|
return nil
|
|
}
|
|
if _, err := buf.Write(b[1:]); err != nil {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
_ = buf.Close()
|
|
|
|
return data.Bytes()
|
|
}
|
|
|
|
func (p *FLACHeaderPacket) Category() int64 {
|
|
return 0
|
|
}
|
|
|
|
const invalidMetadataBlock = 127
|
|
|
|
func readFlacMetadataBlock(br *bitio.Reader) (block byte, data []byte) {
|
|
var err error
|
|
if block, err = br.ReadByte(); err != nil {
|
|
return invalidMetadataBlock, nil
|
|
}
|
|
var lengthInBytes uint64
|
|
if lengthInBytes, err = br.ReadBits(24); err != nil {
|
|
return invalidMetadataBlock, nil
|
|
}
|
|
data = make([]byte, lengthInBytes)
|
|
if _, err = io.ReadFull(br, data); err != nil {
|
|
return invalidMetadataBlock, nil
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func readFlacHeader(br *bitio.Reader) *FLACHeaderPacket {
|
|
hdr := &FLACHeaderPacket{}
|
|
|
|
if _, err := br.Read(hdr.Capture[:]); err != nil || bytes.Compare(hdr.Capture[:], []byte("fLaC")) != 0 {
|
|
return nil
|
|
}
|
|
|
|
block, data := readFlacMetadataBlock(br)
|
|
if (block&0x7F) != 0 || len(data) < ((16+16+24+24+20+3+5+36+128)/8) { //StreamInfo
|
|
return nil
|
|
}
|
|
|
|
hdr.MetadataBlocks = append(hdr.MetadataBlocks, append([]byte{block}, data...))
|
|
|
|
sbr := bitio.NewReader(bytes.NewBuffer(data))
|
|
|
|
var n uint64
|
|
|
|
n, _ = sbr.ReadBits(16)
|
|
hdr.MinimumBlockSize = uint16(n)
|
|
n, _ = sbr.ReadBits(16)
|
|
hdr.MaximumBlockSize = uint16(n)
|
|
n, _ = sbr.ReadBits(24)
|
|
hdr.MinimumFrameSize = uint32(n)
|
|
n, _ = sbr.ReadBits(24)
|
|
hdr.MaximumFrameSize = uint32(n)
|
|
n, _ = sbr.ReadBits(20)
|
|
hdr.SampleRate = uint32(n)
|
|
n, _ = sbr.ReadBits(3)
|
|
hdr.ChannelCount = uint8(n) + 1
|
|
n, _ = sbr.ReadBits(5)
|
|
hdr.BitsPerSample = uint8(n) + 1
|
|
_, _ = sbr.Read(hdr.Hash[:])
|
|
|
|
for {
|
|
if (block & (1 << 7)) > 0 { //if last
|
|
break
|
|
}
|
|
block, data = readFlacMetadataBlock(br)
|
|
if block == invalidMetadataBlock {
|
|
return nil
|
|
}
|
|
|
|
hdr.MetadataBlocks = append(hdr.MetadataBlocks, append([]byte{block}, data...))
|
|
}
|
|
|
|
return hdr
|
|
}
|
|
|
|
func readFlacFrame(hdr *FLACHeaderPacket, br *bitio.Reader, bfr *cachedBitReader) *FLACPacket {
|
|
if sync, err := br.ReadBits(14); err != nil || sync != 0b11111111111110 {
|
|
return nil
|
|
}
|
|
if reserved, err := br.ReadBits(1); err != nil || reserved != 0 {
|
|
return nil
|
|
}
|
|
|
|
p := &FLACPacket{
|
|
hdr: hdr,
|
|
mode: Discard,
|
|
}
|
|
|
|
var err error
|
|
|
|
if p.BlockingStrategy, err = br.ReadBits(1); err != nil {
|
|
return nil
|
|
}
|
|
|
|
if p.BlockSizeRaw, err = br.ReadBits(4); err != nil {
|
|
return nil
|
|
}
|
|
|
|
if p.SampleRateRaw, err = br.ReadBits(4); err != nil {
|
|
return nil
|
|
}
|
|
|
|
if p.ChannelAssignment, err = br.ReadBits(4); err != nil {
|
|
return nil
|
|
}
|
|
|
|
if p.BitsPerSample, err = br.ReadBits(3); err != nil {
|
|
return nil
|
|
}
|
|
|
|
if reserved, err := br.ReadBits(1); err != nil || reserved != 0 {
|
|
return nil
|
|
}
|
|
|
|
if p.Number, err = func(r io.ByteReader) (x uint64, err error) {
|
|
const (
|
|
tx = 0x80 // 1000 0000
|
|
t2 = 0xC0 // 1100 0000
|
|
t3 = 0xE0 // 1110 0000
|
|
t4 = 0xF0 // 1111 0000
|
|
t5 = 0xF8 // 1111 1000
|
|
t6 = 0xFC // 1111 1100
|
|
t7 = 0xFE // 1111 1110
|
|
t8 = 0xFF // 1111 1111
|
|
|
|
maskx = 0x3F // 0011 1111
|
|
mask2 = 0x1F // 0001 1111
|
|
mask3 = 0x0F // 0000 1111
|
|
mask4 = 0x07 // 0000 0111
|
|
mask5 = 0x03 // 0000 0011
|
|
mask6 = 0x01 // 0000 0001
|
|
|
|
rune1Max = 1<<7 - 1
|
|
rune2Max = 1<<11 - 1
|
|
rune3Max = 1<<16 - 1
|
|
rune4Max = 1<<21 - 1
|
|
rune5Max = 1<<26 - 1
|
|
rune6Max = 1<<31 - 1
|
|
rune7Max = 1<<36 - 1
|
|
)
|
|
|
|
c0, err := r.ReadByte()
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
// 1-byte, 7-bit sequence?
|
|
if c0 < tx {
|
|
// if c0 == 0xxxxxxx
|
|
// total: 7 bits (7)
|
|
return uint64(c0), nil
|
|
}
|
|
|
|
// unexpected continuation byte?
|
|
if c0 < t2 {
|
|
// if c0 == 10xxxxxx
|
|
return 0, errors.New("unexpected continuation byte")
|
|
}
|
|
|
|
// get number of continuation bytes and store bits from c0.
|
|
var l int
|
|
switch {
|
|
case c0 < t3:
|
|
// if c0 == 110xxxxx
|
|
// total: 11 bits (5 + 6)
|
|
l = 1
|
|
x = uint64(c0 & mask2)
|
|
case c0 < t4:
|
|
// if c0 == 1110xxxx
|
|
// total: 16 bits (4 + 6 + 6)
|
|
l = 2
|
|
x = uint64(c0 & mask3)
|
|
case c0 < t5:
|
|
// if c0 == 11110xxx
|
|
// total: 21 bits (3 + 6 + 6 + 6)
|
|
l = 3
|
|
x = uint64(c0 & mask4)
|
|
case c0 < t6:
|
|
// if c0 == 111110xx
|
|
// total: 26 bits (2 + 6 + 6 + 6 + 6)
|
|
l = 4
|
|
x = uint64(c0 & mask5)
|
|
case c0 < t7:
|
|
// if c0 == 1111110x
|
|
// total: 31 bits (1 + 6 + 6 + 6 + 6 + 6)
|
|
l = 5
|
|
x = uint64(c0 & mask6)
|
|
case c0 < t8:
|
|
// if c0 == 11111110
|
|
// total: 36 bits (0 + 6 + 6 + 6 + 6 + 6 + 6)
|
|
l = 6
|
|
x = 0
|
|
}
|
|
|
|
// store bits from continuation bytes.
|
|
for i := 0; i < l; i++ {
|
|
x <<= 6
|
|
c, err := r.ReadByte()
|
|
if err != nil {
|
|
if err == io.EOF {
|
|
return 0, io.ErrUnexpectedEOF
|
|
}
|
|
return 0, err
|
|
}
|
|
if c < tx || t2 <= c {
|
|
// if c != 10xxxxxx
|
|
return 0, errors.New("expected continuation byte")
|
|
}
|
|
x |= uint64(c & maskx)
|
|
}
|
|
|
|
// check if number representation is larger than necessary.
|
|
switch l {
|
|
case 1:
|
|
if x <= rune1Max {
|
|
return 0, fmt.Errorf("larger number representation than necessary; x (%d) stored in %d bytes, could be stored in %d bytes", x, l+1, l)
|
|
}
|
|
case 2:
|
|
if x <= rune2Max {
|
|
return 0, fmt.Errorf("larger number representation than necessary; x (%d) stored in %d bytes, could be stored in %d bytes", x, l+1, l)
|
|
}
|
|
case 3:
|
|
if x <= rune3Max {
|
|
return 0, fmt.Errorf("larger number representation than necessary; x (%d) stored in %d bytes, could be stored in %d bytes", x, l+1, l)
|
|
}
|
|
case 4:
|
|
if x <= rune4Max {
|
|
return 0, fmt.Errorf("larger number representation than necessary; x (%d) stored in %d bytes, could be stored in %d bytes", x, l+1, l)
|
|
}
|
|
case 5:
|
|
if x <= rune5Max {
|
|
return 0, fmt.Errorf("larger number representation than necessary; x (%d) stored in %d bytes, could be stored in %d bytes", x, l+1, l)
|
|
}
|
|
case 6:
|
|
if x <= rune6Max {
|
|
return 0, fmt.Errorf("larger number representation than necessary; x (%d) stored in %d bytes, could be stored in %d bytes", x, l+1, l)
|
|
}
|
|
}
|
|
return x, nil
|
|
}(br); err != nil {
|
|
return nil
|
|
}
|
|
|
|
if p.BlockSizeRaw == 0x6 {
|
|
if p.BlockSizeExtra, err = br.ReadBits(8); err != nil {
|
|
return nil
|
|
}
|
|
} else if p.BlockSizeRaw == 0x7 {
|
|
if p.BlockSizeExtra, err = br.ReadBits(16); err != nil {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
if p.SampleRateRaw == 0xC {
|
|
if p.SampleRateExtra, err = br.ReadBits(8); err != nil {
|
|
return nil
|
|
}
|
|
} else if p.SampleRateRaw == 0xD || p.SampleRateRaw == 0xE {
|
|
if p.SampleRateExtra, err = br.ReadBits(16); err != nil {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
if p.CRC8, err = br.ReadBits(8); err != nil {
|
|
return nil
|
|
}
|
|
|
|
channelCount := int(p.ChannelAssignment) + 1
|
|
if p.ChannelAssignment == 0x8 || p.ChannelAssignment == 0x9 || p.ChannelAssignment == 0xA {
|
|
channelCount = 2
|
|
}
|
|
|
|
blockSize := int(p.getBlockSize())
|
|
|
|
bfr.ResetBuffer()
|
|
|
|
var subframeType, wastedBitsFlag, wastedBits uint64
|
|
//TODO: remove error checking here, given we get proper input and a check will happen later
|
|
for channelNumber := 0; channelNumber < channelCount; channelNumber++ {
|
|
bps := p.getBitsPerSample()
|
|
|
|
if p.ChannelAssignment == 0x9 && channelNumber == 0 {
|
|
bps++
|
|
} else if (p.ChannelAssignment == 0x8 || p.ChannelAssignment == 0xA) && channelNumber == 1 {
|
|
bps++
|
|
}
|
|
|
|
//var padding uint64
|
|
if _, err = br.ReadBits(1); err != nil {
|
|
return nil
|
|
}
|
|
if subframeType, err = br.ReadBits(6); err != nil {
|
|
return nil
|
|
}
|
|
|
|
if wastedBitsFlag, err = br.ReadBits(1); err != nil {
|
|
return nil
|
|
}
|
|
|
|
if wastedBitsFlag == 1 {
|
|
if wastedBits, err = readUnary(br); err != nil {
|
|
return nil
|
|
}
|
|
} else {
|
|
wastedBits = 0
|
|
}
|
|
|
|
if wastedBitsFlag == 1 {
|
|
|
|
bps -= uint8(wastedBits) + 1
|
|
}
|
|
|
|
switch {
|
|
case subframeType == 0: //Constant
|
|
|
|
//var constantSample uint64
|
|
if _, err = br.ReadBits(bps); err != nil {
|
|
return nil
|
|
}
|
|
case subframeType == 1: //Verbatim
|
|
//var verbatimData []byte
|
|
if _, err = readManyBits(br, blockSize*int(bps)); err != nil {
|
|
return nil
|
|
}
|
|
case subframeType < 8: //reserved
|
|
return nil
|
|
case subframeType < 16: //Fixed
|
|
order := int(subframeType & 0x07)
|
|
|
|
if order > 4 {
|
|
return nil
|
|
}
|
|
|
|
//var warmupData []byte
|
|
if _, err = readManyBits(br, order*int(bps)); err != nil {
|
|
return nil
|
|
}
|
|
|
|
if err = decodeResidual(br, blockSize, order); err != nil {
|
|
return nil
|
|
}
|
|
case subframeType < 32: //reserved
|
|
return nil
|
|
default: //FIR
|
|
order := int(subframeType&0x1F) + 1
|
|
//var warmupData []byte
|
|
if _, err = readManyBits(br, order*int(bps)); err != nil {
|
|
return nil
|
|
}
|
|
|
|
var coefficientPrecisionLen uint64
|
|
if coefficientPrecisionLen, err = br.ReadBits(4); err != nil {
|
|
return nil
|
|
}
|
|
|
|
if coefficientPrecisionLen == 0xF {
|
|
return nil
|
|
}
|
|
|
|
precision := int(coefficientPrecisionLen) + 1
|
|
|
|
//var quantizationLevel uint64
|
|
if _, err = br.ReadBits(5); err != nil {
|
|
return nil
|
|
}
|
|
|
|
//var coefficientData []byte
|
|
if _, err = readManyBits(br, order*precision); err != nil {
|
|
return nil
|
|
}
|
|
|
|
if err = decodeResidual(br, blockSize, order); err != nil {
|
|
return nil
|
|
}
|
|
}
|
|
}
|
|
|
|
br.Align()
|
|
|
|
p.FrameData = slices.Clone(bfr.GetBuffer())
|
|
|
|
if p.CRC16, err = br.ReadBits(16); err != nil {
|
|
return nil
|
|
}
|
|
|
|
return p
|
|
}
|
|
|
|
func decodeResidual(br *bitio.Reader, blockSize, predictorOrder int) (err error) {
|
|
var entropyCodingMethod, partitionOrder uint64
|
|
if entropyCodingMethod, err = br.ReadBits(2); err != nil {
|
|
return err
|
|
}
|
|
|
|
paramSize := 0
|
|
|
|
switch entropyCodingMethod {
|
|
case 0x0:
|
|
paramSize = 4
|
|
case 0x1:
|
|
paramSize = 5
|
|
default:
|
|
return errors.New("wrong method")
|
|
}
|
|
|
|
if partitionOrder, err = br.ReadBits(4); err != nil {
|
|
return err
|
|
}
|
|
|
|
partitions := 1 << partitionOrder
|
|
|
|
var riceParameter uint64
|
|
for partition := 0; partition < partitions; partition++ {
|
|
if riceParameter, err = br.ReadBits(uint8(paramSize)); err != nil {
|
|
return err
|
|
}
|
|
|
|
var nsamples int
|
|
if partition != 0 {
|
|
nsamples = blockSize / partitions
|
|
} else {
|
|
nsamples = blockSize/partitions - predictorOrder
|
|
}
|
|
|
|
if (paramSize == 4 && riceParameter == 0xF) || (paramSize == 5 && riceParameter == 0x1F) {
|
|
// 1111 or 11111: Escape code, meaning the partition is in unencoded
|
|
// binary form using riceParameter2 bits per sample; riceParameter2 follows as a 5-bit number.
|
|
var riceParameter2 uint64
|
|
|
|
if riceParameter2, err = br.ReadBits(5); err != nil {
|
|
return err
|
|
}
|
|
|
|
if riceParameter2 > 0 {
|
|
//var sampleData []byte
|
|
if _, err = readManyBits(br, nsamples*int(riceParameter2)); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
} else {
|
|
|
|
//TODO: optimize this!
|
|
//var high, low uint64
|
|
if riceParameter == 0 {
|
|
for j := 0; j < nsamples; j++ {
|
|
if _, err = readUnary(br); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
} else {
|
|
for j := 0; j < nsamples; j++ {
|
|
if _, err = readUnary(br); err != nil {
|
|
return err
|
|
}
|
|
if _, err = br.ReadBits(uint8(riceParameter)); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func readManyBits(br *bitio.Reader, bits int) (data []byte, err error) {
|
|
dataLen := bits / 8
|
|
if (bits % 8) != 0 {
|
|
dataLen++
|
|
}
|
|
|
|
data = make([]byte, dataLen)
|
|
for i := 0; i < (bits / 8); i++ {
|
|
if data[i], err = br.ReadByte(); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
if (bits % 8) != 0 {
|
|
var b uint64
|
|
if b, err = br.ReadBits(uint8(bits % 8)); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
data[len(data)-1] = byte(b)
|
|
}
|
|
return
|
|
}
|
|
|
|
func readUnary(br *bitio.Reader) (x uint64, err error) {
|
|
var bit uint64
|
|
for {
|
|
if bit, err = br.ReadBits(1); err != nil {
|
|
return 0, err
|
|
}
|
|
if bit == 1 {
|
|
break
|
|
}
|
|
x++
|
|
}
|
|
return x, nil
|
|
}
|
|
|
|
type FLACPacket struct {
|
|
mode KeepMode
|
|
hdr *FLACHeaderPacket
|
|
|
|
BlockingStrategy uint64
|
|
BlockSizeRaw uint64
|
|
SampleRateRaw uint64
|
|
ChannelAssignment uint64
|
|
BitsPerSample uint64
|
|
Number uint64
|
|
BlockSizeExtra uint64
|
|
SampleRateExtra uint64
|
|
CRC8 uint64
|
|
|
|
FrameData []byte
|
|
|
|
buf []byte
|
|
|
|
CRC16 uint64
|
|
}
|
|
|
|
func (p *FLACPacket) KeepMode() KeepMode {
|
|
return p.mode
|
|
}
|
|
|
|
func (p *FLACPacket) GetStartSampleNumber() int64 {
|
|
if p.BlockingStrategy == 0 { //fixed-blocksize
|
|
return int64(p.Number * uint64(p.hdr.MinimumBlockSize))
|
|
}
|
|
return int64(p.Number)
|
|
}
|
|
|
|
func (p *FLACPacket) GetEndSampleNumber() int64 {
|
|
return p.GetStartSampleNumber() + int64(p.getBlockSize())
|
|
}
|
|
|
|
func (p *FLACPacket) GetData() []byte {
|
|
return p.GetDataOffset(0)
|
|
}
|
|
|
|
func (p *FLACPacket) Category() int64 {
|
|
return 0
|
|
}
|
|
|
|
func (p *FLACPacket) getBlockSize() uint16 {
|
|
n := p.BlockSizeRaw
|
|
x := p.BlockSizeExtra
|
|
|
|
switch {
|
|
case n == 0x0:
|
|
// 0000: reserved.
|
|
return 0
|
|
case n == 0x1:
|
|
// 0001: 192 samples.
|
|
return 192
|
|
case n >= 0x2 && n <= 0x5:
|
|
// 0010-0101: 576 * 2^(n-2) samples.
|
|
return 576 * (1 << (n - 2))
|
|
case n == 0x6:
|
|
// 0110: get 8 bit (block size)-1 from the end of the header.
|
|
return uint16(x + 1)
|
|
case n == 0x7:
|
|
// 0111: get 16 bit (block size)-1 from the end of the header.
|
|
return uint16(x + 1)
|
|
default:
|
|
// 1000-1111: 256 * 2^(n-8) samples.
|
|
return 256 * (1 << (n - 8))
|
|
}
|
|
}
|
|
|
|
func (p *FLACPacket) getSampleRate() uint32 {
|
|
switch p.SampleRateRaw {
|
|
case 0x0:
|
|
// 0000: unknown sample rate; get from StreamInfo.
|
|
return p.hdr.SampleRate
|
|
case 0x1:
|
|
// 0001: 88.2 kHz.
|
|
return 88200
|
|
case 0x2:
|
|
// 0010: 176.4 kHz.
|
|
return 176400
|
|
case 0x3:
|
|
// 0011: 192 kHz.
|
|
return 192000
|
|
case 0x4:
|
|
// 0100: 8 kHz.
|
|
return 8000
|
|
case 0x5:
|
|
// 0101: 16 kHz.
|
|
return 16000
|
|
case 0x6:
|
|
// 0110: 22.05 kHz.
|
|
return 22050
|
|
case 0x7:
|
|
// 0111: 24 kHz.
|
|
return 24000
|
|
case 0x8:
|
|
// 1000: 32 kHz.
|
|
return 32000
|
|
case 0x9:
|
|
// 1001: 44.1 kHz.
|
|
return 44100
|
|
case 0xA:
|
|
// 1010: 48 kHz.
|
|
return 48000
|
|
case 0xB:
|
|
// 1011: 96 kHz.
|
|
return 96000
|
|
case 0xC:
|
|
// 1100: get 8 bit sample rate (in kHz) from the end of the header.
|
|
return uint32(p.SampleRateExtra * 1000)
|
|
case 0xD:
|
|
// 1101: get 16 bit sample rate (in Hz) from the end of the header.
|
|
return uint32(p.SampleRateExtra)
|
|
case 0xE:
|
|
// 1110: get 16 bit sample rate (in daHz) from the end of the header.
|
|
return uint32(p.SampleRateExtra * 10)
|
|
default:
|
|
// 1111: invalid.
|
|
return 0
|
|
}
|
|
}
|
|
|
|
func (p *FLACPacket) getBitsPerSample() uint8 {
|
|
switch p.BitsPerSample {
|
|
case 0x0:
|
|
// 000: unknown bits-per-sample; get from StreamInfo.
|
|
return p.hdr.BitsPerSample
|
|
case 0x1:
|
|
// 001: 8 bits-per-sample.
|
|
return 8
|
|
case 0x2:
|
|
// 010: 12 bits-per-sample.
|
|
return 12
|
|
case 0x4:
|
|
// 100: 16 bits-per-sample.
|
|
return 16
|
|
case 0x5:
|
|
// 101: 20 bits-per-sample.
|
|
return 20
|
|
case 0x6:
|
|
// 110: 24 bits-per-sample.
|
|
return 24
|
|
default:
|
|
// 011: reserved.
|
|
// 111: reserved.
|
|
return 0
|
|
}
|
|
}
|
|
|
|
func (p *FLACPacket) GetDataOffset(offset int64) []byte {
|
|
//TODO: reserve proper amount
|
|
buf := bytes.NewBuffer(make([]byte, 0, len(p.FrameData)+64))
|
|
bw := bitio.NewWriter(buf)
|
|
|
|
//sync
|
|
_ = bw.WriteBits(0b11111111111110, 14)
|
|
|
|
//reserved
|
|
_ = bw.WriteBits(0, 1)
|
|
|
|
_ = bw.WriteBits(p.BlockingStrategy, 1)
|
|
|
|
_ = bw.WriteBits(p.BlockSizeRaw, 4)
|
|
|
|
_ = bw.WriteBits(p.SampleRateRaw, 4)
|
|
|
|
_ = bw.WriteBits(p.ChannelAssignment, 4)
|
|
|
|
_ = bw.WriteBits(p.BitsPerSample, 3)
|
|
|
|
//reserved
|
|
_ = bw.WriteBits(0, 1)
|
|
|
|
number := int64(p.Number)
|
|
if offset != 0 {
|
|
if p.BlockingStrategy == 1 {
|
|
number -= offset
|
|
|
|
if number < 0 {
|
|
return nil
|
|
}
|
|
} else {
|
|
number -= offset / int64(p.hdr.MinimumBlockSize)
|
|
|
|
if number < 0 {
|
|
return nil
|
|
}
|
|
}
|
|
}
|
|
|
|
var err error
|
|
|
|
if err = func(w io.ByteWriter, x uint64) error {
|
|
const (
|
|
tx = 0x80 // 1000 0000
|
|
t2 = 0xC0 // 1100 0000
|
|
t3 = 0xE0 // 1110 0000
|
|
t4 = 0xF0 // 1111 0000
|
|
t5 = 0xF8 // 1111 1000
|
|
t6 = 0xFC // 1111 1100
|
|
t7 = 0xFE // 1111 1110
|
|
t8 = 0xFF // 1111 1111
|
|
|
|
maskx = 0x3F // 0011 1111
|
|
mask2 = 0x1F // 0001 1111
|
|
mask3 = 0x0F // 0000 1111
|
|
mask4 = 0x07 // 0000 0111
|
|
mask5 = 0x03 // 0000 0011
|
|
mask6 = 0x01 // 0000 0001
|
|
|
|
rune1Max = 1<<7 - 1
|
|
rune2Max = 1<<11 - 1
|
|
rune3Max = 1<<16 - 1
|
|
rune4Max = 1<<21 - 1
|
|
rune5Max = 1<<26 - 1
|
|
rune6Max = 1<<31 - 1
|
|
rune7Max = 1<<36 - 1
|
|
)
|
|
|
|
// 1-byte, 7-bit sequence?
|
|
if x <= rune1Max {
|
|
if err := w.WriteByte(byte(x)); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// get number of continuation bytes and store bits of c0.
|
|
var (
|
|
// number of continuation bytes.,
|
|
l int
|
|
// bits of c0.
|
|
bits uint64
|
|
)
|
|
switch {
|
|
case x <= rune2Max:
|
|
// if c0 == 110xxxxx
|
|
// total: 11 bits (5 + 6)
|
|
l = 1
|
|
bits = t2 | (x>>6)&mask2
|
|
case x <= rune3Max:
|
|
// if c0 == 1110xxxx
|
|
// total: 16 bits (4 + 6 + 6)
|
|
l = 2
|
|
bits = t3 | (x>>(6*2))&mask3
|
|
case x <= rune4Max:
|
|
// if c0 == 11110xxx
|
|
// total: 21 bits (3 + 6 + 6 + 6)
|
|
l = 3
|
|
bits = t4 | (x>>(6*3))&mask4
|
|
case x <= rune5Max:
|
|
// if c0 == 111110xx
|
|
// total: 26 bits (2 + 6 + 6 + 6 + 6)
|
|
l = 4
|
|
bits = t5 | (x>>(6*4))&mask5
|
|
case x <= rune6Max:
|
|
// if c0 == 1111110x
|
|
// total: 31 bits (1 + 6 + 6 + 6 + 6 + 6)
|
|
l = 5
|
|
bits = t6 | (x>>(6*5))&mask6
|
|
case x <= rune7Max:
|
|
// if c0 == 11111110
|
|
// total: 36 bits (0 + 6 + 6 + 6 + 6 + 6 + 6)
|
|
l = 6
|
|
bits = 0
|
|
}
|
|
// Store bits of c0.
|
|
if err := w.WriteByte(byte(bits)); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Store continuation bytes.
|
|
for i := l - 1; i >= 0; i-- {
|
|
bits = tx | (x>>uint(6*i))&maskx
|
|
if err := w.WriteByte(byte(bits)); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}(bw, uint64(number)); err != nil {
|
|
return nil
|
|
}
|
|
|
|
if p.BlockSizeRaw == 0x6 {
|
|
_ = bw.WriteBits(p.BlockSizeExtra, 8)
|
|
} else if p.BlockSizeRaw == 0x7 {
|
|
_ = bw.WriteBits(p.BlockSizeExtra, 16)
|
|
}
|
|
|
|
if p.SampleRateRaw == 0xC {
|
|
_ = bw.WriteBits(p.SampleRateExtra, 8)
|
|
} else if p.SampleRateRaw == 0xD || p.SampleRateRaw == 0xE {
|
|
_ = bw.WriteBits(p.SampleRateExtra, 16)
|
|
}
|
|
|
|
_, _ = bw.Align()
|
|
|
|
_ = bw.WriteBits(uint64(flacCrc8(buf.Bytes())), 8)
|
|
|
|
_, _ = bw.Write(p.FrameData)
|
|
|
|
_, _ = bw.Align()
|
|
|
|
_ = bw.WriteBits(uint64(flacCrc16(buf.Bytes())), 16)
|
|
|
|
_ = bw.Close()
|
|
|
|
return buf.Bytes()
|
|
}
|
|
|
|
type cachedBitReader struct {
|
|
r *bufio.Reader
|
|
originalBuf []byte
|
|
buf []byte
|
|
byteBuf []byte
|
|
}
|
|
|
|
func newCachedBitReader(reader io.Reader, bufSize int) *cachedBitReader {
|
|
r := &cachedBitReader{
|
|
r: bufio.NewReaderSize(reader, bufSize),
|
|
buf: make([]byte, 0, bufSize),
|
|
byteBuf: make([]byte, 1),
|
|
}
|
|
r.originalBuf = r.buf[:]
|
|
return r
|
|
}
|
|
|
|
func (r *cachedBitReader) Read(p []byte) (n int, err error) {
|
|
n, err = r.r.Read(p)
|
|
if n > 0 {
|
|
r.buf = append(r.buf, p[:n]...)
|
|
}
|
|
return
|
|
}
|
|
|
|
func (r *cachedBitReader) ReadByte() (byte, error) {
|
|
n, err := r.r.Read(r.byteBuf)
|
|
if n > 0 {
|
|
r.buf = append(r.buf, r.byteBuf[0])
|
|
}
|
|
return r.byteBuf[0], err
|
|
}
|
|
|
|
func (r *cachedBitReader) GetBuffer() []byte {
|
|
return r.buf
|
|
}
|
|
|
|
func (r *cachedBitReader) ResetBuffer() {
|
|
r.buf = r.originalBuf
|
|
}
|
|
|
|
type FLACPacketizer struct {
|
|
bfr *cachedBitReader
|
|
br *bitio.Reader
|
|
hdr *FLACHeaderPacket
|
|
}
|
|
|
|
func NewFLACPacketizer(reader io.Reader) *FLACPacketizer {
|
|
p := &FLACPacketizer{
|
|
bfr: newCachedBitReader(reader, 1024*32),
|
|
}
|
|
p.br = bitio.NewReader(p.bfr)
|
|
return p
|
|
}
|
|
|
|
func (o *FLACPacketizer) GetPacket() Packet {
|
|
o.bfr.ResetBuffer()
|
|
|
|
if o.hdr == nil {
|
|
o.hdr = readFlacHeader(o.br)
|
|
if o.hdr == nil {
|
|
return nil
|
|
}
|
|
return o.hdr
|
|
}
|
|
|
|
packet := readFlacFrame(o.hdr, o.br, o.bfr)
|
|
if packet == nil {
|
|
return nil
|
|
}
|
|
return packet
|
|
}
|