«Basic FM Matrix Synth» by LFSaw

on 22 Mar'13 17:37 in fmsynthmatrix

A basic FM matrix synth (Ndef) with GUI

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
// still have to work out the right modulation index calculation

q = q ? ();
q.numOscs = 5;

(

Ndef(\fmMatrix, {
	var numOscs = q.numOscs;
	
	var oscs;
	var modFreqs = \modFreqs.kr({|i| 1000}!numOscs);
	var modIndex = \modIndex.kr({|i|   0}!(2**numOscs)).clump(numOscs);
	var amps     = \amps    .kr({|i|
		(i == (numOscs-1)).if({1}, {0}) }!numOscs);
	var tmpOsc;
	
	oscs = modFreqs.inject([], {|oscArray, freq, i|
		tmpOsc = SinOscFB.ar(
			freq
			+ oscArray.inject(0, {|sum, osc, j| 
				sum + (osc * modIndex[i][j].linlin(0, 3, 0, 10000))
			}),
			modIndex[i][i]
		);
		
		oscArray ++ tmpOsc;
	}); // end inject
	
	(oscs * amps).sum;
})
)

Ndef(\fmMatrix).gui

(
var specs = (
	modFreqs: [0.1, 10000, \exp, 0].asSpec,
	modIndex: [0, 3, \lin, 0].asSpec;
);
var modIndex     = {0!q.numOscs}!q.numOscs;
var modFreqState = 1000!q.numOscs;
var ampState     = 0!q.numOscs;

q.win = Window.new("FM Matrix", Rect(100, 100, q.numOscs * 30, 800)).decorate.front;


StaticText(q.win, Rect(10, 10, 200, 20)).string_("modIndex");
q.win.view.decorator.nextLine;
q.numOscs.do{|i|
	(i+1).do{|j|
		var ez;
		
		ez = EZKnob(q.win, Rect(25, 25, 25, 50), 
			controlSpec: specs[\modIndex],
			initAction: true
		)
		.action_{|knob| 
			// state[i][j] = specs[key].map(knob.value);
			modIndex[i][j] = knob.value;
			Ndef(\fmMatrix).setn(\modIndex, modIndex.flat);
		};
		ez.knobView.mode_(\vert);
	};
	q.win.view.decorator.nextLine;
};
q.win.view.decorator.nextLine;

StaticText(q.win, Rect(10, 10, 200, 20)).string_("modFreqs");
q.win.view.decorator.nextLine;
q.numOscs.do{|i|
	var ez;
	ez = EZKnob(q.win, Rect(0, 0, 25, 50), 
		controlSpec: specs[\modFreqs],
		initAction: true
	)
	.action_{|knob|
		modFreqState[i] = knob.value;
		Ndef(\fmMatrix).setn(\modFreqs, modFreqState);
	};
	ez.knobView.mode_(\vert);
};

q.win.view.decorator.nextLine;
StaticText(q.win, Rect(10, 10, 200, 20)).string_("amps");
q.win.view.decorator.nextLine;
q.numOscs.do{|i|
	EZSlider(q.win, Rect(0, 0, 25, 100), label: i, layout: 'vert').action_{|slider|
		ampState[i] = slider.value;
		Ndef(\fmMatrix).setn(\amps, ampState);
	}
}
)
raw 2190 chars (focus & ctrl+a+c to copy)
reception
comments
g_montel user 27 Oct'18 09:29

Thanks ! Is any quark needed for the function "decorate" ? I'm getting an error on SC 3.9.3.

russell.r.johnston user 27 Oct'18 13:54

"decorate" is in wslib quark

g_montel user 28 Oct'18 13:54

thanks !