DataHoarder
5d5f2413bf
All checks were successful
continuous-integration/drone/push Build is passing
285 lines
5.1 KiB
Go
285 lines
5.1 KiB
Go
package tta
|
|
|
|
import (
|
|
"io"
|
|
)
|
|
|
|
type fifo struct {
|
|
buffer [fifoBufferSize]byte
|
|
pos int32
|
|
end int32
|
|
bcount uint32 // count of bits in cache
|
|
bcache uint32 // bit cache
|
|
crc uint32
|
|
count uint32
|
|
io io.ReadWriteSeeker
|
|
}
|
|
|
|
func (s *fifo) readByte() (v byte) {
|
|
if s.pos >= s.end {
|
|
v, _ := s.io.Read(s.buffer[:]) // FIXME: handle this error
|
|
s.end = int32(v)
|
|
s.pos = 0
|
|
}
|
|
s.crc = crc32Table[(s.crc^uint32(s.buffer[s.pos]))&0xFF] ^ (s.crc >> 8)
|
|
s.count++
|
|
v = s.buffer[s.pos]
|
|
s.pos++
|
|
return
|
|
}
|
|
|
|
func (s *fifo) readUint16() (v uint16) {
|
|
v = 0
|
|
v |= uint16(s.readByte())
|
|
v |= uint16(s.readByte()) << 8
|
|
return
|
|
}
|
|
|
|
func (s *fifo) readUint32() (v uint32) {
|
|
v = 0
|
|
v |= uint32(s.readByte())
|
|
v |= uint32(s.readByte()) << 8
|
|
v |= uint32(s.readByte()) << 16
|
|
v |= uint32(s.readByte()) << 24
|
|
return
|
|
}
|
|
|
|
func (s *fifo) readCrc32() bool {
|
|
crc := s.crc ^ 0xFFFFFFFF
|
|
return crc == s.readUint32()
|
|
}
|
|
|
|
func (s *fifo) readStart() {
|
|
s.pos = s.end
|
|
}
|
|
|
|
func (s *fifo) reset() {
|
|
s.crc = 0xFFFFFFFF
|
|
s.bcache = 0
|
|
s.bcount = 0
|
|
s.count = 0
|
|
}
|
|
|
|
func (s *fifo) readSkipBytes(size uint32) {
|
|
for size > 0 {
|
|
size--
|
|
s.readByte()
|
|
}
|
|
}
|
|
|
|
func (s *fifo) skipId3v2() (size uint32) {
|
|
s.reset()
|
|
if 'I' != s.readByte() || 'D' != s.readByte() || '3' != s.readByte() {
|
|
s.pos = 0
|
|
return 0
|
|
}
|
|
s.pos += 2 // skip version bytes
|
|
if s.readByte()&0x10 != 0 {
|
|
size += 10
|
|
}
|
|
size += uint32(s.readByte() & 0x7F)
|
|
size = (size << 7) | uint32(s.readByte()&0x7F)
|
|
size = (size << 7) | uint32(s.readByte()&0x7F)
|
|
size = (size << 7) | uint32(s.readByte()&0x7F)
|
|
s.readSkipBytes(size)
|
|
size += 10
|
|
return
|
|
}
|
|
|
|
func (s *fifo) getValue(ad *adapter) (value int32) {
|
|
if s.bcache^bitMask[s.bcount] == 0 {
|
|
value += int32(s.bcount)
|
|
s.bcache = uint32(s.readByte())
|
|
s.bcount = 8
|
|
for s.bcache == 0xFF {
|
|
value += 8
|
|
s.bcache = uint32(s.readByte())
|
|
}
|
|
}
|
|
|
|
for (s.bcache & 1) != 0 {
|
|
value++
|
|
s.bcache >>= 1
|
|
s.bcount--
|
|
}
|
|
s.bcache >>= 1
|
|
s.bcount--
|
|
|
|
var level, k, tmp uint32
|
|
if value == 0 {
|
|
level = 0
|
|
k = ad.k0
|
|
} else {
|
|
level = 1
|
|
k = ad.k1
|
|
value--
|
|
}
|
|
if k != 0 {
|
|
for s.bcount < k {
|
|
tmp = uint32(s.readByte())
|
|
s.bcache |= tmp << s.bcount
|
|
s.bcount += 8
|
|
}
|
|
value = (value << k) + int32(s.bcache&bitMask[k])
|
|
s.bcache >>= k
|
|
s.bcount -= k
|
|
s.bcache &= bitMask[s.bcount]
|
|
}
|
|
if level == 1 {
|
|
ad.sum1 += uint32(value) - (ad.sum1 >> 4)
|
|
if ad.k1 > 0 && ad.sum1 < shift16[ad.k1] {
|
|
ad.k1--
|
|
} else if ad.sum1 > shift16[ad.k1+1] {
|
|
ad.k1++
|
|
}
|
|
value += int32(bitShift[ad.k0])
|
|
}
|
|
|
|
ad.sum0 += uint32(value) - (ad.sum0 >> 4)
|
|
if ad.k0 > 0 && ad.sum0 < shift16[ad.k0] {
|
|
ad.k0--
|
|
} else if ad.sum0 > shift16[ad.k0+1] {
|
|
ad.k0++
|
|
}
|
|
// ((x & 1)?((x + 1) >> 1):(-x >> 1))
|
|
if value&1 != 0 {
|
|
value = (value + 1) >> 1
|
|
} else {
|
|
value = -value >> 1
|
|
}
|
|
return
|
|
}
|
|
|
|
func (s *fifo) writeDone() error {
|
|
if s.pos > 0 {
|
|
if n, err := s.io.Write(s.buffer[:s.pos]); err != nil || n != int(s.pos) {
|
|
return errWrite
|
|
}
|
|
s.pos = 0
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *fifo) writeByte(v byte) error {
|
|
if s.pos == fifoBufferSize {
|
|
if n, err := s.io.Write(s.buffer[:]); err != nil || n != fifoBufferSize {
|
|
return errWrite
|
|
}
|
|
s.pos = 0
|
|
}
|
|
s.crc = crc32Table[(s.crc^uint32(v))&0xFF] ^ (s.crc >> 8)
|
|
s.count++
|
|
s.buffer[s.pos] = v
|
|
s.pos++
|
|
return nil
|
|
}
|
|
|
|
func (s *fifo) writeUint16(v uint16) error {
|
|
if err := s.writeByte(byte(v)); err != nil {
|
|
return err
|
|
}
|
|
if err := s.writeByte(byte(v >> 8)); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *fifo) writeUint32(v uint32) error {
|
|
if err := s.writeByte(byte(v)); err != nil {
|
|
return err
|
|
}
|
|
if err := s.writeByte(byte(v >> 8)); err != nil {
|
|
return err
|
|
}
|
|
if err := s.writeByte(byte(v >> 16)); err != nil {
|
|
return err
|
|
}
|
|
return s.writeByte(byte(v >> 24))
|
|
}
|
|
|
|
func (s *fifo) writeCrc32() error {
|
|
return s.writeUint32(s.crc ^ 0xFFFFFFFF)
|
|
}
|
|
|
|
func (s *fifo) writeSkipBytes(size uint32) error {
|
|
for size > 0 {
|
|
if err := s.writeByte(0); err != nil {
|
|
return err
|
|
}
|
|
size--
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *fifo) putValue(ad *adapter, value int32) {
|
|
var k, unary, outval uint32
|
|
if value > 0 {
|
|
outval = (uint32(value) << 1) - 1
|
|
} else {
|
|
outval = uint32(-value) << 1
|
|
}
|
|
k = ad.k0
|
|
ad.sum0 += outval - (ad.sum0 >> 4)
|
|
if ad.k0 > 0 && ad.sum0 < shift16[ad.k0] {
|
|
ad.k0--
|
|
} else if ad.sum0 > shift16[ad.k0+1] {
|
|
ad.k0++
|
|
}
|
|
|
|
if outval >= bitShift[k] {
|
|
outval -= bitShift[k]
|
|
k = ad.k1
|
|
ad.sum1 += outval - (ad.sum1 >> 4)
|
|
if ad.k1 > 0 && ad.sum1 < shift16[ad.k1] {
|
|
ad.k1--
|
|
} else if ad.sum1 > shift16[ad.k1+1] {
|
|
ad.k1++
|
|
}
|
|
unary = 1 + (outval >> k)
|
|
} else {
|
|
unary = 0
|
|
}
|
|
|
|
for { // put unary
|
|
for s.bcount >= 8 {
|
|
s.writeByte(byte(s.bcache))
|
|
s.bcache >>= 8
|
|
s.bcount -= 8
|
|
}
|
|
if unary > 23 {
|
|
s.bcache |= bitMask[23] << s.bcount
|
|
s.bcount += 23
|
|
unary -= 23
|
|
} else {
|
|
s.bcache |= bitMask[unary] << s.bcount
|
|
s.bcount += unary + 1
|
|
unary = 0
|
|
}
|
|
if unary == 0 {
|
|
break
|
|
}
|
|
}
|
|
for s.bcount >= 8 { // put binary
|
|
s.writeByte(byte(s.bcache))
|
|
s.bcache >>= 8
|
|
s.bcount -= 8
|
|
}
|
|
if k != 0 {
|
|
s.bcache |= (outval & bitMask[k]) << s.bcount
|
|
s.bcount += k
|
|
}
|
|
}
|
|
|
|
func (s *fifo) flushBitCache() {
|
|
for s.bcount > 0 {
|
|
s.writeByte(byte(s.bcache))
|
|
s.bcache >>= 8
|
|
if s.bcount > 8 {
|
|
s.bcount -= 8
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
s.writeCrc32()
|
|
}
|