«DWG sitar model» by snappizz

on 22 Sep'15 22:02 in guitarinstrumentphysical modelplucked stringsplucksitar

guhhh, lots of complication for not that much payoff. please fork if you have some ideas for how to improve this

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
/*
Based on a model by David Ronan (http://issta.ie/wp-content/uploads/The-Physical-Modelling-of-a-Sitar.pdf).
Requires sc3-plugins.

Lacks shimmer. Sounds more like a banjo than a sitar. I don't know whether
this is just a matter of tuning parameters or whether the model itself needs
fixing.
*/

(
// Single string of a sitar.
SynthDef(\tar, {
	|
	out = 0, in = 0, inscale = 1.0, freq = 440, bw = 1.03, amp = 0.5
	pos = 0.1,
	hc1 = 1, hc3 = 30, hfreq = 3000,
	vc1 = 1, vc3 = 30, vfreq = 3000
	|
	var inp, jawari, snd;
	// Input audio -- may be a pluck impulse (chikari) or audio (tarafdar)
	inp = In.ar(in, 1) * inscale;
	// Jawari (bridge) simulation. This is the heart of Ronan's model.
	// Violins and guitars have vertical bridges. The jawari is flat, and this causes the tar to buzz against the jawari.
	// Physically, end of the string coming in contact the bridge causes the string to shorten.
	// We assume that the audio output is a reasonable approximation of how much contact the string has with the bridge.
	// So we shorten the DWG (by adjusting its frequency) according to its own audio output.
	jawari = LocalIn.ar(1);
	// Make the jawari control rate
	jawari = A2K.kr(jawari);
	// Make the jawari affect the freq exponentially
	jawari = jawari.linexp(-1, 1, bw.reciprocal, bw);
	// The string itself has horizontal and vertical planes, which we simulate with two different DWGPlucked instances
	snd = [
		DWGPlucked.ar(freq * jawari, pos: pos, c1: hc1, c3: hc3, inp: LPF.ar(inp, hfreq)),
		DWGPlucked.ar(freq * jawari, pos: pos, c1: vc1, c3: vc3, inp: LPF.ar(inp, vfreq))
	].sum;
	LocalOut.ar(snd);
	Out.ar(out, snd * amp);
}).add;

SynthDef(\pluckImpulse, {
	|out = 0, t_trig = 0, amp = 0.3|
	Out.ar(out, PinkNoise.ar * EnvGen.kr(Env.perc(0.01, 0.02), t_trig) * amp);
}).add;

// Useful for testing. For programmatic usage use \pluckImpulse
SynthDef(\mousePluck, {
	|out = 0, num = 0, amp = 0.3|
	var m = MouseY.kr(0, 8);
	var trig = (num <= m) & (m < (num + 1)) * MouseButton.kr(0, 1, 0);
	Out.ar(out, PinkNoise.ar * EnvGen.kr(Env.perc(0.01, 0.02), trig) * amp);
}).add;

SynthDef(\sitar, {
	|out = 0, chikari = 0, tarafdar = 0, dry = 0.5, wet = 0.5, amp = 0.5|
	var snd = In.ar(chikari, 1) * dry;
	snd = snd + (In.ar(tarafdar, 1) * wet);
	// Dumb gourd model. I randomly picked freqs/bws/amps.
	// Please let me know if you have some estimates of the resonances of a real sitar gourd.
	snd = snd + BPF.ar(snd, [90, 132, 280], [1.3, 0.9, 1.4], [0.9, 0.6, 0.7]).sum;
	snd = Pan2.ar(snd, 0, amp);
	Out.ar(out, snd);
}).add;
)

(
// Don't take this example tuning seriously.
// I know next to nothing about ragas and sitar tuning.
~chikariFreqs = 48.midicps * [1, 16/15, 5/4, 4/3, 3/2, 8/5, 15/8, 2];
~numChikari = ~chikariFreqs.size;
~tarafdarFreqs = 48.midicps * [1, 16/15, 5/4, 4/3, 3/2, 8/5, 15/8, 2, 2*16/15, 2*5/4, 2*4/3, 2*3/2];
~numTarafdar = ~tarafdarFreqs.size;
)

(
// Pluck impulse busses, one per chikari
~pluckBus = Bus.audio(s, ~numChikari);
// Summed output of all chikari (plucked strings)
~chikariBus = Bus.audio(s, 1);
// Summed output of all tarafdar (sympathetic strings)
~tarafdarBus = Bus.audio(s, 1);
)

// Use the mouse button to strum.

(
~pluckGroup = Group();
~chikariGroup = Group.after(~pluckGroup);
~tarafdarGroup = Group.after(~chikariGroup);

~pluck = ~numChikari.collect { |i|
	Synth(\mousePluck, [
		\out, ~pluckBus.index + i,
		\num, i,
	], ~pluckGroup);
};
~chikari = ~numChikari.collect { |i|
	Synth(\tar, [
		\in, ~pluckBus.index + i,
		\out, ~chikariBus,
		\freq, ~chikariFreqs[i],
		\bw, 1.08,
		\hc1, 4, \hc2, 50,
		\vc1, 3, \vc3, 30,
		\amp, 0.1
	], ~chikariGroup);
};
~tarafdar = ~numTarafdar.collect { |i|
	Synth(\tar, [
		\in, ~chikariBus,
		\inscale, 0.1,
		\out, ~tarafdarBus,
		\freq, ~tarafdarFreqs[i] * 1.0.rand.linexp(0, 1, 0.99, 1.01),
		\pos, 0.4,
		\bw, 1.08,
		\hc1, 4, \hc2, 50,
		\vc1, 3, \vc3, 30,
		\amp, 0.1
	], ~tarafdarGroup);
};
~sitar = Synth.after(~tarafdarGroup, \sitar, [
	\chikari, ~chikariBus,
	\tarafdar, ~tarafdarBus,
	\dry, 1,
	\wet, 0.5,
	\amp, 0.8
]);
)
raw 4172 chars (focus & ctrl+a+c to copy)
reception
comments