//Wavetable vector style synth. 2020 Matias Monteagudo.
//My interface options. Change at will.
(
Server.local.options.device = "ASIO : ASIO PreSonus FireStudio";
Server.local.options.sampleRate=48000;
Server.local.options.hardwareBufferSize=128;
)
//Reverb.
((
SynthDef(\verb, {
|in, predelay=1, revtime=2, lpf=4500,mix=0.5,amp=1,out=0|
var dry,wet,temp,sig;
dry = In.ar(in, 2);
temp = In.ar(in, 2);
wet=0;
temp=DelayN.ar(temp, 0.2, predelay);
32.do {temp=AllpassN.ar(temp, 0.05, {Rand(0.001,0.05)}!2,revtime);
temp=LPF.ar(temp,lpf);
wet=wet+temp;
};
sig=XFade2.ar(dry,wet,mix*2-1,amp);
Out.ar(out,sig);
}).add;
);
)
//After evaluating this. You can hit "CMD+." or even restart the server and the verb will be there. (You'll need to re evaluate only if you restart SC)
(
~revBus = Bus.audio(s,2);
~createReverb={~reverbSynth=Synth(\verb, [\mix,0.23, \in, ~revBus])};
ServerTree.add(~createReverb);
)
ServerTree.removeAll;//If you wanna empty the Tree.
//The buffers. You can use any waveform you want. Or bigger samples if you wanna experiment. it will probably work fine with loops too.
(
b=Buffer.readChannel(s,"G:/SAMPLES/Waveforms/AKWF_violin/AKWF_violin_0001.wav");
c=Buffer.readChannel(s,"G:/SAMPLES/Waveforms/AKWF_violin/AKWF_violin_0002.wav");
d=Buffer.readChannel(s,"G:/SAMPLES/Waveforms/AKWF_violin/AKWF_violin_0003.wav");
e=Buffer.readChannel(s,"G:/SAMPLES/Waveforms/AKWF_violin/AKWF_violin_0005.wav");
f=Buffer.readChannel(s,"G:/SAMPLES/Waveforms/AKWF_violin/AKWF_violin_0006.wav");
g=Buffer.readChannel(s,"G:/SAMPLES/Waveforms/AKWF_violin/AKWF_violin_0007.wav");
h=Buffer.readChannel(s,"G:/SAMPLES/Waveforms/AKWF_violin/AKWF_violin_0008.wav");
i=Buffer.readChannel(s,"G:/SAMPLES/Waveforms/AKWF_violin/AKWF_violin_0009.wav");
)
//You can test your buffers here.
{Out.ar(0,[PlayBuf.ar(1,b)]!2)}.play;
{Out.ar(0,[PlayBuf.ar(1,c)]!2)}.play;
{Out.ar(0,[PlayBuf.ar(1,d)]!2)}.play;
{Out.ar(0,[PlayBuf.ar(1,e)]!2)}.play;
{Out.ar(0,[PlayBuf.ar(1,f)]!2)}.play;
{Out.ar(0,[PlayBuf.ar(1,g)]!2)}.play;
{Out.ar(0,[PlayBuf.ar(1,h)]!2)}.play;
{Out.ar(0,[PlayBuf.ar(1,i)]!2)}.play;
//Connect MIDI devices. (0,6) is my keyboard under a virtual MIDI cable. You probably need to evaluate only "MIDIIn.connectAll"
MIDIClient.init;
MIDIIn.connect(0,6);
MIDIIn.disconnect(0,6);
MIDIIn.connectAll
//The Synth. It will crossfade across all buffers (like a Vector synth)
(
SynthDef(\wts,{
| gate=1,vel=1,fq=5,out,bend=0,vr=6,va=0.1|
var sig1,sig2,sig3,sig4,sig5,sig6,sig7,sig8,mix,vib,env, signal;
vib=SinOsc.ar(vr,0,EnvGen.kr(Env([0,0.1],[1],4),1)*va);
sig1=PlayBuf.ar(1,b,fq+vib* bend.midiratio,gate,0,1);
sig2=PlayBuf.ar(1,c,fq+vib* bend.midiratio,gate,0,1);
sig3=PlayBuf.ar(1,d,fq+vib* bend.midiratio,gate,0,1);
sig4=PlayBuf.ar(1,e,fq+vib* bend.midiratio,gate,0,1);
sig5=PlayBuf.ar(1,f,fq+vib* bend.midiratio,gate,0,1);
sig6=PlayBuf.ar(1,g,fq+vib* bend.midiratio,gate,0,1);
sig7=PlayBuf.ar(1,h,fq+vib* bend.midiratio,gate,0,1);
sig8=PlayBuf.ar(1,i,fq+vib* bend.midiratio,gate,0,1);
mix=DXMix.ar(Dseq([0,1,2,3,4,5,6,7],inf),`[sig1,sig2,sig3,sig4,sig5,sig6,sig7,sig8],SinOsc.ar(Rand(0.01,1),mul:Rand(0.003, 0.01),add:Rand(0.7,0.9))); //Each note modulates in Xfade speed.
env = EnvGen.ar(Env.asr(0.2, vel, 0.005),gate, doneAction: 2);
Out.ar(~revBus, mix*env!2)
}).add;
)
~notes
//MIDI functions. Play the synth with a keyboard. (Or equivalent MIDI controller)
(
~notes = Array.newClear(128);
~liftednotes = Array.newClear(128);
~pedaldown = 0;
~cc1= 0;
~bend = 8192;
MIDIdef.noteOn(\noteOn, {
arg vel, nn, chan, src;
if(~notes[nn] != nil){ //release notes if you're trying to repeat them
~notes[nn].set(\gate, 0); ~notes[nn] = nil
};
~notes[nn] = Synth.new(\wts,
[
\fq, nn.midicps/40,
\gate, 1,
\vel, vel/1000,
\vr, ~cc1.linlin(0, 127, 0, 8),
\va, ~cc1.lincurve(0, 127, 0, 1,-100),//This uses the last used value from cc1
\bend, ~bend.linlin(0, 16383, -2, 2),//This uses the last used value from your pitch bend wheel.
]
);
});
MIDIdef.noteOff(\noteOff, {
arg vel, nn;
if(~pedaldown == 127) {//if pedal is down:
~liftednotes[nn] = ~notes[nn];
}
{//else if pedal is up:
~notes[nn].set(\gate,0);
~notes[nn] = nil;
}
} );
MIDIdef.cc(\cc1, {
arg val, chan, src;
['ModWheel', val].postln;
~cc1 = val; //This will store the last used cc1 value.
~notes.do{arg synth; synth.set(\vr, val.linlin(0, 127, 0, 8), \va, val.lincurve(0,127,0,1,-100))};
},ccNum:1, chan: 0);
MIDIdef.bend(\bend, {
arg val, chan, src;
['bend', val, chan, src].postln; // [ bend, 11888, 0, 1 ]
~bend = val;//This will store the last used bend value.
// also update any notes currently in ~notes
~notes.do{arg synth; synth.set(\bend, val.linlin(0, 16383, -2, 2))};
}, chan: 0);
MIDIdef.cc(\pedal,{
arg val, key;
['pedal',val].postln;
if(key == 64) { //only worry about pedal control messages
~pedaldown = val;
if(val == 0) {
~liftednotes.do{arg synth; synth.set(\gate, 0);
}
};
};
},ccNum:64);
)