-
Notifications
You must be signed in to change notification settings - Fork 7
/
WaveLoader.go
133 lines (107 loc) · 3 KB
/
WaveLoader.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
121
122
123
124
125
126
127
128
129
130
131
132
133
package wav
import (
"bytes"
"encoding/binary"
"io"
"github.com/inkyblackness/hacked/ss1"
)
const (
errUnsupportedFormat ss1.StringError = "unsupported WAVE format"
)
func l8FromL8(input []byte) []byte {
return input
}
func l8FromL16(input []byte) []byte {
samples := len(input) / 2
output := make([]byte, samples)
for i := 0; i < samples; i++ {
output[i] = byte(int(input[i*2+1]) + 0x80)
}
return output
}
type waveLoader struct {
dataRead bool
formatRead bool
samples []byte
sampleRate float32
reader io.Reader
err error
dataConverter func([]byte) []byte
}
func (loader *waveLoader) load(reader io.Reader) {
loader.reader = reader
loader.dataConverter = l8FromL8
loader.loadRiff()
}
func (loader *waveLoader) read(data interface{}) bool {
if loader.err == nil {
loader.err = binary.Read(loader.reader, binary.LittleEndian, data)
}
return loader.err == nil
}
func (loader *waveLoader) readBytes(size uint32) (data []byte) {
data = make([]byte, int(size))
_, loader.err = loader.reader.Read(data)
return
}
func (loader *waveLoader) loadChunk(handler func(riffChunkType, uint32)) {
var tag riffChunkTag
if loader.read(&tag) {
handler(tag.ChunkType, tag.Size)
}
}
func (loader *waveLoader) loadRiff() {
loader.loadChunk(loader.handleRiff)
}
func (loader *waveLoader) handleRiff(chunkType riffChunkType, size uint32) {
if chunkType == riffChunkTypeRiff {
var contentType riffContentType
if loader.read(&contentType) && (contentType == riffContentTypeWave) {
loader.loadWave()
} else if loader.err == nil {
loader.err = errNotASupportedWave
}
} else {
loader.err = errNotASupportedWave
}
}
func (loader *waveLoader) loadWave() {
for !loader.isDone() {
loader.loadFormatOrData()
}
loader.samples = loader.dataConverter(loader.samples)
}
func (loader *waveLoader) loadFormatOrData() {
loader.loadChunk(loader.handleFormatOrData)
}
func (loader *waveLoader) handleFormatOrData(chunkType riffChunkType, size uint32) {
if chunkType == riffChunkTypeFmt {
loader.loadFormat(size)
} else if chunkType == riffChunkTypeData {
loader.loadData(size)
}
}
func (loader *waveLoader) loadFormat(size uint32) {
headerData := loader.readBytes(size)
headerReader := bytes.NewReader(headerData)
var header formatHeader
loader.formatRead = true
loader.err = binary.Read(headerReader, binary.LittleEndian, &header.base)
loader.err = binary.Read(headerReader, binary.LittleEndian, &header.extension.BitsPerSample)
loader.sampleRate = float32(header.base.SamplesPerSec)
if header.extension.BitsPerSample == 16 {
loader.dataConverter = l8FromL16
}
if (header.base.FormatType != waveFormatTypePcm) ||
(header.base.Channels != 1) ||
((header.extension.BitsPerSample != 8) && (header.extension.BitsPerSample != 16)) {
loader.err = errUnsupportedFormat
}
}
func (loader *waveLoader) loadData(size uint32) {
loader.dataRead = true
loader.samples = loader.readBytes(size)
}
func (loader *waveLoader) isDone() bool {
return (loader.err != nil) || (loader.dataRead && loader.formatRead)
}