forked from DylanMeeus/GoAudio
/
main.go
103 lines (90 loc) 路 2 KB
/
main.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
package main
/*
Play sound based on midi notes..
*/
import (
"encoding/binary"
"fmt"
"math"
"os"
"strconv"
)
type config struct {
Duration int
MidiNote int
SampleRate int
Amplitude float64
}
// Constants for generating our output
const (
DURATION = iota
MIDI
SR
AMP
OUTFILE
TOTAL_ARGS
)
const concertA = float64(440)
// usage: go run main.go [dur] [hz] [sr] [amp]
// e.g: go run main.go 2 440 44100 1
func main() {
fmt.Printf("Generating..\n")
generate(parseInput())
fmt.Printf("Done\n")
}
// midi2hertz turns a midi note into a frequency
func midi2hertz(n int) float64 {
middleC := concertA // oft used default for middleC
return math.Pow(2, (float64(n)-69)/12) * middleC
}
// generate the sample based on the config
func generate(c config) {
var (
start float64 = 1.0
end float64 = 1.0e-4
tau = math.Pi * 2
)
hertz := midi2hertz(c.MidiNote)
fmt.Printf("don't hertz me: %v\n", hertz)
// setup output file
file := os.Args[1:][OUTFILE]
f, err := os.Create(file)
if err != nil {
panic(err)
}
defer f.Close()
nsamples := c.Duration * c.SampleRate
angleincr := tau * hertz / float64(nsamples)
decayfac := math.Pow(end/start, 1.0/float64(nsamples))
for i := 0; i < nsamples; i++ {
sample := c.Amplitude * math.Sin(angleincr*float64(i))
sample *= start
start *= decayfac
var buf [8]byte
// I know my system is LittleEndian, use BigEndian if yours is not..
binary.LittleEndian.PutUint32(buf[:], math.Float32bits(float32(sample)))
bw, err := f.Write(buf[:])
if err != nil {
panic(err)
}
fmt.Printf("\rWrote: %v bytes to %s", bw, file)
}
fmt.Printf("\n")
}
// will ignore error handling for now.. ;-)
func parseInput() config {
args := os.Args[1:]
if len(args) != TOTAL_ARGS {
return config{}
}
dur, _ := strconv.Atoi(args[DURATION])
midi, _ := strconv.Atoi(args[MIDI])
sr, _ := strconv.Atoi(args[SR])
amp, _ := strconv.ParseFloat(args[AMP], 64)
return config{
Duration: dur,
MidiNote: midi,
SampleRate: sr,
Amplitude: amp,
}
}