«DWG sitar model» by snappizz
on 22 Sep'15 22:02 inguhhh, 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 ]); )
descendants
full graph
reception
comments