go-tta/fifo.go
DataHoarder 5d5f2413bf
All checks were successful
continuous-integration/drone/push Build is passing
Made changes based in reference implementation
2022-02-26 15:59:04 +01:00

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()
}