av/cmd/adpcm/main.go

107 lines
2.4 KiB
Go

package main
import (
"encoding/binary"
"flag"
"fmt"
"io/ioutil"
"os"
"github.com/bovarysme/adpcm"
"github.com/go-audio/audio"
"github.com/go-audio/wav"
"github.com/pkg/errors"
)
// This program is for compare data size of pcm and adpcm, it takes a wav file and compresses and encodes it to adpcm,
// the adpcm byte array is stored as a file and then the adpcm is decoded and the result saved as final.wav
func main() {
//open wav
var wavPath string
flag.StringVar(&wavPath, "path", "before_compression.wav", "file path of input data")
flag.Parse()
f, err := os.Open(wavPath)
if err != nil {
panic(err)
}
defer f.Close()
//decode wav
dec := wav.NewDecoder(f)
if !dec.IsValidFile() {
panic(errors.Errorf("invalid WAV file %q", wavPath))
}
sampleRate, nchannels, bps := int(dec.SampleRate), int(dec.NumChans), int(dec.BitDepth)
buf, err := dec.FullPCMBuffer()
if err != nil {
panic(err)
}
fmt.Println("Decoded wav. First 8 samples: ")
for i := 0; i < len(buf.Data) && i < 8; i++ {
fmt.Print(buf.Data[i], ", ")
}
fmt.Println()
// save pcm to file
var pcmBytes []byte
for _, sample := range buf.Data {
bs := make([]byte, 2)
binary.LittleEndian.PutUint16(bs, uint16(sample))
pcmBytes = append(pcmBytes, bs[0], bs[1])
}
pcmPath := "out.pcm"
err = ioutil.WriteFile(pcmPath, pcmBytes, 0644)
if err != nil {
panic(err)
}
fmt.Println("Saved raw PCM to " + pcmPath + ". First 8 bytes: ")
for i := 0; i < len(pcmBytes) && i < 8; i++ {
fmt.Print(pcmBytes[i], ", ")
}
fmt.Println()
//encode adpcm
var comp []byte
adpcm.Encode(buf.Data, &comp)
// save adpcm to file
adpcmPath := "out.adpcm"
err = ioutil.WriteFile(adpcmPath, comp, 0644)
if err != nil {
panic(err)
}
//decode adpcm
var decoded []int
deco := adpcm.NewDecoder(nchannels)
deco.Decode(comp, &decoded)
//encode wav and save to file
finalWavPath := "final.wav"
of, err := os.Create(finalWavPath)
if err != nil {
panic(err)
}
defer of.Close()
sampleBytes := bps / 8
// normal uncompressed WAV format
wavformat := 1
enc := wav.NewEncoder(of, sampleRate, bps, nchannels, wavformat)
format := &audio.Format{
NumChannels: nchannels,
SampleRate: sampleRate,
}
intBuf := &audio.IntBuffer{Data: decoded, Format: format, SourceBitDepth: sampleBytes * 8}
if err := enc.Write(intBuf); err != nil {
panic(err)
}
if err := enc.Close(); err != nil {
panic(err)
}
fmt.Printf("Saved audio to %s\n", finalWavPath)
}