adpcm: changed adpcm to not have blocks of fixed size

This commit is contained in:
Trek H 2019-04-26 19:58:30 +09:30
parent d136d13e38
commit e55cc27a55
1 changed files with 37 additions and 6 deletions

View File

@ -193,7 +193,7 @@ func (d *decoder) decodeSample(nibble byte) int16 {
// 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 (dest). // the encoder, and writing the first sample to the encoder's io.Writer (dest).
// It returns the number of bytes written to the encoder's io.Writer (dest) along with any errors. // It returns the number of bytes written to the encoder's io.Writer (dest) along with any errors.
func (e *encoder) calcHead(sample []byte) (int, error) { func (e *encoder) calcHead(sample []byte, pad bool) (int, error) {
// Check that we are given 1 16-bit sample (2 bytes). // Check that we are given 1 16-bit sample (2 bytes).
const sampSize = 2 const sampSize = 2
if len(sample) != sampSize { if len(sample) != sampSize {
@ -214,7 +214,11 @@ func (e *encoder) calcHead(sample []byte) (int, error) {
} }
n++ n++
err = e.dest.WriteByte(byte(0x00)) if pad {
err = e.dest.WriteByte(0x01)
} else {
err = e.dest.WriteByte(0x00)
}
if err != nil { if err != nil {
return n, err return n, err
} }
@ -234,7 +238,7 @@ func (e *encoder) encodeBlock(block []byte) (int, error) {
return 0, fmt.Errorf("unsupported block size. Given: %v, expected: %v, ie. 505 16-bit PCM samples", len(block), PcmBS) return 0, fmt.Errorf("unsupported block size. Given: %v, expected: %v, ie. 505 16-bit PCM samples", len(block), PcmBS)
} }
n, err := e.calcHead(block[0:2]) n, err := e.calcHead(block[0:2], false)
if err != nil { if err != nil {
return n, err return n, err
} }
@ -300,13 +304,19 @@ func (d *decoder) decodeBlock(block []byte) (int, error) {
// It writes its output to the encoder's dest. // It writes its output to the encoder's dest.
// 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(inPcm []byte) (int, error) { func (e *encoder) Write(inPcm []byte) (int, error) {
// Determine if there will be a byte that won't contain two full nibbles and will need padding.
pcmLen := len(inPcm)
pad := false
if (pcmLen-2)%4 != 0 {
pad = true
}
n, err := e.calcHead(inPcm[0:2]) n, err := e.calcHead(inPcm[0:2], pad)
if err != nil { if err != nil {
return n, err return n, err
} }
for i := 3; i < len(inPcm); i += 4 { for i := 3; i < pcmLen; i += 4 {
nib1 := e.encodeSample(int16(binary.LittleEndian.Uint16(inPcm[i-1 : i+1]))) nib1 := e.encodeSample(int16(binary.LittleEndian.Uint16(inPcm[i-1 : i+1])))
nib2 := e.encodeSample(int16(binary.LittleEndian.Uint16(inPcm[i+1 : i+3]))) nib2 := e.encodeSample(int16(binary.LittleEndian.Uint16(inPcm[i+1 : i+3])))
err = e.dest.WriteByte(byte((nib2 << 4) | nib1)) err = e.dest.WriteByte(byte((nib2 << 4) | nib1))
@ -315,6 +325,16 @@ func (e *encoder) Write(inPcm []byte) (int, error) {
} }
n++ n++
} }
// If we've reached the end of the pcm data and there's a sample (2 bytes) left over,
// compress it to a nibble and leave the first half of the byte padded with 0s.
if pad {
nib := e.encodeSample(int16(binary.LittleEndian.Uint16(inPcm[pcmLen-2 : pcmLen])))
err = e.dest.WriteByte(nib)
if err != nil {
return n, err
}
n++
}
return n, nil return n, nil
} }
@ -335,7 +355,8 @@ func (d *decoder) Write(inAdpcm []byte) (int, error) {
// For each byte, seperate it into two nibbles (each nibble is a compressed sample), // For each byte, seperate it into two nibbles (each nibble is a compressed sample),
// then decode each nibble and output the resulting 16-bit samples. // then decode each nibble and output the resulting 16-bit samples.
for i := 4; i < len(inAdpcm); i++ { // If padding flag is true (Adpcm[3]), only decode up until the last byte, then decode that separately.
for i := 4; i < len(inAdpcm)-int(inAdpcm[3]); i++ {
twoNibs := inAdpcm[i] twoNibs := inAdpcm[i]
nib2 := byte(twoNibs >> 4) nib2 := byte(twoNibs >> 4)
nib1 := byte((nib2 << 4) ^ twoNibs) nib1 := byte((nib2 << 4) ^ twoNibs)
@ -356,6 +377,16 @@ func (d *decoder) Write(inAdpcm []byte) (int, error) {
return n, err return n, err
} }
} }
if inAdpcm[3] == 0x01 {
padNib := inAdpcm[len(inAdpcm)-1]
samp := make([]byte, 2)
binary.LittleEndian.PutUint16(samp, uint16(d.decodeSample(padNib)))
_n, err := d.dest.Write(samp)
n += _n
if err != nil {
return n, err
}
}
return n, nil return n, nil
} }