Audio
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user