I’m interested in creating my own operators and creating a few FM synthesis algorithms. I’ve searched the forum, and found a similar question from a few years ago (this one). The OP was directed to a DX7 emulation someone had written, as well as the FM7 UGen. Both of those are far more complicated than I need, though. I’m also not looking to emulate the DX7, but simply gain a better understanding of how FM synthesis work by creating something relatively simple (4 operators and a few algorithms).
Like the OP of the post I linked to, I’m basing my code on Eli Fieldsteel’s FN synthesis tutorials. Below are the SynthDefs I have so far. Note that I’m using Supriya, and not sclang.
This is Eli’s SynthDef (in Python):
@synthdef()
def frequency_modulation(
attack_release=(0.01, 3.0),
curve_attack_release=(4, -4),
frequency=500,
modulator_ratio=1,
carrier_ratio=1,
index_scale=(1, 5),
):
amp = 0.2
attack = attack_release[0]
release = attack_release[1]
pan = 0.0
curve_attack = curve_attack_release[0]
curve_release = curve_attack_release[1]
index = index_scale[0]
scaled_index = index_scale[0] * index_scale[1]
index_envelope = EnvGen.kr(
envelope=Envelope(
amplitudes=[index, scaled_index, index],
durations=[attack, release],
curves=[curve_attack, curve_release],
)
)
env = EnvGen.kr(
envelope=Envelope.percussive(
attack_time=attack,
release_time=release,
curve=curve_release,
),
done_action=2,
)
modulator = SinOsc.ar(frequency=frequency * modulator_ratio) * (frequency * modulator_ratio) * index_envelope
carrier = SinOsc.ar(frequency=frequency * carrier_ratio + modulator) * env * amp
signal = Pan2.ar(source=carrier, position=pan)
Out.ar(bus=0, source=signal)
My question is how to handle input and output signals in the SynthDefs based on some of the algorithms. For example, algorithm 5:
I have working code where I split the carrier and modulator into their own SynthDefs. However, that creates complications because looking at something like algorithm 5, it seems that some operators will need more than one In
and Out
UGen. For example. I’ve read that carriers (like operators 1 and 3 in algorithm 5) are summed before being output. So how to do that, and how to implement the feedback in operator 4, is where I’m running to problems. Any suggestions?