mirror of https://bitbucket.org/ausocean/av.git
ADPCM: unexported encoder and decoder structs, documented Write funcs.
This commit is contained in:
parent
fdc4d880ac
commit
d4e0c87635
|
@ -38,31 +38,31 @@ import (
|
|||
"fmt"
|
||||
)
|
||||
|
||||
// Encoder is used to encode to ADPCM from PCM data.
|
||||
// encoder is used to encode to ADPCM from PCM data.
|
||||
// pred and index hold state that persists between calls to encodeSample and calcHead.
|
||||
// dest is the output buffer that implements io.writer and io.bytewriter, ie. where the encoded ADPCM data is written to.
|
||||
type Encoder struct {
|
||||
type encoder struct {
|
||||
dest *bytes.Buffer
|
||||
pred int16
|
||||
index int16
|
||||
}
|
||||
|
||||
// Decoder is used to decode from ADPCM to PCM data.
|
||||
// decoder is used to decode from ADPCM to PCM data.
|
||||
// pred, index, and step hold state that persists between calls to decodeSample.
|
||||
// dest is the output buffer that implements io.writer and io.bytewriter, ie. where the decoded PCM data is written to.
|
||||
type Decoder struct {
|
||||
type decoder struct {
|
||||
dest *bytes.Buffer
|
||||
pred int16
|
||||
index int16
|
||||
step int16
|
||||
}
|
||||
|
||||
// PcmBS is the size of the blocks that an Encoder uses.
|
||||
// 'EncodeBlock' will encode PcmBS bytes at a time and the output will be AdpcmBS bytes long.
|
||||
// PcmBS is the size of the blocks that an encoder uses.
|
||||
// 'encodeBlock' will encode PcmBS bytes at a time and the output will be AdpcmBS bytes long.
|
||||
const PcmBS = 1010
|
||||
|
||||
// AdpcmBS is the size of the blocks that a Decoder uses.
|
||||
// 'DecodeBlock' will decode AdpcmBS bytes at a time and the output will be PcmBS bytes long.
|
||||
// AdpcmBS is the size of the blocks that a decoder uses.
|
||||
// 'decodeBlock' will decode AdpcmBS bytes at a time and the output will be PcmBS bytes long.
|
||||
const AdpcmBS = 256
|
||||
|
||||
// Table of index changes (see spec).
|
||||
|
@ -88,16 +88,16 @@ var stepTable = []int16{
|
|||
}
|
||||
|
||||
// NewEncoder retuns a new ADPCM encoder.
|
||||
func NewEncoder(dst *bytes.Buffer) *Encoder {
|
||||
e := Encoder{
|
||||
func NewEncoder(dst *bytes.Buffer) *encoder {
|
||||
e := encoder{
|
||||
dest: dst,
|
||||
}
|
||||
return &e
|
||||
}
|
||||
|
||||
// NewDecoder retuns a new ADPCM decoder.
|
||||
func NewDecoder(dst *bytes.Buffer) *Decoder {
|
||||
d := Decoder{
|
||||
func NewDecoder(dst *bytes.Buffer) *decoder {
|
||||
d := decoder{
|
||||
step: stepTable[0],
|
||||
dest: dst,
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ func NewDecoder(dst *bytes.Buffer) *Decoder {
|
|||
|
||||
// encodeSample takes a single 16 bit PCM sample and
|
||||
// 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 of actual sample from encoder's prediction.
|
||||
delta := sample - e.pred
|
||||
|
||||
|
@ -139,6 +139,7 @@ func (e *Encoder) encodeSample(sample int16) byte {
|
|||
}
|
||||
|
||||
e.index += indexTable[nib&7]
|
||||
|
||||
// Check for underflow and overflow.
|
||||
if e.index < 0 {
|
||||
e.index = 0
|
||||
|
@ -151,7 +152,7 @@ func (e *Encoder) encodeSample(sample int16) byte {
|
|||
|
||||
// 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.
|
||||
func (d *Decoder) decodeSample(nibble byte) int16 {
|
||||
func (d *decoder) decodeSample(nibble byte) int16 {
|
||||
// Calculate difference.
|
||||
var diff int16
|
||||
if nibble&4 != 0 {
|
||||
|
@ -191,7 +192,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.
|
||||
func (e *Encoder) calcHead(sample []byte) (int, error) {
|
||||
func (e *encoder) calcHead(sample []byte) (int, error) {
|
||||
// Check that we are given 1 16-bit sample (2 bytes).
|
||||
const sampSize = 2
|
||||
if len(sample) != sampSize {
|
||||
|
@ -220,13 +221,13 @@ func (e *Encoder) calcHead(sample []byte) (int, error) {
|
|||
return writ, nil
|
||||
}
|
||||
|
||||
// EncodeBlock takes a slice of 1010 bytes (505 16-bit PCM samples).
|
||||
// encodeBlock takes a slice of 1010 bytes (505 16-bit PCM samples).
|
||||
// It outputs encoded (compressed) bytes (each byte containing two ADPCM nibbles) to the encoder's dest writer.
|
||||
// Note: nibbles are output in little endian order, eg. n1n0 n3n2 n5n4...
|
||||
// Note: first 4 bytes are for initializing the decoder before decoding a block.
|
||||
// - First two bytes contain the first 16-bit sample uncompressed.
|
||||
// - Third byte is the decoder's starting index for the block, the fourth is padding and ignored.
|
||||
func (e *Encoder) EncodeBlock(block []byte) (int, error) {
|
||||
func (e *encoder) encodeBlock(block []byte) (int, error) {
|
||||
writ := 0
|
||||
if len(block) != PcmBS {
|
||||
return writ, fmt.Errorf("unsupported block size. Given: %v, expected: %v, ie. 505 16-bit PCM samples", len(block), PcmBS)
|
||||
|
@ -250,9 +251,9 @@ func (e *Encoder) EncodeBlock(block []byte) (int, error) {
|
|||
return writ, nil
|
||||
}
|
||||
|
||||
// DecodeBlock takes a slice of 256 bytes, each byte after the first 4 should contain two ADPCM encoded nibbles.
|
||||
// decodeBlock takes a slice of 256 bytes, each byte after the first 4 should contain two ADPCM encoded nibbles.
|
||||
// It outputs the resulting decoded (decompressed) 16-bit PCM samples to the decoder's dest writer.
|
||||
func (d *Decoder) DecodeBlock(block []byte) (int, error) {
|
||||
func (d *decoder) decodeBlock(block []byte) (int, error) {
|
||||
writ := 0
|
||||
if len(block) != AdpcmBS {
|
||||
return writ, fmt.Errorf("unsupported block size. Given: %v, expected: %v", len(block), AdpcmBS)
|
||||
|
@ -294,12 +295,15 @@ func (d *Decoder) DecodeBlock(block []byte) (int, error) {
|
|||
return writ, nil
|
||||
}
|
||||
|
||||
func (e *Encoder) Write(inPcm []byte) (int, error) {
|
||||
// Write takes a slice of bytes of arbitrary length representing pcm and encodes in into adpcm.
|
||||
// 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) {
|
||||
numBlocks := len(inPcm) / PcmBS
|
||||
writ := 0
|
||||
for i := 0; i < numBlocks; i++ {
|
||||
block := inPcm[PcmBS*i : PcmBS*(i+1)]
|
||||
writB, err := e.EncodeBlock(block)
|
||||
writB, err := e.encodeBlock(block)
|
||||
writ += writB
|
||||
if err != nil {
|
||||
return writ, err
|
||||
|
@ -309,12 +313,15 @@ func (e *Encoder) Write(inPcm []byte) (int, error) {
|
|||
return writ, nil
|
||||
}
|
||||
|
||||
func (d *Decoder) Write(inAdpcm []byte) (int, error) {
|
||||
// Write takes a slice of bytes of arbitrary length representing adpcm and decodes in into pcm.
|
||||
// It writes its output to the decoder's dest.
|
||||
// The number of bytes written out is returned along with any error that occured.
|
||||
func (d *decoder) Write(inAdpcm []byte) (int, error) {
|
||||
numBlocks := len(inAdpcm) / AdpcmBS
|
||||
writ := 0
|
||||
for i := 0; i < numBlocks; i++ {
|
||||
block := inAdpcm[AdpcmBS*i : AdpcmBS*(i+1)]
|
||||
writB, err := d.DecodeBlock(block)
|
||||
writB, err := d.decodeBlock(block)
|
||||
writ += writB
|
||||
if err != nil {
|
||||
return writ, err
|
||||
|
|
Loading…
Reference in New Issue