86 lines
2.2 KiB
Go
86 lines
2.2 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"flag"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
silk "github.com/git-jiadong/go-silk"
|
|
)
|
|
|
|
const sampleRate = 24000
|
|
|
|
func main() {
|
|
in := flag.String("in", "", "input .silk file")
|
|
out := flag.String("out", "", "output .wav file")
|
|
flag.Parse()
|
|
if strings.TrimSpace(*in) == "" || strings.TrimSpace(*out) == "" {
|
|
fatalf("missing -in or -out")
|
|
}
|
|
if err := decodeSilkToWav(*in, *out); err != nil {
|
|
fatalf("%v", err)
|
|
}
|
|
}
|
|
|
|
func fatalf(format string, args ...interface{}) {
|
|
_, _ = fmt.Fprintf(os.Stderr, format+"\n", args...)
|
|
os.Exit(1)
|
|
}
|
|
|
|
func decodeSilkToWav(inputPath string, outputPath string) error {
|
|
input, err := os.Open(inputPath)
|
|
if err != nil {
|
|
return fmt.Errorf("open silk failed: %w", err)
|
|
}
|
|
defer input.Close()
|
|
var pcm bytes.Buffer
|
|
writer := silk.NewWriter(&pcm)
|
|
writer.Decoder.SetSampleRate(sampleRate)
|
|
if _, err := io.Copy(writer, input); err != nil {
|
|
_ = writer.Close()
|
|
return fmt.Errorf("silk decode failed: %w", err)
|
|
}
|
|
if err := writer.Close(); err != nil {
|
|
return fmt.Errorf("silk decode close failed: %w", err)
|
|
}
|
|
if pcm.Len() == 0 {
|
|
return fmt.Errorf("silk decode returned empty pcm")
|
|
}
|
|
return writeWAV(outputPath, pcm.Bytes())
|
|
}
|
|
|
|
func writeWAV(path string, pcm []byte) error {
|
|
if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
|
|
return err
|
|
}
|
|
file, err := os.Create(path)
|
|
if err != nil {
|
|
return fmt.Errorf("create wav failed: %w", err)
|
|
}
|
|
defer file.Close()
|
|
dataSize := uint32(len(pcm))
|
|
header := &bytes.Buffer{}
|
|
header.WriteString("RIFF")
|
|
_ = binary.Write(header, binary.LittleEndian, uint32(36)+dataSize)
|
|
header.WriteString("WAVEfmt ")
|
|
_ = binary.Write(header, binary.LittleEndian, uint32(16))
|
|
_ = binary.Write(header, binary.LittleEndian, uint16(1))
|
|
_ = binary.Write(header, binary.LittleEndian, uint16(1))
|
|
_ = binary.Write(header, binary.LittleEndian, uint32(sampleRate))
|
|
_ = binary.Write(header, binary.LittleEndian, uint32(sampleRate*2))
|
|
_ = binary.Write(header, binary.LittleEndian, uint16(2))
|
|
_ = binary.Write(header, binary.LittleEndian, uint16(16))
|
|
header.WriteString("data")
|
|
_ = binary.Write(header, binary.LittleEndian, dataSize)
|
|
if _, err := file.Write(header.Bytes()); err != nil {
|
|
return err
|
|
}
|
|
_, err = file.Write(pcm)
|
|
return err
|
|
}
|