Files
2026-09-02 01:00:09 +03:00

62 lines
1.7 KiB
Go

package mic
import (
"encoding/binary"
"errors"
)
const (
SampleRate = 16000
Channels = 1
BitsPerSample = 16
BytesPerSample = BitsPerSample / 8 * Channels
)
var wavHeaderSize = 44
// EncodeWAV wraps 16-bit mono PCM in a complete WAV file.
func EncodeWAV(pcm []byte) []byte {
if len(pcm) == 0 {
return nil
}
if len(pcm)%BytesPerSample != 0 {
pcm = pcm[:len(pcm)-len(pcm)%BytesPerSample]
}
out := make([]byte, wavHeaderSize+len(pcm))
writeWAVHeader(out, len(pcm))
copy(out[wavHeaderSize:], pcm)
return out
}
func writeWAVHeader(buf []byte, dataLen int) {
if len(buf) < wavHeaderSize {
return
}
copy(buf[0:4], "RIFF")
binary.LittleEndian.PutUint32(buf[4:8], uint32(36+dataLen))
copy(buf[8:12], "WAVE")
copy(buf[12:16], "fmt ")
binary.LittleEndian.PutUint32(buf[16:20], 16)
binary.LittleEndian.PutUint16(buf[20:22], 1) // PCM
binary.LittleEndian.PutUint16(buf[22:24], Channels)
binary.LittleEndian.PutUint32(buf[24:28], SampleRate)
byteRate := SampleRate * Channels * BytesPerSample
binary.LittleEndian.PutUint32(buf[28:32], uint32(byteRate))
binary.LittleEndian.PutUint16(buf[32:34], uint16(Channels*BytesPerSample))
binary.LittleEndian.PutUint16(buf[34:36], BitsPerSample)
copy(buf[36:40], "data")
binary.LittleEndian.PutUint32(buf[40:44], uint32(dataLen))
}
// PCMBytesFromWAV returns PCM payload length implied by a WAV header.
func PCMBytesFromWAV(hdr []byte) (int, error) {
if len(hdr) < wavHeaderSize {
return 0, errors.New("wav header too short")
}
if string(hdr[0:4]) != "RIFF" || string(hdr[8:12]) != "WAVE" {
return 0, errors.New("not a wav file")
}
dataLen := int(binary.LittleEndian.Uint32(hdr[40:44]))
return dataLen, nil
}