Skip to content

Commit

Permalink
use envelope as an extra field in modules
Browse files Browse the repository at this point in the history
  • Loading branch information
iljarotar committed Aug 14, 2024
1 parent 429bfc5 commit e66c96e
Show file tree
Hide file tree
Showing 9 changed files with 66 additions and 23 deletions.
16 changes: 10 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ Run `synth -h` to see all configuration options.
| phase | Float | phase in range [-1,1] |
| pan | Input | stereo balance in range [-1,1] |
| filters | String[0..*] | names of the filters to apply |
| envelope | String | name of the envelope to apply |

| OscillatorType |
| --------------- |
Expand All @@ -88,6 +89,7 @@ Run `synth -h` to see all configuration options.
| amp | Input | amplitude in range [0,2] |
| pan | Input | stereo balance in range [-1,1] |
| filters | String[0..*] | names of the filters to apply |
| envelope | String | name of the envelope to apply |

| Wavetable | | |
| --------- | ------------ | ----------------------------------------- |
Expand All @@ -98,6 +100,7 @@ Run `synth -h` to see all configuration options.
| freq | Input | periods per second [0,20000] |
| table | Float [0..*] | output values |
| filters | String[0..*] | names of the filters to apply |
| envelope | String | name of the envelope to apply |

| Sampler | | |
| --------- | ------------ | -------------------------------------------------- |
Expand All @@ -108,6 +111,7 @@ Run `synth -h` to see all configuration options.
| freq | Input | frequency in range [0,SAMPLE_RATE (default 44100)] |
| filters | String[0..*] | names of the filters to apply |
| inputs | String[0..*] | names of the modules that will be sampled |
| envelope | String | name of the envelope to apply |

A sampler periodically samples the output values of the given inputs and outputs their sum.

Expand Down Expand Up @@ -135,12 +139,12 @@ transitioning at the `low-cutoff` frequency. If both cutoff frequencies are defi
| bpm | Input | triggers per minute [0,600000] |
| time-shift | Float | initial time shift |

| Input | | |
| --------- | ------------- | ------------------------------------------ |
| **Field** | **Type** | **Description** |
| val | Float | initial value of the respective parameter |
| mod | String [0..*] | names of modulating modules |
| mod-amp | Float | amplitude of the modulation in range [0,1] |
| Input | | |
| --------- | ------------- | ----------------------------------------------------------------------- |
| **Field** | **Type** | **Description** |
| val | Float | initial value of the respective parameter |
| mod | String [0..*] | names of modulating modules (oscillators, samplers, wavetables, noises) |
| mod-amp | Float | amplitude of the modulation in range [0,1] |

## Example patch file

Expand Down
24 changes: 22 additions & 2 deletions examples/envelope.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,30 @@
vol: 1
out: [o1]
out: [s1]
wavetables:
- name: w1
amp: {val: 1}
freq: {val: 200}
table: [1,0]
envelope: e1

samplers:
- name: s1
amp: {val: 1}
freq: {val: 44100}
inputs: [n1]
envelope: e1

noises:
- name: n1
amp: {val: 0.1}
envelope: e1

oscillators:
- name: o1
type: Triangle
freq: {val: 200}
amp: {val: 0, mod: [e1], mod-amp: 1}
amp: {val: 1}
envelope: e1

- name: lfo1
type: Square
Expand Down
7 changes: 4 additions & 3 deletions module/envelope.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import (
"github.com/iljarotar/synth/utils"
)

type EnvelopesMap map[string]*Envelope

