-
Notifications
You must be signed in to change notification settings - Fork 3
/
wav.go
77 lines (65 loc) · 1.96 KB
/
wav.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package wav
import (
"bytes"
"encoding/binary"
)
type Head struct {
ChunkID [4]byte //内容为"RIFF"
ChunkSize uint32 //wav文件的字节数, 不包含ChunkID和ChunkSize这8个字节)
Format [4]byte //内容为WAVE
}
type Fmt struct {
Subchunk1ID [4]byte //内容为"fmt "
Subchunk1Size uint32 // Fmt所占字节数,为16
AudioFormat uint16 //存储音频的编码格式,pcm为1
NumChannels uint16 //通道数, 单通道为1,双通道为2
SampleRate uint32 //采样率,如8k, 44.1k等
ByteRate uint32 //每秒存储的byte数,其值=SampleRate * NumChannels * BitsPerSample/8
BlockAlign uint16 //块对齐大小,其值=NumChannels * BitsPerSample/8
BitsPerSample uint16 //每个采样点的bit数,一般为8,16,32等。
}
type Data struct {
Subchunk2ID [4]byte //内容为"data"
Subchunk2Size uint32 //内容为接下来的正式的数据部分的字节数,其值=NumSamples * NumChannels * BitsPerSample/8
}
type WavHead struct {
Head
Fmt
Data
}
func New(numChannels uint16, sampleRate uint32, bitsPerSample uint16, wavLen uint32) *WavHead {
head := &WavHead{
Head: Head{
//ChunkID: []byte("RIFF"),
ChunkSize: uint32(36 + wavLen),
//Format: []byte("WAVE"),
},
Fmt: Fmt{
//Subchunk1ID: []byte("fmt "),
Subchunk1Size: 16,
AudioFormat: 1,
NumChannels: numChannels,
SampleRate: sampleRate,
ByteRate: sampleRate * uint32(numChannels) * uint32(bitsPerSample) / 8,
BlockAlign: numChannels * bitsPerSample / 8,
BitsPerSample: bitsPerSample,
},
Data: Data{
//Subchunk2ID: []byte("data"),
Subchunk2Size: uint32(wavLen),
},
}
copy(head.ChunkID[:], "RIFF")
copy(head.Format[:], "WAVE")
copy(head.Subchunk1ID[:], "fmt ")
copy(head.Subchunk2ID[:], "data")
return head
}
func (wh *WavHead) Marshal() ([]byte, error) {
buf := &bytes.Buffer{}
err := binary.Write(buf, binary.LittleEndian, *wh)
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}