You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

276 lines
9.9 KiB
Plaintext

(
//busses
~masterBus = Bus.audio(s, 1);
~guitarBus = Bus.audio(s, 1);
~accompHighBus = Bus.audio(s, 1);
~accompLowLowerBusA = Bus.audio(s, 1);
~accompLowUpperBusA = Bus.audio(s, 1);
~accompLowLowerBusB = Bus.audio(s, 1);
~accompLowUpperBusB = Bus.audio(s, 1);
~interludeTremoloBus = Bus.audio(s, 1);
~clickBus = Bus.audio(s, 1);
SynthDef(\masterPlayerControl ++ ~hash, {
arg sel = 0,
masterVol = 1, masterMute = 1,
guitarVol = 1, guitarPan = 0, guitarMute = 0,
accompHighVol = 1, accompHighPan = 0, accompHighMute = 1,
accompLowLowerVol = 1, accompLowLowerPan = 0, accompLowLowerMute = 1,
accompLowUpperVol = 1, accompLowUpperPan = 0, accompLowUpperMute = 1,
interludeVol = 1, interludePan = 0, interludeMute = 1,
clickVol = 1, clickPan = 0, clickMute = 1;
var guitarSig, accompHighSig, accompLowLowerSig, accompLowUpperSig, interludeSig, clickSig,
guitarSigPanned, accompHighSigPanned, accompLowLowerSigPanned, accompLowUpperSigPanned, interludeSigPanned, clickSigPanned,
masterSig, imp;
guitarSig = In.ar(~guitarBus) * guitarVol;
accompHighSig = In.ar(~accompHighBus) * accompHighVol;
accompLowLowerSig = Mix.ar(
[
In.ar(~accompLowLowerBusA) * EnvGen.kr(Env.asr(0.001, 1, 0.1), (sel + 1) % 2),
In.ar(~accompLowLowerBusB) * EnvGen.kr(Env.asr(0.001, 1, 0.1), sel)
]
) * accompLowLowerVol;
accompLowUpperSig = Mix.ar(
[
In.ar(~accompLowUpperBusA) * EnvGen.kr(Env.asr(0.001, 1, 0.1), (sel + 1) % 2),
In.ar(~accompLowUpperBusB) * EnvGen.kr(Env.asr(0.001, 1, 0.1), sel)
]
) * accompLowUpperVol;
interludeSig = In.ar(~interludeTremoloBus) * interludeVol;
clickSig = In.ar(~clickBus) * clickVol;
guitarSigPanned = Pan2.ar(guitarSig * guitarMute, guitarPan);
accompHighSigPanned = Pan2.ar(accompHighSig * accompHighMute, accompHighPan);
accompLowLowerSigPanned = Pan2.ar(accompLowLowerSig * accompLowLowerMute, accompLowLowerPan);
accompLowUpperSigPanned = Pan2.ar(accompLowUpperSig * accompLowUpperMute, accompLowUpperPan);
interludeSigPanned = Pan2.ar(interludeSig * interludeMute, interludePan);
clickSigPanned = Pan2.ar(clickSig * clickMute, clickPan);
masterSig = Mix.ar(
[
guitarSigPanned,
accompHighSigPanned,
accompLowLowerSigPanned,
accompLowUpperSigPanned,
interludeSigPanned
]) * masterVol * masterMute;
Out.ar(0, masterSig);
Out.ar(2, clickSigPanned); //change this if you want the click to go somewhere else
imp = Impulse.kr(10);
SendReply.kr(imp,
'/masterLevels' ++ ~hash,
values: [Amplitude.kr(masterSig)]);
SendReply.kr(imp,
'/trackLevels' ++ ~hash,
values:
[
Amplitude.kr(guitarSig), Amplitude.kr(accompHighSig),
Amplitude.kr(accompLowLowerSig), Amplitude.kr(accompLowUpperSig),
Amplitude.kr(interludeSig), Amplitude.kr(clickSig)
]
);
}).add;
SynthDef(\transport ++ ~hash, {arg measure = 0, beat = 0, gate = 1, dur = 1;
SendReply.kr(Impulse.kr(0) * (measure > 0) * (beat > 0),'/measureClock' ++ ~hash, values: [measure, beat]);
SendReply.kr(Impulse.kr(0) * (measure < 1) * (beat < 1),'/nextSubsection' ++ ~hash);
EnvGen.kr(Env.sine(dur), gate, doneAction: 2);
}).add;
SynthDef(\click ++ ~hash, {arg beat = 0, gate = 1, dur = 1;
Out.ar(~clickBus, 10 * BPF.ar(WhiteNoise.ar * EnvGen.kr(Env.perc(0.01, 0.1), gate), 440 * ((beat <= 1) + 1), 0.02));
EnvGen.kr(Env.sine(dur), gate, doneAction: 2);
}).add;
//~~~~karplus
SynthDef(\karplus ++ ~hash, {arg freq, gate = 1, amp = 0.5, bus;
Out.ar(bus,
Pluck.ar(WhiteNoise.ar(0.1), Impulse.kr(0), 220.reciprocal, freq.reciprocal, 10, coef:0) *
Linen.kr(gate, doneAction: 2) * amp)
}).add;
//~~~~accompaniment
SynthDef(\accompBass ++ ~hash, {arg freq1 = 100, freq2 = 100, gate = 1, amp = 0.5, busLower, busUpper, cutoff = 0;
var env, lower, upper;
env = EnvGen.kr(Env.perc(0.1, 10, level: amp), Impulse.kr(0) + Changed.kr(freq2));
lower = SinOsc.ar(freq1, 0, 0.5) * env;
upper = SinOsc.ar(freq2, 0, 0.5) * env;
Out.ar(busLower, lower);
Out.ar(busUpper, upper)
}).add;
//this is not releasing properly
SynthDef(\accompTreble ++ ~hash, {arg freq, gate = 1, sustain, amp, bus;
var treble;
treble = SinOsc.ar(freq, 0, EnvGen.kr(Env.linen(0.3, 0, 0.7, amp * 0.075, \sine), gate, timeScale: sustain, doneAction: 2));
Out.ar(bus, treble)
}).add;
//~~~~interlude
//note that this is sensitive to frequency and tremolo rate inputs
SynthDef(\interludeTremelo ++ ~hash, {arg gate = 0, amp = 1, freq1, freq2, tremRate;
var tremeloTrig, trem, freq, sig, feedback, fade;
//fast tremelo - note that this can be slower so long as the delaytime of the feedback remains short
tremeloTrig = Impulse.kr(tremRate);
//tremelo between two notes
trem = Select.kr(Stepper.kr(tremeloTrig, 0, 0, 1), [freq1, freq2]);
//occasionally tremelo on same note
freq = Select.kr(TWChoose.kr(Dust.kr(10), [0, 1, 2], [5, 1, 1], 1), [trem, freq1, freq2]);
//generate signal
sig = VarSaw.ar(freq, 0, 0.3, 0.1) * EnvGen.kr(Env.perc(0.01, 0.1), tremeloTrig);
//feedback
feedback = CombC.ar(sig, 0.2, tremRate.reciprocal, 5);
fade = feedback * EnvGen.ar(Env.asr(15, 1, 15, \sine), gate) * amp * 0.75;
Out.ar(~interludeTremoloBus, fade);
}).add;
//~~~~gen music
~genPatterns = {arg guitarSeqIn, accompLowSeqIn, accompHighSeqIn, sectionSeqIn, beatFrac = 1/8;
var calcSustains, genSectionSec, sectionLimits, measureCount;
//~~~~helper sus function
calcSustains = {arg stringSeq, durSeq;
var res = [];
stringSeq.size.do({arg index;
var curString, dur, count;
if(stringSeq[index].isRest.not, {
curString = stringSeq[index];
dur = durSeq[index];
count = 1;
while({(stringSeq[(index + count).clip(0, stringSeq.size - 1)] != curString) &&
(dur < 16) && (count < 100)}, {
dur = dur + durSeq[(index + count).clip(0, durSeq.size - 1)];
count = count + 1;
});
res = res.add(dur.clip(0, 16));
}, {
res.add(Rest());
});
});
res
};
genSectionSec = {arg seq, startTime, endTime, type;
var durSum, resSeqs, inSecs, mult;
durSum = 0;
resSeqs = [];
seq.do({arg item;
if((durSum >= startTime) && (durSum < endTime), {
var dur = durSum - startTime;
if((resSeqs.size == 0) && (dur > 0), {
switch(type,
0, {resSeqs = resSeqs.add([Rest(-1), Rest(-1), dur])},
1, {resSeqs = resSeqs.add([Rest(-1), Rest(-1), dur])},
2, {resSeqs = resSeqs.add([Rest(-1), dur, dur])})
});
resSeqs = resSeqs.add(item);
});
durSum = durSum + if(type == 2, {item[1]}, {item[2]});
});
resSeqs
};
measureCount = 0;
sectionLimits = [];
sectionSeqIn.slice(nil, 0).add(100000).doAdjacentPairs({arg a, b; sectionLimits = sectionLimits.add([a, b])});
~sectionStartMeasure = [];
sectionLimits.collect({arg timePair, secIndex;
var startTime, endTime, beatLength, beatSeq, measureSeq,
guitarSecSeq, accompLowSecSeq, accompHighSecSeq,
stringSeq, fretSeq, harmLimit, freqSeq, durSeq, susSeq, trigSeq, openStrings, pattern;
startTime = timePair[0];
endTime = timePair[1];
if((secIndex % 4) == 0, {measureCount = 0});
beatLength = (endTime - startTime) / 8;
beatSeq = ((beatLength / 2) - 1).asInteger.collect({[1, 2]});
beatSeq = if((beatLength % 2) == 0, {beatSeq.add([1, 2])}, {beatSeq.add([1, 2, 3])});
measureSeq = measureCount + beatSeq.collect({arg measure, mIndex; measure.collect({mIndex + 1})}).flat;
~sectionStartMeasure = ~sectionStartMeasure.add(measureCount + 1);
measureCount = measureSeq.last;
beatSeq = beatSeq.flat;
measureSeq = measureSeq.add(0);
beatSeq = beatSeq.add(0);
guitarSecSeq = genSectionSec.value(guitarSeqIn, startTime, endTime, 0);
accompLowSecSeq = genSectionSec.value(accompLowSeqIn, startTime, endTime, 1);
accompHighSecSeq = genSectionSec.value(accompHighSeqIn, startTime, endTime, 2);
if(accompHighSecSeq == [], {accompHighSecSeq = [[Rest(-1), 1, 0], [Rest(-1), 1, 0]]});
openStrings = [1/1, 3/2, 2/1, 5/2, 35/12, 7/2];
harmLimit = [9, 8, 7, 6, 5, 4];
stringSeq = guitarSecSeq.slice(nil, 0);
fretSeq = guitarSecSeq.slice(nil, 1);
durSeq = guitarSecSeq.slice(nil, 2);
susSeq = calcSustains.value(stringSeq, durSeq);
freqSeq = stringSeq.collect({arg string, index;
if(string.isRest, {Rest()}, {
var midi, freq;
//this is transposed up because karplus-strong does not really sound correctly in the guitar range
midi = (62.midicps * openStrings[string]).cpsmidi + fretSeq[index];
freq = midi.midicps * if((secIndex % 4) != 3, {1}, {[1, harmLimit[string].rand + 1].choose})})
});
pattern = EventPatternProxy.new;
pattern.source = Ppar([
Pbind(
\instrument, \karplus ++ ~hash,
\amp, 0.3,
\dur, Pseq(durSeq * beatFrac),
\sustain, Pseq(susSeq * beatFrac),
\freq, Pseq(freqSeq),
\bus, ~guitarBus.index),
if(accompLowSecSeq.size > 1, {
Pmono(
\accompBass ++ ~hash,
\amp, 0.5,
\freq1, Pseq(accompLowSecSeq.slice(nil, 0)),
\freq2, Pseq(accompLowSecSeq.slice(nil, 1)),
\dur, Pseq(accompLowSecSeq.slice(nil, 2)) * beatFrac,
\busLower, if(secIndex % 2 == 0, {~accompLowLowerBusA.index}, {~accompLowLowerBusB.index}),
\busUpper, if(secIndex % 2 == 0, {~accompLowUpperBusA.index}, {~accompLowUpperBusB.index}))
}, {
Pmono(
\accompBass ++ ~hash,
\amp, 0.5,
\freq1, Pseq([accompLowSecSeq[0][0]]),
\freq2, Pseq([accompLowSecSeq[0][1]]),
\dur, Pseq([accompLowSecSeq[0][2]]) * beatFrac,
\busLower, if(secIndex % 2 == 0, {~accompLowLowerBusA.index}, {~accompLowLowerBusB.index}),
\busUpper, if(secIndex % 2 == 0, {~accompLowUpperBusA.index}, {~accompLowUpperBusB.index}))
}),
Pbind(
\instrument, \accompTreble ++ ~hash,
//\freq, Pseq(accompHighSecSeq.slice(nil, 0)),
\freq, Pseq(accompHighSecSeq.slice(nil, 0).curdle(0.3).collect({arg item; item.cpsmidi - 0.16 + 0.32.rand}).midicps.flat),
\dur, Pseq(accompHighSecSeq.slice(nil, 1) * beatFrac),
\sustain, Pseq(accompHighSecSeq.slice(nil, 2) * beatFrac),
\amp, 0.5,
\bus, ~accompHighBus.index),
Pbind(
\instrument, \transport ++ ~hash,
\measure, Pseq(measureSeq),
\beat, Pseq(beatSeq),
\dur, beatFrac * 8
),
Pbind(
\instrument, \click ++ ~hash,
\beat, Pseq(beatSeq.drop(-1)),
\dur, beatFrac * 8
)
]);
pattern
});
};
)