-
Notifications
You must be signed in to change notification settings - Fork 13
/
adsr_envelope.go
91 lines (78 loc) · 2.17 KB
/
adsr_envelope.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
package derived
import (
"github.com/bspaans/bleep/audio"
"github.com/bspaans/bleep/generators"
)
type EnvelopeGenerator struct {
Generator generators.Generator
Pitch float64
Attack float64
Decay float64
Sustain float64
SustainHold float64
Release float64
Period int
}
func NewEnvelopeGenerator(g generators.Generator, attack, decay, sustain, release float64) *EnvelopeGenerator {
return &EnvelopeGenerator{
Generator: g,
Attack: attack,
Decay: decay,
Sustain: sustain,
SustainHold: 0.1,
Release: release,
Period: 0,
}
}
func (e *EnvelopeGenerator) GetSamples(cfg *audio.AudioConfig, n int) []float64 {
result := generators.GetEmptySampleArray(cfg, n)
if e.Pitch == 0.0 {
return result
}
attackLength := float64(cfg.SampleRate) * e.Attack
decayLength := float64(cfg.SampleRate) * e.Decay
decayEnd := attackLength + decayLength
sustainLength := float64(cfg.SampleRate) * e.SustainHold
sustainEnd := decayEnd + sustainLength
releaseLength := float64(cfg.SampleRate) * e.Release
releaseEnd := sustainEnd + releaseLength
samples := e.Generator.GetSamples(cfg, n)
for i := 0; i < n; i++ {
factor := 0.0
if float64(e.Period) < attackLength {
factor = float64(e.Period) * (1.0 / attackLength)
} else if float64(e.Period) < decayEnd {
p := float64(e.Period) - attackLength
decayDomain := e.Sustain - 1.0
decayPerPeriod := decayDomain / decayLength
factor = (decayPerPeriod*p + 1.0)
} else if float64(e.Period) < sustainEnd {
factor = e.Sustain
} else if float64(e.Period) < releaseEnd {
p := float64(e.Period) - sustainEnd
releasePerPeriod := (0 - e.Sustain) / releaseLength
factor = releasePerPeriod*p + e.Sustain
}
e.Period++
if !cfg.Stereo {
result[i] = samples[i] * factor
} else {
result[i*2] = samples[i*2] * factor
result[i*2+1] = samples[i*2+1] * factor
}
}
return result
}
func (e *EnvelopeGenerator) SetPitch(f float64) {
e.Pitch = f
e.Generator.SetPitch(f)
if f == 0.0 {
e.Period = 0
}
}
func (e *EnvelopeGenerator) SetGain(f float64) {
e.Generator.SetGain(f)
}
func (e *EnvelopeGenerator) SetPitchbend(f float64) {
e.Generator.SetPitchbend(f)
}