From 7d3829d19f5128a59cb8d3ddfb88aacbb875d570 Mon Sep 17 00:00:00 2001 From: Trek H Date: Wed, 13 Feb 2019 16:53:25 +1030 Subject: [PATCH] ADPCM: pre-allocating memory for entire known length of output byte slice --- cmd/adpcm/decode-pcm/decode-pcm.go | 30 +++++++++++++------------ cmd/adpcm/encode-pcm/encode-pcm.go | 29 +++++++++++++----------- stream/adpcm/adpcm_test.go | 36 +++++++++++++----------------- 3 files changed, 48 insertions(+), 47 deletions(-) diff --git a/cmd/adpcm/decode-pcm/decode-pcm.go b/cmd/adpcm/decode-pcm/decode-pcm.go index 64973e3f..fded5005 100644 --- a/cmd/adpcm/decode-pcm/decode-pcm.go +++ b/cmd/adpcm/decode-pcm/decode-pcm.go @@ -29,6 +29,7 @@ package main import ( "flag" + "fmt" "io/ioutil" "bitbucket.org/ausocean/av/stream/adpcm" @@ -39,30 +40,30 @@ import ( func main() { var inPath string var outPath string - flag.StringVar(&inPath, "in", "encoded.adpcm", "file path of input") flag.StringVar(&outPath, "out", "decoded.pcm", "file path of output data") flag.Parse() - //read adpcm + // read adpcm comp, err := ioutil.ReadFile(inPath) if err != nil { panic(err) } + fmt.Println("Read", len(comp), "bytes from file", inPath) - //decode adpcm - var decoded []byte - start := 0 - for i := 0; i < len(comp); i++ { - if i%256 == 255 { - block := comp[start : i+1] - decBlock, err := adpcm.DecodeBlock(block) - if err != nil { - panic(err) - } - decoded = append(decoded, decBlock...) - start = i + 1 + // decode adpcm + inBSize := 256 + numBlocks := int(len(comp) / inBSize) + outBSize := 2 + (inBSize-4)*4 // 2 bytes are copied, 2 are used as block header info, the remaining bytes are decompressed 1:4 + decoded := make([]byte, 0, outBSize*numBlocks) + for i, start := inBSize-1, 0; i < len(comp); i += inBSize { + block := comp[start : i+1] + decBlock, err := adpcm.DecodeBlock(block) + if err != nil { + panic(err) } + decoded = append(decoded, decBlock...) + start = i + 1 } // save pcm to file @@ -70,4 +71,5 @@ func main() { if err != nil { panic(err) } + fmt.Println("Decoded and wrote", len(decoded), "bytes to file", outPath) } diff --git a/cmd/adpcm/encode-pcm/encode-pcm.go b/cmd/adpcm/encode-pcm/encode-pcm.go index 47ba6e07..002e2c22 100644 --- a/cmd/adpcm/encode-pcm/encode-pcm.go +++ b/cmd/adpcm/encode-pcm/encode-pcm.go @@ -29,11 +29,14 @@ package main import ( "flag" + "fmt" "io/ioutil" "bitbucket.org/ausocean/av/stream/adpcm" ) +// This program accepts an input pcm file and outputs an encoded adpcm file. +// Input and output file names can be specified as arguments. func main() { var inPath string var adpcmPath string @@ -46,22 +49,21 @@ func main() { if err != nil { panic(err) } + fmt.Println("Read", len(pcm), "bytes from file", inPath) //encode adpcm - var comp []byte - start := 0 - bSize := 1010 - for i := 0; i < len(pcm); i++ { - if i%bSize == bSize-1 { - block := pcm[start : i+1] - - encBlock, err := adpcm.EncodeBlock(block) - if err != nil { - panic(err) - } - comp = append(comp, encBlock...) - start = i + 1 + inBSize := 1010 + numBlocks := int(len(pcm) / inBSize) + outBSize := int(float32(inBSize/4) + float32(3.5)) // compression is 4:1 and 3.5 bytes of info are added to each block + comp := make([]byte, 0, outBSize*numBlocks) + for i, start := inBSize-1, 0; i < len(pcm); i += inBSize { + block := pcm[start : i+1] + encBlock, err := adpcm.EncodeBlock(block) + if err != nil { + panic(err) } + comp = append(comp, encBlock...) + start = i + 1 } // save adpcm to file @@ -69,4 +71,5 @@ func main() { if err != nil { panic(err) } + fmt.Println("Encoded and wrote", len(comp), "bytes to file", adpcmPath) } diff --git a/stream/adpcm/adpcm_test.go b/stream/adpcm/adpcm_test.go index 4d40f3e9..bbda1d31 100644 --- a/stream/adpcm/adpcm_test.go +++ b/stream/adpcm/adpcm_test.go @@ -44,18 +44,16 @@ func TestEncodeBlock(t *testing.T) { //encode adpcm var comp []byte - start := 0 - for i := 0; i < len(pcm); i++ { - if i%1010 == 1009 { - block := pcm[start : i+1] + bSize := 1010 + for i, start := bSize-1, 0; i < len(pcm); i += bSize { + block := pcm[start : i+1] - encBlock, err := EncodeBlock(block) - if err != nil { - t.Errorf("Unable to encode block: %v", err) - } - comp = append(comp, encBlock...) - start = i + 1 + encBlock, err := EncodeBlock(block) + if err != nil { + t.Errorf("Unable to encode block: %v", err) } + comp = append(comp, encBlock...) + start = i + 1 } //read expected adpcm file @@ -80,17 +78,15 @@ func TestDecodeBlock(t *testing.T) { //decode adpcm var decoded []byte - start := 0 - for i := 0; i < len(comp); i++ { - if i%256 == 255 { - block := comp[start : i+1] - decBlock, err := DecodeBlock(block) - if err != nil { - t.Errorf("Unable to decode block: %v", err) - } - decoded = append(decoded, decBlock...) - start = i + 1 + bSize := 256 + for i, start := bSize-1, 0; i < len(comp); i += bSize { + block := comp[start : i+1] + decBlock, err := DecodeBlock(block) + if err != nil { + t.Errorf("Unable to decode block: %v", err) } + decoded = append(decoded, decBlock...) + start = i + 1 } //read expected pcm file