ADPCM: encoder now using byte writer instead of returning byte slices

This commit is contained in:
Trek H 2019-02-28 12:53:51 +10:30
parent d1c37569c4
commit 3ebf928ffe
2 changed files with 21 additions and 23 deletions

View File

@ -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.

View File

@ -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")
}
}