{
   "name" : "modulate pattern keys with arbitrary envelopes",
   "author" : "grirgz",
   "ancestor_list" : [],
   "description" : "",
   "labels" : [
      "pattern",
      "event"
   ],
   "is_private" : null,
   "id" : "1-4Ri",
   "code" : "(\r\nSynthDef(\\ctlPoint, { |outbus, value, time, curve|\r\n       var     start = In.kr(outbus, 1);\r\n       ReplaceOut.kr(outbus, EnvGen.kr(Env([start, value], [time], curve), doneAction: 2));\r\n}).store;\r\n\r\n// can't Pchain the resulting pattern, so use the \"chain\" argument to chain the inner pattern\r\n~penvcontrol = { arg pat, chain=nil;\r\n\tvar buskeydict = Dictionary.new;\r\n\tvar respat = List.new;\r\n\tvar ctlpatlist = List.new;\r\n\tvar pbindpat;\r\n\tvar makebusmap;\r\n\r\n\tmakebusmap = { arg key;\r\n\t\tPfunc { arg ev; ev[key].asMap }\r\n\t};\r\n\t\r\n\tif(pat.class == EventPatternProxy) {\r\n\t\tpbindpat = pat.source;\r\n\t} {\r\n\t\tpbindpat = pat\r\n\t};\r\n\r\n\tpbindpat.patternpairs.pairsDo { arg key,val;\r\n\t\tvar buskey;\r\n\t\tvar env;\r\n\t\tvar cbus;\r\n\t\tvar ctlpat;\r\n\t\tif(val.class == Ref) {\r\n\t\t\tbuskey = \"bus_\" ++ key;\r\n\t\t\trespat.add(key);\r\n\t\t\trespat.add(makebusmap.(buskey));\r\n\t\t\tenv = val.value;\r\n\t\t\tbuskeydict[buskey] = env.levels[0];\r\n\t\t\tcbus.set(env.levels[0]);\r\n\t\t\tctlpat = Pbind(\r\n\t\t\t\t\\instrument, \\ctlPoint,\r\n\t\t\t\t\\value, Pseq(env.levels[1..],inf),\r\n\t\t\t\t\\time, Pseq(env.times,inf) / Pfunc({thisThread.clock.tempo}),\r\n\t\t\t\t\\group, Pkey(\\busgroup),\r\n\t\t\t\t\\outbus, Pfunc { arg ev; ev[buskey].index },\r\n\t\t\t\t\\curve, env.curves,\r\n\t\t\t\t\\dur, Pseq(env.times,inf)\r\n\t\t\t);\r\n\t\t\tctlpatlist.add(ctlpat);\r\n\t\t} \r\n\t};\r\n\r\n\tPfset({\r\n\t\t\tbuskeydict.keysValuesDo { arg key, val;\r\n\t\t\t\tcurrentEnvironment[key] = Bus.control(s, 1);\r\n\t\t\t\tcurrentEnvironment[key].set(val);\r\n\t\t\t};\r\n\t\t\tcurrentEnvironment[\\busgroup] = Group.new;\r\n\t\t},\r\n\t\tPfpar(\r\n\t\t\t[\r\n\t\t\t\tif(chain.notNil) {\r\n\t\t\t\t\tchain <> Pbind(*respat) <> pat;\r\n\t\t\t\t} {\r\n\t\t\t\t\tPbind(*respat) <> pat;\r\n\t\t\t\t}\r\n\t\t\t]\r\n\t\t\t++ ctlpatlist\r\n\t\t),\r\n\t\t{\r\n\t\t\tbuskeydict.keysValuesDo { arg key, val;\r\n\t\t\t\tcurrentEnvironment[key].free;\r\n\t\t\t};\r\n\t\t\tcurrentEnvironment[\\busgroup].freeAll;\r\n\t\t\tcurrentEnvironment[\\busgroup].free;\r\n\t\t}\r\n\t)\r\n};\r\n\r\n)\r\n\r\n\r\n(\r\n~pb = ~penvcontrol.(Pbind(\r\n \\instrument, \\default,\r\n \\freq, Ref(Env([100,400,500],[1,0.5],0)),  \r\n // the Ref is used by ~penvcontrol to detect envelopes\r\n \\amp, Ref(Env([0.1,1,0.1],[2,2],0)),\r\n \\sustain, 1,\r\n //\\dur, 1,\r\n \\dur, Pn(1,2) // use finite pattern to restart env in sync\r\n));\r\n//~pb.play\r\nPn(~pb).play\r\n\r\n)"
}
