|
- package recorder
-
- import (
- "encoding/binary"
- "os"
- )
-
- func writeWAV(path string, samples []float32, sampleRate int, channels int) error {
- f, err := os.Create(path)
- if err != nil {
- return err
- }
- defer f.Close()
-
- if channels <= 0 {
- channels = 1
- }
- // 16-bit PCM
- dataSize := uint32(len(samples) * 2)
- // RIFF header
- if _, err := f.Write([]byte("RIFF")); err != nil {
- return err
- }
- if err := binary.Write(f, binary.LittleEndian, uint32(36)+dataSize); err != nil {
- return err
- }
- if _, err := f.Write([]byte("WAVE")); err != nil {
- return err
- }
- // fmt chunk
- if _, err := f.Write([]byte("fmt ")); err != nil {
- return err
- }
- if err := binary.Write(f, binary.LittleEndian, uint32(16)); err != nil {
- return err
- }
- if err := binary.Write(f, binary.LittleEndian, uint16(1)); err != nil { // PCM
- return err
- }
- if err := binary.Write(f, binary.LittleEndian, uint16(channels)); err != nil {
- return err
- }
- if err := binary.Write(f, binary.LittleEndian, uint32(sampleRate)); err != nil {
- return err
- }
- byteRate := uint32(sampleRate * channels * 2)
- if err := binary.Write(f, binary.LittleEndian, byteRate); err != nil {
- return err
- }
- if err := binary.Write(f, binary.LittleEndian, uint16(channels*2)); err != nil {
- return err
- }
- if err := binary.Write(f, binary.LittleEndian, uint16(16)); err != nil { // bits
- return err
- }
- // data chunk
- if _, err := f.Write([]byte("data")); err != nil {
- return err
- }
- if err := binary.Write(f, binary.LittleEndian, dataSize); err != nil {
- return err
- }
- // samples
- for _, s := range samples {
- v := int16(clip(s * 32767))
- if err := binary.Write(f, binary.LittleEndian, v); err != nil {
- return err
- }
- }
- return nil
- }
-
- func clip(v float32) float32 {
- if v > 32767 {
- return 32767
- }
- if v < -32768 {
- return -32768
- }
- return v
- }
|