From 762653b59a182b89746a195144f8ae854e22e8f4 Mon Sep 17 00:00:00 2001 From: Trek H Date: Wed, 29 May 2019 02:57:17 +0930 Subject: [PATCH] adpcm: naming and syntactical changes --- codec/adpcm/adpcm.go | 86 ++++++++++++++++++++------------------------ 1 file changed, 39 insertions(+), 47 deletions(-) diff --git a/codec/adpcm/adpcm.go b/codec/adpcm/adpcm.go index 352929f1..ce8ae9f7 100644 --- a/codec/adpcm/adpcm.go +++ b/codec/adpcm/adpcm.go @@ -27,7 +27,7 @@ LICENSE Reference algorithms for ADPCM compression and decompression are in part 6. */ -// Package adpcm provides Encoder and Decoder structs to encode and decode PCM to and from ADPCM. +// Package adpcm provides functions to transcode between PCM and ADPCM. package adpcm import ( @@ -38,13 +38,13 @@ import ( ) const ( - byteDepth = 2 // TODO(Trek): make configurable. - initSamps = 2 + byteDepth = 2 // We are working with 16-bit samples. TODO(Trek): make configurable. + initSamps = 2 // Number of samples used to initialise the encoder. initBytes = initSamps * byteDepth - headBytes = 4 - samplesPerEnc = 2 + headBytes = 4 // Number of bytes in the header of ADPCM. + samplesPerEnc = 2 // Number of sample encoded at a time eg. 2 16-bit samples get encoded into 1 byte. bytesPerEnc = samplesPerEnc * byteDepth - compFact = 4 + compFact = 4 // In general ADPCM compresses by a factor of 4. ) // Table of index changes (see spec). @@ -71,31 +71,26 @@ var stepTable = []int16{ // Encoder is used to encode to ADPCM from PCM data. type Encoder struct { - // dst is the destination for encoded data. + // dst is the destination for ADPCM-encoded data. dst io.Writer - // est and index hold state that persists between calls to encodeSample and calcHead. - est int16 - index int16 + est int16 // Estimation of sample based on quantised ADPCM nibble. + idx int16 // Index to step used for estimation. } // Decoder is used to decode from ADPCM to PCM data. type Decoder struct { - // dst is the output buffer that implements io.Writer and io.Bytewriter, ie. where the decoded PCM data is written to. + // dst is the destination for PCM-encoded data. dst io.Writer - // est, index, and step hold state that persists between calls to decodeSample. - est int16 - index int16 - step int16 + est int16 // Estimation of sample based on quantised ADPCM nibble. + idx int16 // Index to step used for estimation. + step int16 } // NewEncoder retuns a new ADPCM Encoder. func NewEncoder(dst io.Writer) *Encoder { - e := Encoder{ - dst: dst, - } - return &e + return &Encoder{dst: dst} } // encodeSample takes a single 16 bit PCM sample and @@ -111,7 +106,7 @@ func (e *Encoder) encodeSample(sample int16) byte { delta = -delta } - step := stepTable[e.index] + step := stepTable[e.idx] diff := step >> 3 var mask byte = 4 @@ -132,13 +127,13 @@ func (e *Encoder) encodeSample(sample int16) byte { // Adjust estimated sample based on calculated difference. e.est = capAdd16(e.est, diff) - e.index += indexTable[nib&7] + e.idx += indexTable[nib&7] // Check for underflow and overflow. - if e.index < 0 { - e.index = 0 - } else if e.index > int16(len(stepTable)-1) { - e.index = int16(len(stepTable) - 1) + if e.idx < 0 { + e.idx = 0 + } else if e.idx > int16(len(stepTable)-1) { + e.idx = int16(len(stepTable) - 1) } return nib @@ -146,7 +141,7 @@ func (e *Encoder) encodeSample(sample int16) byte { // 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 (dst). -// It returns the number of bytes written to the Encoder's io.Writer (dst) along with any errors. +// It returns the number of bytes written to the Encoder's destination and the first error encountered. func (e *Encoder) calcHead(sample []byte, pad bool) (int, error) { // Check that we are given 1 sample. if len(sample) != byteDepth { @@ -158,7 +153,7 @@ func (e *Encoder) calcHead(sample []byte, pad bool) (int, error) { return n, err } - _n, err := e.dst.Write([]byte{byte(int16(e.index))}) + _n, err := e.dst.Write([]byte{byte(int16(e.idx))}) if err != nil { return n, err } @@ -184,7 +179,7 @@ func (e *Encoder) init(samples []byte) { int2 := int16(binary.LittleEndian.Uint16(samples[byteDepth:initBytes])) e.est = int1 - halfDiff := math.Abs(math.Abs(float64(int1)) - math.Abs(float64(int2))/2.0) + halfDiff := math.Abs(math.Abs(float64(int1)) - math.Abs(float64(int2))/2) closest := math.Abs(float64(stepTable[0]) - halfDiff) var cInd int16 for i, step := range stepTable { @@ -193,7 +188,7 @@ func (e *Encoder) init(samples []byte) { cInd = int16(i) } } - e.index = cInd + e.idx = cInd } // Write takes a slice of bytes of arbitrary length representing pcm and encodes it into adpcm. @@ -242,10 +237,7 @@ func (e *Encoder) Write(b []byte) (int, error) { // NewDecoder retuns a new ADPCM Decoder. func NewDecoder(dst io.Writer) *Decoder { - d := Decoder{ - dst: dst, - } - return &d + return &Decoder{dst: dst} } // decodeSample takes a byte, the last 4 bits of which contain a single @@ -273,17 +265,17 @@ func (d *Decoder) decodeSample(nibble byte) int16 { d.est = capAdd16(d.est, diff) // Adjust index into step size lookup table using nibble. - d.index += indexTable[nibble] + d.idx += indexTable[nibble] // Check for overflow and underflow. - if d.index < 0 { - d.index = 0 - } else if d.index > int16(len(stepTable)-1) { - d.index = int16(len(stepTable) - 1) + if d.idx < 0 { + d.idx = 0 + } else if d.idx > int16(len(stepTable)-1) { + d.idx = int16(len(stepTable) - 1) } // Find new quantizer step size. - d.step = stepTable[d.index] + d.step = stepTable[d.idx] return d.est } @@ -294,8 +286,8 @@ func (d *Decoder) decodeSample(nibble byte) int16 { func (d *Decoder) Write(b []byte) (int, error) { // Initialize Decoder with first 4 bytes of b. d.est = int16(binary.LittleEndian.Uint16(b[:byteDepth])) - d.index = int16(b[byteDepth]) - d.step = stepTable[d.index] + d.idx = int16(b[byteDepth]) + d.step = stepTable[d.idx] n, err := d.dst.Write(b[:byteDepth]) if err != nil { return n, err @@ -351,13 +343,13 @@ func capAdd16(a, b int16) int16 { } } -// EncBytes will return the number of adpcm bytes that will be generated when encoding the given amount of pcm bytes (len). -func EncBytes(len int) int { - // For 'len' pcm bytes, 1 sample is left uncompressed, the rest is compressed by a factor of 4 +// EncBytes will return the number of adpcm bytes that will be generated when encoding the given amount of pcm bytes (n). +func EncBytes(n int) int { + // For 'n' pcm bytes, 1 sample is left uncompressed, the rest is compressed by a factor of 4 // and a start index and padding-flag byte are added. // Also if there are an even number of samples, there will be half a byte of padding added to the last byte. - if len%bytesPerEnc == 0 { - return (len-byteDepth)/compFact + headBytes + 1 + if n%bytesPerEnc == 0 { + return (n-byteDepth)/compFact + headBytes + 1 } - return (len-byteDepth)/compFact + headBytes + return (n-byteDepth)/compFact + headBytes }