forked from peterbourgon/goop
/
wav.go
107 lines (96 loc) · 2.5 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
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
package goop
import (
"bufio"
"encoding/binary"
"fmt"
"os"
)
// Reads .wav data to a struct, to be consumed by a WavGenerator.
// Thanks to Tony Worm <verdverm@gmail.com> for this code, taken
// more-or-less verbatim from golang-nuts post on Mon, 30 Jan 2012
// at 14:02 PST.
type WavData struct {
bChunkID [4]byte // B
ChunkSize uint32 // L
bFormat [4]byte // B
bSubchunk1ID [4]byte // B
Subchunk1Size uint32 // L
AudioFormat uint16 // L
NumChannels uint16 // L
SampleRate uint32 // L
ByteRate uint32 // L
BlockAlign uint16 // L
BitsPerSample uint16 // L
bSubchunk2ID [4]byte // B
Subchunk2Size uint32 // L
data []byte // L
}
func ReadWavData(file string) (WavData, error) {
// read file to Reader
ftotal, err := os.OpenFile(file, os.O_RDONLY, 0)
if err != nil {
return WavData{}, fmt.Errorf("ReadWavData: %s", err)
}
defer ftotal.Close()
f := bufio.NewReader(ftotal)
// fill WavData structure
wav := WavData{}
binary.Read(f, binary.BigEndian, &wav.bChunkID)
binary.Read(f, binary.LittleEndian, &wav.ChunkSize)
binary.Read(f, binary.BigEndian, &wav.bFormat)
binary.Read(f, binary.BigEndian, &wav.bSubchunk1ID)
binary.Read(f, binary.LittleEndian, &wav.Subchunk1Size)
binary.Read(f, binary.LittleEndian, &wav.AudioFormat)
binary.Read(f, binary.LittleEndian, &wav.NumChannels)
binary.Read(f, binary.LittleEndian, &wav.SampleRate)
binary.Read(f, binary.LittleEndian, &wav.ByteRate)
binary.Read(f, binary.LittleEndian, &wav.BlockAlign)
binary.Read(f, binary.LittleEndian, &wav.BitsPerSample)
binary.Read(f, binary.BigEndian, &wav.bSubchunk2ID)
binary.Read(f, binary.LittleEndian, &wav.Subchunk2Size)
wav.data = make([]byte, wav.Subchunk2Size)
binary.Read(f, binary.LittleEndian, &wav.data)
// bam
return wav, nil
}
const (
mid16 uint16 = 1 >> 2
big16 uint16 = 1 >> 1
big32 uint32 = 65535
)
func btou(b []byte) []uint16 {
u := make([]uint16, len(b)/2)
for i, _ := range u {
val := uint16(b[i*2])
val += uint16(b[i*2+1]) << 8
u[i] = val
}
return u
}
func btoi16(b []byte) []int16 {
u := make([]int16, len(b)/2)
for i, _ := range u {
val := int16(b[i*2])
val += int16(b[i*2+1]) << 8
u[i] = val
}
return u
}
func btof32(b []byte) []float32 {
u := btoi16(b)
f := make([]float32, len(u))
for i, v := range u {
f[i] = float32(v) / float32(32768)
}
return f
}
func utob(u []uint16) []byte {
b := make([]byte, len(u)*2)
for i, val := range u {
lo := byte(val)
hi := byte(val >> 8)
b[i*2] = lo
b[i*2+1] = hi
}
return b
}