-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathctrl.go
84 lines (70 loc) · 2.16 KB
/
ctrl.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
package main
import (
"fmt"
"math"
"github.com/scgolang/midi"
"github.com/scgolang/sc"
)
const (
// polyphony is used to scale the gain of each synth voice.
polyphony = 4
// fmtAmtHi is the max value for op1amt.
fmtAmtHi = float32(2000)
// freqScaleLo is the min value for op2freqscale (as a power of 2).
freqScaleLo = float32(-8)
// freqScaleHi is the max value for op2freqscale (as a power of 2).
freqScaleHi = float32(2)
// decayLo is the min value for op2decay (in secs).
decayLo = float32(0.0001)
// decayHi is the max value for op2decay (in secs).
decayHi = float32(10)
)
var (
ops = []int{1, 2, 3, 4, 5, 6}
)
func ctrlName(op int, name string) string {
return fmt.Sprintf("op%d%s", op, name)
}
// FromNote implements poly.Controller.
func (dx7 *DX7) FromNote(note midi.Note) map[string]float32 {
var (
ctrls = map[string]float32{"gate": float32(1)}
freq = sc.Midicps(float32(note.Number))
gain = float32(note.Velocity) / (127 * polyphony)
)
for op := range ops {
ctrls[ctrlName(op, "freq")] = freq
ctrls[ctrlName(op, "gain")] = gain
ctrls[ctrlName(op, "amt")] = dx7.ctrls["op1amt"]
ctrls[ctrlName(op, "freqscale")] = dx7.ctrls["op2freqscale"]
ctrls[ctrlName(op, "decay")] = dx7.ctrls["op2decay"]
ctrls[ctrlName(op, "sustain")] = dx7.ctrls["op2sustain"]
}
return ctrls
}
// FromCtrl implements poly.Controller.
func (dx7 *DX7) FromCtrl(ctrl midi.CC) map[string]float32 {
switch ctrl.Number {
default:
return nil
case 106: // op1 FM Amt
dx7.ctrls["op1amt"] = float32(ctrl.Value) * (fmtAmtHi / 127)
case 107: // op2 Freq Scale
dx7.ctrls["op2freqscale"] = getOp2FreqScale(ctrl.Value)
case 108:
dx7.ctrls["op2decay"] = linear(ctrl.Value, decayLo, decayHi)
case 109:
dx7.ctrls["op2sustain"] = float32(ctrl.Value) / 127
}
return dx7.ctrls
}
// getOp2FreqScale returns a frequency scaling value for op2.
func getOp2FreqScale(value int) float32 {
exp := float64(linear(value, freqScaleLo, freqScaleHi))
// return float32(math.Pow(2, float64((norm*(freqScaleHi-freqScaleLo))+freqScaleLo)))
return float32(math.Pow(2, exp))
}
func linear(val int, min, max float32) float32 {
norm := float32(val) / 127
return (norm * (max - min)) + min
}