diff --git a/audio/packetizer/flac.go b/audio/packetizer/flac.go index 8bb3ac5..d5c0d64 100644 --- a/audio/packetizer/flac.go +++ b/audio/packetizer/flac.go @@ -9,10 +9,6 @@ import ( "io" ) -func NewFLACPacketizer(reader io.Reader) *FLACPacketizer { - return &FLACPacketizer{br: bitio.NewReader(bufio.NewReaderSize(reader, 4096))} -} - type FLACHeaderPacket struct { Capture [4]byte MinimumBlockSize uint16 @@ -137,7 +133,7 @@ func readFlacHeader(br *bitio.Reader) *FLACHeaderPacket { return hdr } -func readFlacFrame(hdr *FLACHeaderPacket, br *bitio.Reader) *FLACPacket { +func readFlacFrame(hdr *FLACHeaderPacket, br *bitio.Reader, bfr *cachedBitReader) *FLACPacket { if sync, err := br.ReadBits(14); err != nil || sync != 0b11111111111110 { return nil } @@ -336,11 +332,9 @@ func readFlacFrame(hdr *FLACHeaderPacket, br *bitio.Reader) *FLACPacket { blockSize := int(p.getBlockSize()) - buf := bytes.NewBuffer(hdr.buf[:0]) + bfr.ResetBuffer() - bw := bitio.NewWriter(buf) - - var padding, subframeType, wastedBitsFlag, wastedBits uint64 + 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() @@ -351,7 +345,8 @@ func readFlacFrame(hdr *FLACHeaderPacket, br *bitio.Reader) *FLACPacket { bps++ } - if padding, err = br.ReadBits(1); err != nil { + //var padding uint64 + if _, err = br.ReadBits(1); err != nil { return nil } if subframeType, err = br.ReadBits(6); err != nil { @@ -370,11 +365,11 @@ func readFlacFrame(hdr *FLACHeaderPacket, br *bitio.Reader) *FLACPacket { wastedBits = 0 } - _ = bw.WriteBits(padding, 1) - _ = bw.WriteBits(subframeType, 6) - _ = bw.WriteBits(wastedBitsFlag, 1) + //_ = bw.WriteBits(padding, 1) + //_ = bw.WriteBits(subframeType, 6) + //_ = bw.WriteBits(wastedBitsFlag, 1) if wastedBitsFlag == 1 { - _ = writeUnary(bw, wastedBits) + //_ = writeUnary(bw, wastedBits) bps -= uint8(wastedBits) + 1 } @@ -382,17 +377,17 @@ func readFlacFrame(hdr *FLACHeaderPacket, br *bitio.Reader) *FLACPacket { switch { case subframeType == 0: //Constant - var constantSample uint64 - if constantSample, err = br.ReadBits(bps); err != nil { + //var constantSample uint64 + if _, err = br.ReadBits(bps); err != nil { return nil } - _ = bw.WriteBits(constantSample, bps) + //_ = bw.WriteBits(constantSample, bps) case subframeType == 1: //Verbatim - var verbatimData []byte - if verbatimData, err = readManyBits(br, blockSize*int(bps)); err != nil { + //var verbatimData []byte + if _, err = readManyBits(br, blockSize*int(bps)); err != nil { return nil } - _ = writeManyBits(bw, verbatimData, blockSize*int(bps)) + //_ = writeManyBits(bw, verbatimData, blockSize*int(bps)) case subframeType < 8: //reserved return nil case subframeType < 16: //Fixed @@ -402,30 +397,30 @@ func readFlacFrame(hdr *FLACHeaderPacket, br *bitio.Reader) *FLACPacket { return nil } - var warmupData []byte - if warmupData, err = readManyBits(br, order*int(bps)); err != nil { + //var warmupData []byte + if _, err = readManyBits(br, order*int(bps)); err != nil { return nil } - _ = writeManyBits(bw, warmupData, order*int(bps)) + //_ = writeManyBits(bw, warmupData, order*int(bps)) - if err = decodeResidual(br, bw, blockSize, order); err != 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 warmupData, err = readManyBits(br, order*int(bps)); err != nil { + //var warmupData []byte + if _, err = readManyBits(br, order*int(bps)); err != nil { return nil } - _ = writeManyBits(bw, warmupData, order*int(bps)) + //_ = writeManyBits(bw, warmupData, order*int(bps)) - var coefficientPrecisionLen, quantizationLevel uint64 + var coefficientPrecisionLen uint64 if coefficientPrecisionLen, err = br.ReadBits(4); err != nil { return nil } - _ = bw.WriteBits(coefficientPrecisionLen, 4) + //_ = bw.WriteBits(coefficientPrecisionLen, 4) if coefficientPrecisionLen == 0xF { return nil @@ -433,35 +428,30 @@ func readFlacFrame(hdr *FLACHeaderPacket, br *bitio.Reader) *FLACPacket { precision := int(coefficientPrecisionLen) + 1 - if quantizationLevel, err = br.ReadBits(5); err != nil { + //var quantizationLevel uint64 + if _, err = br.ReadBits(5); err != nil { return nil } - _ = bw.WriteBits(quantizationLevel, 5) + //_ = bw.WriteBits(quantizationLevel, 5) - var coefficientData []byte - if coefficientData, err = readManyBits(br, order*precision); err != nil { + //var coefficientData []byte + if _, err = readManyBits(br, order*precision); err != nil { return nil } - _ = writeManyBits(bw, coefficientData, order*precision) + //_ = writeManyBits(bw, coefficientData, order*precision) - if err = decodeResidual(br, bw, blockSize, order); err != nil { + if err = decodeResidual(br, blockSize, order); err != nil { return nil } } } - if n := br.Align(); n > 0 { - _ = bw.WriteBits(0, n) - if n, err = bw.Align(); err != nil || n != 0 { - //Alignment mismatch! - return nil - } - } + br.Align() - _ = bw.Close() + buf := bfr.GetBuffer() - p.FrameData = make([]byte, buf.Len()) - copy(p.FrameData, buf.Bytes()) + p.FrameData = make([]byte, len(buf)) + copy(p.FrameData, buf) if p.CRC16, err = br.ReadBits(16); err != nil { return nil @@ -470,12 +460,12 @@ func readFlacFrame(hdr *FLACHeaderPacket, br *bitio.Reader) *FLACPacket { return p } -func decodeResidual(br *bitio.Reader, bw *bitio.Writer, blockSize, predictorOrder int) (err error) { +func decodeResidual(br *bitio.Reader, blockSize, predictorOrder int) (err error) { var entropyCodingMethod, partitionOrder uint64 if entropyCodingMethod, err = br.ReadBits(2); err != nil { return err } - _ = bw.WriteBits(entropyCodingMethod, 2) + //_ = bw.WriteBits(entropyCodingMethod, 2) paramSize := 0 @@ -491,7 +481,7 @@ func decodeResidual(br *bitio.Reader, bw *bitio.Writer, blockSize, predictorOrde if partitionOrder, err = br.ReadBits(4); err != nil { return err } - _ = bw.WriteBits(partitionOrder, 4) + //_ = bw.WriteBits(partitionOrder, 4) partitions := 1 << partitionOrder @@ -500,7 +490,7 @@ func decodeResidual(br *bitio.Reader, bw *bitio.Writer, blockSize, predictorOrde if riceParameter, err = br.ReadBits(uint8(paramSize)); err != nil { return err } - _ = bw.WriteBitsUnsafe(riceParameter, uint8(paramSize)) + //_ = bw.WriteBitsUnsafe(riceParameter, uint8(paramSize)) var nsamples int if partition != 0 { @@ -517,36 +507,36 @@ func decodeResidual(br *bitio.Reader, bw *bitio.Writer, blockSize, predictorOrde if riceParameter2, err = br.ReadBits(5); err != nil { return err } - _ = bw.WriteBitsUnsafe(riceParameter2, 5) + //_ = bw.WriteBitsUnsafe(riceParameter2, 5) if riceParameter2 > 0 { - var sampleData []byte - if sampleData, err = readManyBits(br, nsamples*int(riceParameter2)); err != nil { + //var sampleData []byte + if _, err = readManyBits(br, nsamples*int(riceParameter2)); err != nil { return err } - _ = writeManyBits(bw, sampleData, nsamples*int(riceParameter2)) + //_ = writeManyBits(bw, sampleData, nsamples*int(riceParameter2)) } } else { //TODO: optimize this! - var high, low uint64 + //var high, low uint64 if riceParameter == 0 { for j := 0; j < nsamples; j++ { - if high, err = readUnary(br); err != nil { + if _, err = readUnary(br); err != nil { return err } - _ = writeUnary(bw, high) + //_ = writeUnary(bw, high) } } else { for j := 0; j < nsamples; j++ { - if high, err = readUnary(br); err != nil { + if _, err = readUnary(br); err != nil { return err } - _ = writeUnary(bw, high) - if low, err = br.ReadBits(uint8(riceParameter)); err != nil { + //_ = writeUnary(bw, high) + if _, err = br.ReadBits(uint8(riceParameter)); err != nil { return err } - _ = bw.WriteBitsUnsafe(low, uint8(riceParameter)) + //_ = bw.WriteBitsUnsafe(low, uint8(riceParameter)) } } } @@ -934,12 +924,64 @@ func (p *FLACPacket) GetDataOffset(offset int64) []byte { 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 { @@ -948,7 +990,7 @@ func (o *FLACPacketizer) GetPacket() Packet { return o.hdr } - packet := readFlacFrame(o.hdr, o.br) + packet := readFlacFrame(o.hdr, o.br, o.bfr) if packet == nil { return nil }