-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathnote.go
100 lines (83 loc) · 2.18 KB
/
note.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
package synthia
import (
"math"
"github.com/synthia-synth/synthia/domains"
)
type NoteName int
const (
A NoteName = 9
B = 11
C = 0
D = 2
E = 4
F = 5
G = 7
)
type Accidental float64
const (
AccidentalNatural Accidental = 0
AccidentalSharp = 1
AccidentalFlat = -1
AccidentalDoubleSharp = 2
AccidentalDoubleFlat = -2
AccidentalHalfSharp = 0.5
AccidentalHalfFlat = -.5
)
type NoteLen float64
const (
Breve NoteLen = 8
SemiBreve NoteLen = 4
Minim NoteLen = 2
Crotchet NoteLen = 1
Quaver NoteLen = 1.0 / 2
SemiQuaver NoteLen = 1.0 / 4
DemiSemiQuaver NoteLen = 1.0 / 8
HemiDemiSemiQuaver NoteLen = 1.0 / 16
SemiHemiDemiSemiQuaver NoteLen = 1.0 / 32
DemiSemiHemiDemiSemiQuaver NoteLen = 1.0 / 64
)
type LenModifier float64
const (
Dotted LenModifier = 1.5
NormalLength LenModifier = 1
)
const (
referencePoint = 4*12 + int(A)
referenceFreq = 440
freqStep = 1.059463094359
)
var bpm, beatLength float64
type Note struct {
note NoteName
accidental Accidental
length NoteLen
lengthModifier LenModifier
octave int
vol int32
}
func setBPM(newBPM float64) {
bpm = newBPM
beatLength = 60 / bpm
}
func lengthToDuration(len NoteLen, modifier LenModifier) float64 {
return float64(len) * beatLength * float64(modifier)
}
func (n *Note) Frequency() float64 {
note := int(n.note) + 12*n.octave
diff := float64(note - referencePoint)
diff += float64(n.accidental)
return referenceFreq * math.Pow(freqStep, diff)
}
func NewNote(note NoteName, octave int, accidental Accidental, length NoteLen, lengthModifier LenModifier) *Note {
n := new(Note)
n.note = note
n.octave = octave
n.accidental = accidental
n.length = length
n.lengthModifier = lengthModifier
n.vol = 1 << 30
return n
}
func (n *Note) GenerateTone(generator ToneGenerator) []domains.Time {
return adsr1(generator.Play(n.Frequency(), lengthToDuration(n.length, n.lengthModifier), n.vol))
}