mirror of https://bitbucket.org/ausocean/av.git
adpcm: encoder and decoder structs are now exported
This commit is contained in:
parent
537d5bab73
commit
a1fe6c6deb
|
@ -27,7 +27,7 @@ LICENSE
|
||||||
Reference algorithms for ADPCM compression and decompression are in part 6.
|
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 Encoder and Decoder structs to encode and decode PCM to and from ADPCM.
|
||||||
package adpcm
|
package adpcm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -69,8 +69,8 @@ var stepTable = []int16{
|
||||||
32767,
|
32767,
|
||||||
}
|
}
|
||||||
|
|
||||||
// encoder is used to encode to ADPCM from PCM data.
|
// Encoder is used to encode to ADPCM from PCM data.
|
||||||
type encoder struct {
|
type Encoder struct {
|
||||||
// dst is the destination for encoded data.
|
// dst is the destination for encoded data.
|
||||||
dst io.Writer
|
dst io.Writer
|
||||||
|
|
||||||
|
@ -79,8 +79,8 @@ type encoder struct {
|
||||||
index int16
|
index int16
|
||||||
}
|
}
|
||||||
|
|
||||||
// decoder is used to decode from ADPCM to PCM data.
|
// Decoder is used to decode from ADPCM to PCM data.
|
||||||
type decoder struct {
|
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 output buffer that implements io.Writer and io.Bytewriter, ie. where the decoded PCM data is written to.
|
||||||
dst io.Writer
|
dst io.Writer
|
||||||
|
|
||||||
|
@ -90,9 +90,9 @@ type decoder struct {
|
||||||
step int16
|
step int16
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEncoder retuns a new ADPCM encoder.
|
// NewEncoder retuns a new ADPCM Encoder.
|
||||||
func NewEncoder(dst io.Writer) *encoder {
|
func NewEncoder(dst io.Writer) *Encoder {
|
||||||
e := encoder{
|
e := Encoder{
|
||||||
dst: dst,
|
dst: dst,
|
||||||
}
|
}
|
||||||
return &e
|
return &e
|
||||||
|
@ -100,7 +100,7 @@ func NewEncoder(dst io.Writer) *encoder {
|
||||||
|
|
||||||
// encodeSample takes a single 16 bit PCM sample and
|
// encodeSample takes a single 16 bit PCM sample and
|
||||||
// returns a byte of which the last 4 bits are an encoded ADPCM nibble.
|
// returns a byte of which the last 4 bits are an encoded ADPCM nibble.
|
||||||
func (e *encoder) encodeSample(sample int16) byte {
|
func (e *Encoder) encodeSample(sample int16) byte {
|
||||||
// Find difference between the sample and the previous estimation.
|
// Find difference between the sample and the previous estimation.
|
||||||
delta := capAdd16(sample, -e.est)
|
delta := capAdd16(sample, -e.est)
|
||||||
|
|
||||||
|
@ -144,10 +144,10 @@ func (e *encoder) encodeSample(sample int16) byte {
|
||||||
return nib
|
return nib
|
||||||
}
|
}
|
||||||
|
|
||||||
// calcHead sets the state for the encoder by running the first sample through
|
// 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).
|
// 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 io.Writer (dst) along with any errors.
|
||||||
func (e *encoder) calcHead(sample []byte, pad bool) (int, error) {
|
func (e *Encoder) calcHead(sample []byte, pad bool) (int, error) {
|
||||||
// Check that we are given 1 sample.
|
// Check that we are given 1 sample.
|
||||||
if len(sample) != byteDepth {
|
if len(sample) != byteDepth {
|
||||||
return 0, fmt.Errorf("length of given byte array is: %v, expected: %v", len(sample), byteDepth)
|
return 0, fmt.Errorf("length of given byte array is: %v, expected: %v", len(sample), byteDepth)
|
||||||
|
@ -176,10 +176,10 @@ func (e *encoder) calcHead(sample []byte, pad bool) (int, error) {
|
||||||
return n, nil
|
return n, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// init initializes the encoder's estimation to the first uncompressed sample and the index to
|
// init initializes the Encoder's estimation to the first uncompressed sample and the index to
|
||||||
// point to a suitable quantizer step size.
|
// point to a suitable quantizer step size.
|
||||||
// The suitable step size is the closest step size in the stepTable to half the absolute difference of the first two samples.
|
// The suitable step size is the closest step size in the stepTable to half the absolute difference of the first two samples.
|
||||||
func (e *encoder) init(samples []byte) {
|
func (e *Encoder) init(samples []byte) {
|
||||||
int1 := int16(binary.LittleEndian.Uint16(samples[:byteDepth]))
|
int1 := int16(binary.LittleEndian.Uint16(samples[:byteDepth]))
|
||||||
int2 := int16(binary.LittleEndian.Uint16(samples[byteDepth:initBytes]))
|
int2 := int16(binary.LittleEndian.Uint16(samples[byteDepth:initBytes]))
|
||||||
e.est = int1
|
e.est = int1
|
||||||
|
@ -197,10 +197,10 @@ func (e *encoder) init(samples []byte) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write takes a slice of bytes of arbitrary length representing pcm and encodes it into adpcm.
|
// Write takes a slice of bytes of arbitrary length representing pcm and encodes it into adpcm.
|
||||||
// It writes its output to the encoder's dst.
|
// It writes its output to the Encoder's dst.
|
||||||
// The number of bytes written out is returned along with any error that occured.
|
// The number of bytes written out is returned along with any error that occured.
|
||||||
func (e *encoder) Write(b []byte) (int, error) {
|
func (e *Encoder) Write(b []byte) (int, error) {
|
||||||
// Check that pcm has enough data to initialize decoder.
|
// Check that pcm has enough data to initialize Decoder.
|
||||||
pcmLen := len(b)
|
pcmLen := len(b)
|
||||||
if pcmLen < initBytes {
|
if pcmLen < initBytes {
|
||||||
return 0, fmt.Errorf("length of given byte array must be >= %v", initBytes)
|
return 0, fmt.Errorf("length of given byte array must be >= %v", initBytes)
|
||||||
|
@ -240,9 +240,9 @@ func (e *encoder) Write(b []byte) (int, error) {
|
||||||
return n, nil
|
return n, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDecoder retuns a new ADPCM decoder.
|
// NewDecoder retuns a new ADPCM Decoder.
|
||||||
func NewDecoder(dst io.Writer) *decoder {
|
func NewDecoder(dst io.Writer) *Decoder {
|
||||||
d := decoder{
|
d := Decoder{
|
||||||
dst: dst,
|
dst: dst,
|
||||||
}
|
}
|
||||||
return &d
|
return &d
|
||||||
|
@ -250,7 +250,7 @@ func NewDecoder(dst io.Writer) *decoder {
|
||||||
|
|
||||||
// decodeSample takes a byte, the last 4 bits of which contain a single
|
// decodeSample takes a byte, the last 4 bits of which contain a single
|
||||||
// 4 bit ADPCM nibble, and returns a 16 bit decoded PCM sample.
|
// 4 bit ADPCM nibble, and returns a 16 bit decoded PCM sample.
|
||||||
func (d *decoder) decodeSample(nibble byte) int16 {
|
func (d *Decoder) decodeSample(nibble byte) int16 {
|
||||||
// Calculate difference.
|
// Calculate difference.
|
||||||
var diff int16
|
var diff int16
|
||||||
if nibble&4 != 0 {
|
if nibble&4 != 0 {
|
||||||
|
@ -289,10 +289,10 @@ func (d *decoder) decodeSample(nibble byte) int16 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write takes a slice of bytes of arbitrary length representing adpcm and decodes it into pcm.
|
// Write takes a slice of bytes of arbitrary length representing adpcm and decodes it into pcm.
|
||||||
// It writes its output to the decoder's dst.
|
// It writes its output to the Decoder's dst.
|
||||||
// The number of bytes written out is returned along with any error that occured.
|
// The number of bytes written out is returned along with any error that occured.
|
||||||
func (d *decoder) Write(b []byte) (int, error) {
|
func (d *Decoder) Write(b []byte) (int, error) {
|
||||||
// Initialize decoder with first 4 bytes of b.
|
// Initialize Decoder with first 4 bytes of b.
|
||||||
d.est = int16(binary.LittleEndian.Uint16(b[:byteDepth]))
|
d.est = int16(binary.LittleEndian.Uint16(b[:byteDepth]))
|
||||||
d.index = int16(b[byteDepth])
|
d.index = int16(b[byteDepth])
|
||||||
d.step = stepTable[d.index]
|
d.step = stepTable[d.index]
|
||||||
|
|
Loading…
Reference in New Issue