-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwave.go
120 lines (97 loc) · 3.35 KB
/
wave.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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// based on https://gist.github.com/brendaningram/67c1761b9559cbc6afa3
package ilbc
import (
"bytes"
"encoding/binary"
)
// golang types
// uint8 the set of all unsigned 8-bit (1 byte) integers (0 to 255)
// uint16 the set of all unsigned 16-bit (2 byte) integers (0 to 65535)
// uint32 the set of all unsigned 32-bit (4 byte) integers (0 to 4294967295)
// uint64 the set of all unsigned 64-bit (8 byte) integers (0 to 18446744073709551615)
// WAVE PCM soundfile format http://soundfile.sapp.org/doc/WaveFormat/
// The default byte ordering assumed for WAVE data files is little-endian.
// Files written using the big-endian byte ordering scheme have the identifier RIFX instead of RIFF.
type waveHeader struct {
// Offset 0
// Contains the letters "RIFF" in ASCII form
RiffTag [4]byte // ChunkID 4 bytes
// Offset 4
// This is the size of the entire file in bytes minus 8 bytes for the two fields not included in this count: ChunkID and ChunkSize.
// Also = 4 + (8 + SubChunk1Size) + (8 + SubChunk2Size)
RiffLength uint32 // ChunkSize 4 bytes
// Offset 8
// Contains the letters "WAVE"
WaveTag [4]byte // Format 4 bytes
// Offset 12
// Contains the letters "fmt "
FmtTag [4]byte // Subchunk1ID 4 bytes
// Offset 16
// 16 for PCM
FmtLength uint32 // Subchunk1Size 4 bytes
// Offset 20
// PCM = 1 (i.e. Linear quantization)
// Values other than 1 indicate some form of compression.
AudioFormat uint16 // AudioFormat 2 bytes
// Offset 22
// Mono = 1, Stereo = 2
NumChannels uint16 // NumChannels 2 bytes
// Offset 24
// 44100, 96000 etc
SampleRate uint32 // SampleRate 4 bytes
// Offset 28
// = SampleRate * NumChannels * BitsPerSample/8
ByteRate uint32 // ByteRate 4 bytes
// Offset 32
// The number of bytes for one sample including all channels.
// = NumChannels * BitsPerSample/8
BlockAlign uint16 // BlockAlign 2 bytes
// Offset 34
// 8 bits = 8, 16 bits = 16
BitsPerSample uint16 // BitsPerSample 2 bytes
// Offset 36
// Contains the letters "data"
DataTag [4]byte // Subchunk2ID 4 bytes
// Offset 40
// This is the number of bytes in the data.
// = NumSamples * NumChannels * BitsPerSample/8
DataLength uint32 // Subchunk2Size 4 bytes
}
// Convert the waveHeader struct to a byte slice
func (h *waveHeader) toBytes() []byte {
buffer := new(bytes.Buffer)
binary.Write(buffer, binary.LittleEndian, h)
return buffer.Bytes()
}
func readWaveHeader(data []byte) (waveHeader, error) {
var h waveHeader
err := binary.Read(bytes.NewReader(data), binary.LittleEndian, &h)
if err != nil {
return h, err
}
return h, nil
}
func writeWaveHeader(data []byte) []byte {
var (
waveHeaderSize uint32 = 44 // bytes
fileLength uint32 = uint32(len(data)) + waveHeaderSize
riffLength uint32 = fileLength - 8
dataLength uint32 = fileLength - waveHeaderSize
)
header := &waveHeader{}
copy(header.RiffTag[:], "RIFF")
header.RiffLength = riffLength
copy(header.WaveTag[:], "WAVE")
copy(header.FmtTag[:], "fmt ")
header.FmtLength = 16
header.AudioFormat = 1
header.NumChannels = 1
header.SampleRate = 8000
header.ByteRate = header.SampleRate * uint32(header.NumChannels) * uint32(header.SampleRate/8)
header.BlockAlign = header.NumChannels * uint16(16/8)
header.BitsPerSample = uint16(16)
copy(header.DataTag[:], "data")
header.DataLength = dataLength
data = append(header.toBytes(), data...)
return data
}