-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathfm∞.mmckpy
156 lines (130 loc) · 4.86 KB
/
fm∞.mmckpy
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
from collections import defaultdict
from rv.api import m
# -----------------------------------------------------------------------------
def set_parameters(p, P):
# Define your parameters below by assigning them to the
# `p` object, then returning it.
#
# You can define String or Integer parameters.
#
# Example:
#
# p.name = String(label='Project Name')
# p.voices = Integer(5, range=(3, 17), step=2)
# p.spread = Integer(5, range=(0, 128))
p.name = P.String('My FM Synth', label='Project Name')
p.algorithm = P.String('4- 43 3. 2. 1.', label='Algorithm')
# -----------------------------------------------------------------------------
def build_project(p, c, project):
# Construct the MetaModule interior by
# attaching modules to the `project` object.
# Consult the `rv` documentation for details.
# http://radiant-voices.rtfd.io/
#
# Expose controllers you'd like to manipulate
# by adding them to the `c` object, using
# `(module, ctl_name)` notation.
#
# Group them together using `Group` objects.
#
# Example:
#
# gen = project.new_module(
# m.AnalogGenerator,
# polyphony_ch=1,
# sustain=False,
# )
# gen >> project.output
# c.attack = (gen, 'attack')
# c.release = (gen, 'release')
def sin_generator(group, name):
module = project.new_module(
m.AnalogGenerator,
name=name,
polyphony_ch=1,
waveform=m.AnalogGenerator.Waveform.sin,
)
group.waveform = (module, 'waveform')
group.sustain = (module, 'sustain')
group.attack = (module, 'attack')
group.release = (module, 'release')
group.duty_cycle = (module, 'duty_cycle')
return module
def operator(group, name):
return sin_generator(group, name)
operator_factories = None
# =========================
project.name = p.name
note_in = project.new_module(m.MultiSynth, name='note in')
out_amp = project.new_module(m.Amplifier)
out_amp >> project.output
forward_graph = defaultdict(list)
edges = [(src, dest) for src, dest in p.algorithm.split(' ')]
for src, dest in edges:
dest = src if dest == '-' else dest
node = forward_graph[src]
if dest not in node:
forward_graph[src].append(dest)
reverse_graph = defaultdict(list)
edges = [(src, dest) for src, dest in p.algorithm.split(' ')]
for src, dest in edges:
dest = src if dest == '-' else dest
node = reverse_graph[dest]
if src not in node:
reverse_graph[dest].append(src)
operator_count = len(forward_graph)
operator_names = set(forward_graph).union(set(reverse_graph))
operator_names = list(sorted(operator_names))
operator_names.remove('.')
operator_factories = operator_factories or ([operator] * operator_count)
operators = {}
operator_c_amps = {}
operator_m_amps = {}
operator_mods = {}
operator_multis = {}
for name, factory in zip(operator_names, operator_factories):
group = c['operator_{}'.format(name)]
multi = m.MultiSynth(name='{} note'.format(name))
oper = factory(group, name='{} oper'.format(name))
c_amp = m.Amplifier(name='{} c amp'.format(name))
m_amp = m.Amplifier(name='{} m amp'.format(name))
mod = m.Modulator(
modulation_type='phase',
name='{} mod'.format(name),
)
project += [multi, oper, c_amp, m_amp, mod]
multi >> oper >> c_amp >> mod
m_amp >> mod
operators[name] = oper
operator_c_amps[name] = c_amp
operator_m_amps[name] = m_amp
operator_mods[name] = mod
operator_multis[name] = multi
group.carrier_amp = (c_amp, 'volume')
group.modulator_amp = (m_amp, 'volume')
feedback_ctls = {}
for dest_key, src_keys in reverse_graph.items():
if dest_key == '.':
dest_amp = out_amp
else:
dest_amp = operator_m_amps[dest_key]
for src_key in src_keys:
src_mod = operator_mods[src_key]
if src_key == dest_key:
fb1 = project.new_module(m.Feedback, volume=0)
fb2 = project.new_module(m.Feedback, volume=0)
fb_ctl = m.MultiCtl.macro(
project,
(fb1, 'volume'),
(fb2, 'volume'),
name='{} fb'.format(src_key),
)
src_m_amp = operator_m_amps[src_key]
src_mod >> fb1 >> fb2 >> src_m_amp
feedback_ctls[src_key] = fb_ctl
group = c['operator_{}'.format(src_key)]
group.feedback = (fb_ctl, 'value')
else:
src_mod >> dest_amp
note_in >> list(operator_multis.values())
project.layout()