/
wavefile.go
110 lines (98 loc) · 9.14 KB
/
wavefile.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
package wave
// representation of the wave file, used by reader.go and writer.go
// Frame is a single float64 value of raw audio data
type Frame float64
/*
╔════════╤════════════════╤══════╤═══════════════════════════════════════════════════╗
║ Offset │ Field │ Size │ -- start of header ║
╠════════╪════════════════╪══════╪═══════════════════════════════════════════════════╣
║ 0 │ ChunkID │ 4 │ ║
╟────────┼────────────────┼──────┼───────────────────────────────────────────────────╢
║ 4 │ ChunkSize │ 4 │ ║
╟────────┼────────────────┼──────┼───────────────────────────────────────────────────╢
║ 8 │ Format │ 8 │ ║
╟────────┼────────────────┼──────┼───────────────────────────────────────────────────╢
║ -- │ -- │ -- │ -- start of fmt ║
╟────────┼────────────────┼──────┼───────────────────────────────────────────────────╢
║ 12 │ SubchunkID │ 4 │ ║
╟────────┼────────────────┼──────┼───────────────────────────────────────────────────╢
║ 16 │ SubchunkSize │ 4 │ ║
╟────────┼────────────────┼──────┼───────────────────────────────────────────────────╢
║ 20 │ AudioFormat │ 2 │ ║
╟────────┼────────────────┼──────┼───────────────────────────────────────────────────╢
║ 22 │ NumChannels │ 2 │ ║
╟────────┼────────────────┼──────┼───────────────────────────────────────────────────╢
║ 24 │ SampleRate │ 4 │ ║
╟────────┼────────────────┼──────┼───────────────────────────────────────────────────╢
║ 28 │ ByteRate │ 4 │ ║
╟────────┼────────────────┼──────┼───────────────────────────────────────────────────╢
║ 32 │ BlockAlign │ 2 │ ║
╟────────┼────────────────┼──────┼───────────────────────────────────────────────────╢
║ 34 │ BitsPerSample │ 2 │ ║
╟────────┼────────────────┼──────┼───────────────────────────────────────────────────╢
║ * 36 │ ExtraParamSize │ 2 │ Optional! Only when not PCM ║
╟────────┼────────────────┼──────┼───────────────────────────────────────────────────╢
║ * 38 │ ExtraParams │ * │ Optional! Only when not PCM ║
╟────────┼────────────────┼──────┼───────────────────────────────────────────────────╢
║ -- │ -- │ -- │ -- start of data, assuming PCM ║
╟────────┼────────────────┼──────┼───────────────────────────────────────────────────╢
║ 36 │ Subchunk2ID │ 4 │ (offset by extra params of subchunk 1 if not PCM) ║
╟────────┼────────────────┼──────┼───────────────────────────────────────────────────╢
║ 40 │ SubchunkSize │ 4 │ (offset by extra params of subchunk 1 if not PCM) ║
╟────────┼────────────────┼──────┼───────────────────────────────────────────────────╢
║ 44 │ Data │ * │ (offset by extra params of subchunk 1 if not PCM) ║
╚════════╧════════════════╧══════╧═══════════════════════════════════════════════════╝
*/
// Wave represents an entire .wav audio file
type Wave struct {
WaveHeader
WaveFmt
WaveData
}
// WaveHeader describes the header each WAVE file should start with
type WaveHeader struct {
ChunkID []byte // should be RIFF on little-endian or RIFX on big-endian systems..
ChunkSize int
Format string // sanity-check, should be WAVE (//TODO: keep as []byte?)
}
// WaveFmt describes the format of the sound-information in the data subchunks
type WaveFmt struct {
Subchunk1ID []byte // should contain "fmt"
Subchunk1Size int // 16 for PCM
AudioFormat int // PCM = 1 (Linear Quantization), if not 1, compression was used.
NumChannels int // Mono 1, Stereo = 2, ..
SampleRate int // 44100 for CD-Quality, etc..
ByteRate int // SampleRate * NumChannels * BitsPerSample / 8
BlockAlign int // NumChannels * BitsPerSample / 8 (number of bytes per sample)
BitsPerSample int // 8 bits = 8, 16 bits = 16, .. :-)
ExtraParamSize int // if not PCM, can contain extra params
ExtraParams []byte // the actual extra params.
}
// WaveData contains the raw sound data
type WaveData struct {
Subchunk2ID []byte // Identifier of subchunk
Subchunk2Size int // size of raw sound data
RawData []byte // raw sound data itself
Frames []Frame
}
// NewWaveFmt can be used to generate a complete WaveFmt by calculating the remaining props
func NewWaveFmt(format, channels, samplerate, bitspersample int, extraparams []byte) WaveFmt {
return WaveFmt{
Subchunk1ID: Format,
Subchunk1Size: 16, // assume PCM for now
AudioFormat: format,
NumChannels: channels,
SampleRate: samplerate,
ByteRate: samplerate * channels * (bitspersample / 8.0),
BlockAlign: channels * (bitspersample / 8),
BitsPerSample: bitspersample,
ExtraParamSize: len(extraparams),
ExtraParams: extraparams,
}
}
// SetChannels changes the FMT to adapt to a new amount of channels
func (wfmt *WaveFmt) SetChannels(n uint) {
wfmt.NumChannels = int(n)
wfmt.ByteRate = (wfmt.SampleRate * wfmt.NumChannels * wfmt.BitsPerSample) / 8
wfmt.BlockAlign = (wfmt.NumChannels * wfmt.BitsPerSample) / 8
}