type Envelope struct {
Module
Name string `yaml:"name"`
Attack Input `yaml:"attack"`
Decay Input `yaml:"decay"`
Expand All @@ -17,6 +18,7 @@ type Envelope struct {
SustainLevel Input `yaml:"sustain-level"`
TimeShift float64 `yaml:"time-shift"`
BPM Input `yaml:"bpm"`
current float64
lastTriggeredAt *float64
currentConfig envelopeConfig
}
Expand All @@ -32,14 +34,13 @@ type envelopeConfig struct {

func (e *Envelope) Initialize() {
e.limitParams()
e.current = output{Mono: 0, Left: 0, Right: 0}
}

func (e *Envelope) Next(t float64, modMap ModulesMap) {
bpm := modulate(e.BPM, bpmLimits, modMap)
e.trigger(t, bpm, modMap)
y := e.getCurrentValue(t)
e.current = output{Mono: y, Left: 0, Right: 0}
e.current = y
}

func (e *Envelope) getCurrentConfig(t float64, modMap ModulesMap) {
Expand Down
7 changes: 7 additions & 0 deletions module/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ func modulate(param Input, lim limits, modMap ModulesMap) float64 {
return utils.Limit(y, lim.min, lim.max)
}

func applyEnvelope(x float64, envelopeName string, envelopesMap EnvelopesMap) float64 {
if e, ok := envelopesMap[envelopeName]; ok {
return x * e.current
}
return x
}

func stereo(x, pan float64) output {
out := output{}
p := utils.Percentage(pan, -1, 1)
Expand Down
4 changes: 3 additions & 1 deletion module/noise.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type Noise struct {
Amp Input `yaml:"amp"`
Pan Input `yaml:"pan"`
Filters []string `yaml:"filters"`
Envelope string `yaml:"envelope"`
inputs []filterInputs
sampleRate float64
}
Expand All @@ -23,7 +24,7 @@ func (n *Noise) Initialize(sampleRate float64) {
n.current = stereo(noise()*n.Amp.Val, n.Pan.Val)
}

func (n *Noise) Next(modMap ModulesMap, filtersMap FiltersMap) {
func (n *Noise) Next(modMap ModulesMap, filtersMap FiltersMap, envelopesMap EnvelopesMap) {
pan := modulate(n.Pan, panLimits, modMap)
amp := modulate(n.Amp, ampLimits, modMap)

Expand All @@ -34,6 +35,7 @@ func (n *Noise) Next(modMap ModulesMap, filtersMap FiltersMap) {
}

y, newInputs := cfg.applyFilters(noise())
y = applyEnvelope(y, n.Envelope, envelopesMap)
n.integral += y / n.sampleRate
n.inputs = newInputs
n.current = stereo(y*amp, pan)
Expand Down
4 changes: 3 additions & 1 deletion module/oscillator.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type Oscillator struct {
Phase float64 `yaml:"phase"`
Pan Input `yaml:"pan"`
Filters []string `yaml:"filters"`
Envelope string `yaml:"envelope"`
inputs []filterInputs
signal SignalFunc
sampleRate float64
Expand All @@ -44,7 +45,7 @@ func (o *Oscillator) Initialize(sampleRate float64) {
o.current = stereo(y, o.Pan.Val)
}

func (o *Oscillator) Next(t float64, modMap ModulesMap, filtersMap FiltersMap) {
func (o *Oscillator) Next(t float64, modMap ModulesMap, filtersMap FiltersMap, envelopesMap EnvelopesMap) {
pan := modulate(o.Pan, panLimits, modMap)
amp := modulate(o.Amp, ampLimits, modMap)
offset := o.getOffset(modMap)
Expand All @@ -57,6 +58,7 @@ func (o *Oscillator) Next(t float64, modMap ModulesMap, filtersMap FiltersMap) {

x := o.signalValue(t, amp, offset)
y, newInputs := cfg.applyFilters(x)
y = applyEnvelope(y, o.Envelope, envelopesMap)
avg := (y + o.Current().Mono) / 2
o.integral += avg / o.sampleRate
o.inputs = newInputs
Expand Down
4 changes: 3 additions & 1 deletion module/sampler.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type Sampler struct {
Freq Input `yaml:"freq"`
Filters []string `yaml:"filters"`
Inputs []string `yaml:"inputs"`
Envelope string `yaml:"envelope"`
inputs []filterInputs
lastTriggeredAt float64
limits
Expand All @@ -26,7 +27,7 @@ func (s *Sampler) Initialize(sampleRate float64) {
s.current = stereo(0, s.Pan.Val)
}

func (s *Sampler) Next(t float64, modMap ModulesMap, filtersMap FiltersMap) {
func (s *Sampler) Next(t float64, modMap ModulesMap, filtersMap FiltersMap, envelopesMap EnvelopesMap) {
amp := modulate(s.Amp, ampLimits, modMap)
pan := modulate(s.Pan, panLimits, modMap)
freq := modulate(s.Freq, s.limits, modMap)
Expand All @@ -39,6 +40,7 @@ func (s *Sampler) Next(t float64, modMap ModulesMap, filtersMap FiltersMap) {

x := s.sample(t, freq, amp, modMap)
y, newInputs := cfg.applyFilters(x)
y = applyEnvelope(y, s.Envelope, envelopesMap)
s.integral += y / s.sampleRate
s.inputs = newInputs
s.current = stereo(y, pan)
Expand Down
4 changes: 3 additions & 1 deletion module/wavetable.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type Wavetable struct {
Amp Input `yaml:"amp"`
Pan Input `yaml:"pan"`
Filters []string `yaml:"filters"`
Envelope string `yaml:"envelope"`
inputs []filterInputs
sampleRate float64
}
Expand All @@ -28,7 +29,7 @@ func (w *Wavetable) Initialize(sampleRate float64) {
w.current = stereo(y, w.Pan.Val)
}

func (w *Wavetable) Next(t float64, modMap ModulesMap, filtersMap FiltersMap) {
func (w *Wavetable) Next(t float64, modMap ModulesMap, filtersMap FiltersMap, envelopesMap EnvelopesMap) {
pan := modulate(w.Pan, panLimits, modMap)
amp := modulate(w.Amp, ampLimits, modMap)
freq := modulate(w.Freq, freqLimits, modMap)
Expand All @@ -41,6 +42,7 @@ func (w *Wavetable) Next(t float64, modMap ModulesMap, filtersMap FiltersMap) {

x := w.signalValue(t, amp, freq)
y, newInputs := cfg.applyFilters(x)
y = applyEnvelope(y, w.Envelope, envelopesMap)
w.integral += y / w.sampleRate
w.inputs = newInputs
w.current = stereo(y, pan)
Expand Down
19 changes: 11 additions & 8 deletions synth/synth.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type Synth struct {
sampleRate float64
modMap module.ModulesMap
filtersMap module.FiltersMap
envelopesMap module.EnvelopesMap
step, volumeMemory float64
notifyFadeOutDone chan bool
fadeDirection FadeDirection
Expand Down Expand Up @@ -164,19 +165,19 @@ func (s *Synth) getCurrentValue() (left, right, mono float64) {
func (s *Synth) updateCurrentValues() {
for _, o := range s.Oscillators {
osc := o
osc.Next(s.Time, s.modMap, s.filtersMap)
osc.Next(s.Time, s.modMap, s.filtersMap, s.envelopesMap)
}

for _, n := range s.Noises {
n.Next(s.modMap, s.filtersMap)
n.Next(s.modMap, s.filtersMap, s.envelopesMap)
}

for _, c := range s.Wavetables {
c.Next(s.Time, s.modMap, s.filtersMap)
c.Next(s.Time, s.modMap, s.filtersMap, s.envelopesMap)
}

for _, smplr := range s.Samplers {
smplr.Next(s.Time, s.modMap, s.filtersMap)
smplr.Next(s.Time, s.modMap, s.filtersMap, s.envelopesMap)
}

for _, e := range s.Envelopes {
Expand All @@ -193,6 +194,7 @@ func (s *Synth) updateCurrentValues() {
func (s *Synth) makeMaps() {
modMap := make(module.ModulesMap)
filtersMap := make(module.FiltersMap)
envelopesMap := make(module.EnvelopesMap)

for _, osc := range s.Oscillators {
modMap[osc.Name] = osc
Expand All @@ -210,16 +212,17 @@ func (s *Synth) makeMaps() {
modMap[smplr.Name] = smplr
}

for _, e := range s.Envelopes {
modMap[e.Name] = e
}

for _, f := range s.Filters {
filtersMap[f.Name] = f
}

for _, e := range s.Envelopes {
envelopesMap[e.Name] = e
}

s.modMap = modMap
s.filtersMap = filtersMap
s.envelopesMap = envelopesMap
}

func secondsToStep(seconds, delta, sampleRate float64) float64 {
Expand Down

0 comments on commit e66c96e

Please sign in to comment.