From edb0ec6de131534e240a8685c39658e397c1a1bb Mon Sep 17 00:00:00 2001 From: Trek H Date: Thu, 28 Feb 2019 12:53:51 +1030 Subject: [PATCH] ADPCM: encoder now using byte writer instead of returning byte slices --- stream/adpcm/adpcm.go | 35 +++++++++++++++++------------------ stream/adpcm/adpcm_test.go | 9 ++++----- 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/stream/adpcm/adpcm.go b/stream/adpcm/adpcm.go index a8cc7de3..de123bf7 100644 --- a/stream/adpcm/adpcm.go +++ b/stream/adpcm/adpcm.go @@ -43,7 +43,7 @@ import ( // pred and index hold state that persists between calls to encodeSample and calcHead. // dest is the output, ie. where the encoded ADPCM data is written to. type Encoder struct { - dest io.Writer + dest io.ByteWriter pred int16 index int16 } @@ -52,7 +52,7 @@ type Encoder struct { // pred, index, and step hold state that persists between calls to decodeSample. // dest is the output, ie. where the decoded PCM data is written to. type Decoder struct { - dest io.Writer + dest io.ByteWriter pred int16 index int16 step int16 @@ -81,7 +81,7 @@ var stepTable = []int16{ } // NewEncoder retuns a new ADPCM encoder. -func NewEncoder(dst io.Writer) *Encoder { +func NewEncoder(dst io.ByteWriter) *Encoder { e := Encoder{ dest: dst, } @@ -89,7 +89,7 @@ func NewEncoder(dst io.Writer) *Encoder { } // NewDecoder retuns a new ADPCM decoder. -func NewDecoder(dst io.Writer) *Decoder { +func NewDecoder(dst io.ByteWriter) *Decoder { d := Decoder{ step: stepTable[0], dest: dst, @@ -203,48 +203,47 @@ func capAdd16(a, b int16) int16 { } } -func (e *Encoder) calcHead(sample []byte) ([]byte, error) { +func (e *Encoder) calcHead(sample []byte) error { // check that we are given 1 16-bit sample (2 bytes) sampSize := 2 if len(sample) != sampSize { - return nil, fmt.Errorf("length of given byte array is: %v, expected: %v", len(sample), sampSize) + return fmt.Errorf("length of given byte array is: %v, expected: %v", len(sample), sampSize) } intSample := int16(binary.LittleEndian.Uint16(sample)) e.encodeSample(intSample) - head := make([]byte, 2, 4) - head[0] = sample[0] - head[1] = sample[1] + e.dest.WriteByte(sample[0]) + e.dest.WriteByte(sample[1]) - head = append(head, byte(uint16(e.index))) - head = append(head, byte(0x00)) - return head, nil + e.dest.WriteByte(byte(uint16(e.index))) + e.dest.WriteByte(byte(0x00)) + return nil } // EncodeBlock takes a slice of 1010 bytes (505 16-bit PCM samples). // It returns a byte slice containing encoded (compressed) ADPCM nibbles (each byte contains two nibbles). -func (e *Encoder) EncodeBlock(block []byte) ([]byte, error) { +func (e *Encoder) EncodeBlock(block []byte) error { bSize := 1010 if len(block) != bSize { - return nil, fmt.Errorf("unsupported block size. Given: %v, expected: %v, ie. 505 16-bit PCM samples", len(block), bSize) + return fmt.Errorf("unsupported block size. Given: %v, expected: %v, ie. 505 16-bit PCM samples", len(block), bSize) } - result, err := e.calcHead(block[0:2]) + err := e.calcHead(block[0:2]) if err != nil { - return nil, err + return err } for i := 2; i < len(block); i++ { if (i+1)%4 == 0 { sample2 := e.encodeSample(int16(binary.LittleEndian.Uint16(block[i-1 : i+1]))) sample := e.encodeSample(int16(binary.LittleEndian.Uint16(block[i+1 : i+3]))) - result = append(result, byte((sample<<4)|sample2)) + e.dest.WriteByte(byte((sample << 4) | sample2)) } } - return result, nil + return nil } // DecodeBlock takes a slice of 256 bytes, each byte should contain two ADPCM encoded nibbles. diff --git a/stream/adpcm/adpcm_test.go b/stream/adpcm/adpcm_test.go index 02eb8f37..9ab1ac55 100644 --- a/stream/adpcm/adpcm_test.go +++ b/stream/adpcm/adpcm_test.go @@ -47,15 +47,14 @@ func TestEncodeBlock(t *testing.T) { inBSize := 1010 numBlocks := len(pcm) / inBSize outBSize := int(float64(inBSize)/4 + 3.5) // compression is 4:1 and 3.5 bytes of info are added to each block - comp := make([]byte, 0, outBSize*numBlocks) - enc := NewEncoder(nil) + comp := bytes.NewBuffer(make([]byte, 0, outBSize*numBlocks)) + enc := NewEncoder(comp) for i := 0; i < numBlocks; i++ { block := pcm[inBSize*i : inBSize*(i+1)] - encBlock, err := enc.EncodeBlock(block) + err := enc.EncodeBlock(block) if err != nil { log.Fatal(err) } - comp = append(comp, encBlock...) } //read expected adpcm file @@ -64,7 +63,7 @@ func TestEncodeBlock(t *testing.T) { t.Errorf("Unable to read expected ADPCM file: %v", err) } - if !bytes.Equal(comp, exp) { + if !bytes.Equal(comp.Bytes(), exp) { t.Error("ADPCM generated does not match expected ADPCM") } }