( //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 }); }; )