From e55cc27a554b7dfa44d779bd564b552aa8f73f62 Mon Sep 17 00:00:00 2001 From: Trek H Date: Fri, 26 Apr 2019 19:58:30 +0930 Subject: [PATCH] adpcm: changed adpcm to not have blocks of fixed size --- codec/adpcm/adpcm.go | 43 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/codec/adpcm/adpcm.go b/codec/adpcm/adpcm.go index 3e1f48f1..f32c8875 100644 --- a/codec/adpcm/adpcm.go +++ b/codec/adpcm/adpcm.go @@ -193,7 +193,7 @@ func (d *decoder) decodeSample(nibble byte) int16 { // calcHead sets the state for the encoder by running the first sample through // the encoder, and writing the first sample to the encoder's io.Writer (dest). // It returns the number of bytes written to the encoder's io.Writer (dest) along with any errors. -func (e *encoder) calcHead(sample []byte) (int, error) { +func (e *encoder) calcHead(sample []byte, pad bool) (int, error) { // Check that we are given 1 16-bit sample (2 bytes). const sampSize = 2 if len(sample) != sampSize { @@ -214,7 +214,11 @@ func (e *encoder) calcHead(sample []byte) (int, error) { } n++ - err = e.dest.WriteByte(byte(0x00)) + if pad { + err = e.dest.WriteByte(0x01) + } else { + err = e.dest.WriteByte(0x00) + } if err != nil { return n, err } @@ -234,7 +238,7 @@ func (e *encoder) encodeBlock(block []byte) (int, error) { return 0, fmt.Errorf("unsupported block size. Given: %v, expected: %v, ie. 505 16-bit PCM samples", len(block), PcmBS) } - n, err := e.calcHead(block[0:2]) + n, err := e.calcHead(block[0:2], false) if err != nil { return n, err } @@ -300,13 +304,19 @@ func (d *decoder) decodeBlock(block []byte) (int, error) { // It writes its output to the encoder's dest. // The number of bytes written out is returned along with any error that occured. func (e *encoder) Write(inPcm []byte) (int, error) { + // Determine if there will be a byte that won't contain two full nibbles and will need padding. + pcmLen := len(inPcm) + pad := false + if (pcmLen-2)%4 != 0 { + pad = true + } - n, err := e.calcHead(inPcm[0:2]) + n, err := e.calcHead(inPcm[0:2], pad) if err != nil { return n, err } - for i := 3; i < len(inPcm); i += 4 { + for i := 3; i < pcmLen; i += 4 { nib1 := e.encodeSample(int16(binary.LittleEndian.Uint16(inPcm[i-1 : i+1]))) nib2 := e.encodeSample(int16(binary.LittleEndian.Uint16(inPcm[i+1 : i+3]))) err = e.dest.WriteByte(byte((nib2 << 4) | nib1)) @@ -315,6 +325,16 @@ func (e *encoder) Write(inPcm []byte) (int, error) { } n++ } + // If we've reached the end of the pcm data and there's a sample (2 bytes) left over, + // compress it to a nibble and leave the first half of the byte padded with 0s. + if pad { + nib := e.encodeSample(int16(binary.LittleEndian.Uint16(inPcm[pcmLen-2 : pcmLen]))) + err = e.dest.WriteByte(nib) + if err != nil { + return n, err + } + n++ + } return n, nil } @@ -335,7 +355,8 @@ func (d *decoder) Write(inAdpcm []byte) (int, error) { // For each byte, seperate it into two nibbles (each nibble is a compressed sample), // then decode each nibble and output the resulting 16-bit samples. - for i := 4; i < len(inAdpcm); i++ { + // If padding flag is true (Adpcm[3]), only decode up until the last byte, then decode that separately. + for i := 4; i < len(inAdpcm)-int(inAdpcm[3]); i++ { twoNibs := inAdpcm[i] nib2 := byte(twoNibs >> 4) nib1 := byte((nib2 << 4) ^ twoNibs) @@ -356,6 +377,16 @@ func (d *decoder) Write(inAdpcm []byte) (int, error) { return n, err } } + if inAdpcm[3] == 0x01 { + padNib := inAdpcm[len(inAdpcm)-1] + samp := make([]byte, 2) + binary.LittleEndian.PutUint16(samp, uint16(d.decodeSample(padNib))) + _n, err := d.dest.Write(samp) + n += _n + if err != nil { + return n, err + } + } return n, nil }