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 }