{
   "description" : "These are variations using lsystems I built for: https://anvaka.github.io/lsystem/\r\n\r\nI've only changed the LSystem itself, not the note selections or instruments.",
   "ancestor_list" : [
      "1-5bp"
   ],
   "name" : "Re: Generating Graphics and Music From The Dragon Curve",
   "author" : "blueprint",
   "code" : "// if you have never done so, run the following code first\r\n(\r\nQuarks.install(\"https://github.com/shimpe/panola\");\r\nQuarks.install(\"https://github.com/shimpe/sc-lsystem\");\r\n)\r\n\r\n// Also try\r\n//\r\n// FF+[c+F-F-F]-[-F+F+dF]\r\n\r\n(\r\ns.waitForBoot({\r\n    var player;\r\n    var lsys = LSystem(\r\n        iterations:4,\r\n        axiom:\"Y\",\r\n        constants:Set[],\r\n        rules:(\\X : \"X[-F+FF][+F-FF]FX\",\r\n\t\t\\Y : \"YFX[+Y][-Y]\"));\r\n    var interp = LSystemInterpreter(\r\n        lsystem:lsys,\r\n        globalstate:(\r\n            \\acceptablenotes : Set[\"c3\", \"d3\", \"e3\", \"g3\", \"a3\", \"c4\", \"d4\", \"e4\", \"g4\", \"a4\"],\r\n            \\patternnotes : [\"c3\"],\r\n            \\transpose : 0,\r\n            \\tempo : 16,\r\n        ),\r\n        actions:(\r\n            // whenever you encounter an F, extend the list of played notes\r\n            'F' : [{ | glob, loc |\r\n                // extend list notes being played (using some randomness :) )\r\n                glob[\\patternnotes] = glob[\\patternnotes].add(glob[\\acceptablenotes].choose.debug(\"add new note\"));\r\n\r\n                // always return state at the end\r\n                [glob, loc];\r\n            }, nil],\r\n            // whenever you encounter a +, transpose up\r\n            '+': [{ | glob, loc |\r\n                glob[\\transpose] = (glob[\\transpose] + [1,2,3,4].choose.debug(\"transpose up\")).clip(-12,12);\r\n                // always return state at the end\r\n                [glob, loc];\r\n            }, nil],\r\n            // whenever you encounter a -, transpose down\r\n            '-': [{ | glob, loc |\r\n                \"transpose down\".postln;\r\n                glob[\\transpose] = (glob[\\transpose] - [1,2,3,4].choose.debug(\"transpose down\")).clip(-12, 12);\r\n                // always return state at the end\r\n                [glob, loc];\r\n            }, nil],\r\n            // whenever you encounter an X, remove first note from the played notes\r\n            'X' : [{ | glob, loc |\r\n                \"remove first note\".postln;\r\n                if (glob[\\patternnotes].size > 1) {\r\n                    // keep at least one note\r\n                    glob[\\patternnotes] = glob[\\patternnotes].reverse;\r\n                    glob[\\patternnotes].pop;\r\n                    glob[\\patternnotes] = glob[\\patternnotes].reverse;\r\n                };\r\n                // always return state at the end\r\n                [glob, loc];\r\n            }, nil],\r\n            // whenever you encounter a Y, change tempo (randomly) )\r\n            'Y' : [{ | glob, loc |\r\n                glob[\\tempo] = (glob[\\tempo] * [0.3, 1.2, 1.4, 1.7, 2, 0.5, 3].choose.debug(\"tempo factor\")).clip(8,32);\r\n                // always return state at the end\r\n                [glob, loc];\r\n            }, nil],\r\n        )\r\n    );\r\n\r\n    var interp2 = interp.deepCopy();\r\n\r\n    SynthDef(\\kalimba, {\r\n        |out = 0, freq = 440, amp = 0.1, mix = 0.1|\r\n        var snd, click;\r\n        // Basic tone is a SinOsc\r\n        snd = SinOsc.ar(freq) * EnvGen.ar(Env.perc(0.03, Rand(3.0, 4.0), 1, -7), doneAction: 2);\r\n        snd = HPF.ar( LPF.ar(snd, 380), 120);\r\n        // The \"clicking\" sounds are modeled with a bank of resonators excited by enveloped white noise\r\n        click = DynKlank.ar(`[\r\n            // the resonant frequencies are randomized a little to add variation\r\n            // there are two high resonant freqs and one quiet \"bass\" freq to give it some depth\r\n            [240*ExpRand(0.97, 1.02), 2020*ExpRand(0.97, 1.02), 3151*ExpRand(0.97, 1.02)],\r\n            [-9, 0, -5].dbamp,\r\n            [0.8, 0.07, 0.08]\r\n        ], BPF.ar(PinkNoise.ar, 6500, 0.1) * EnvGen.ar(Env.perc(0.001, 0.01))) * 0.1;\r\n        snd = (snd*mix) + (click*(1-mix));\r\n        snd = Mix( snd );\r\n        Out.ar(out, Pan2.ar(snd, 0, amp));\r\n    }).add;\r\n\r\n    SynthDef(\\flute, {\r\n\t\t| out = 0, freq = 440, amp = 1.0, a = 0.1, r = 0.1|\r\n\t\t//var fmod = 1; // clean\r\n\t\t//var fmod = LFCub.kr(freq:1/12).range(1, LFNoise2.kr(freq:12.0).range(1,1.1)); // tone deaf flute\r\n\t\tvar fmod = LFCub.kr(freq:1/12).range(1, LFNoise2.kr(freq:12.0).range(1,1.02)); // flute-like sound\r\n\t\tvar env = EnvGen.ar(Env.perc(a, r), levelScale:0.5, doneAction:2);\r\n\t\tvar snd = SinOsc.ar(freq * fmod)!2;\r\n\t\tOut.ar(bus:out, channelsArray:(env*(amp*snd).tanh));\r\n\t}).add;\r\n\r\n    s.sync;\r\n\r\n    fork {\r\n        var skipfirstidx = 0; // increase to skip more steps at the beginning\r\n        var sz = lsys.getCalculatedString.size();\r\n        lsys.getCalculatedString.do({\r\n            | chr, idx |\r\n            var pattern;\r\n            var transposedpattern;\r\n            var transposition;\r\n            var transposition2;\r\n            (\"*** PART\" + (idx+1) + \"OF\" + sz + \"***\").postln;\r\n            interp.step(idx);\r\n            interp2.step(idx);\r\n            // start playing from step skipfirstidx\r\n            if (idx > skipfirstidx) {\r\n                var repeats = inf;\r\n                if (idx == (sz-1)) { repeats = 3; }; // don't repeat last pattern indefinitely\r\n                transposition = interp.globalState()[\\transpose].debug(\"transpose\");\r\n                transposition2 = interp2.globalState()[\\transpose].debug(\"transpose2\");\r\n                pattern = Pn(\r\n                    Ppar([\r\n                        Padd(\\midinote, Pfunc({transposition}),\r\n                            Panola.new(\r\n                                notation:interp.globalState()[\\patternnotes].join(\" \").debug(\"notes1\"),\r\n                                dur_default:interp.globalState()[\\tempo]\r\n                            ).asPbind(\\kalimba)\r\n                        ),\r\n                        Padd(\\midinote, Pfunc({transposition2}),\r\n                            Panola.new(\r\n                                notation:interp2.globalState()[\\patternnotes].join(\" \").debug(\"notes2\"),\r\n                                dur_default:interp2.globalState()[\\tempo]*2,\r\n                                playdur_default:1,\r\n                                vol_default:0.1\r\n                            ).asPbind(\\flute),\r\n                        )\r\n                    ]),\r\n                    repeats);\r\n                if (player.notNil) { player.stop; };\r\n                player = pattern.play();\r\n                1.wait;\r\n                if (idx == (sz-1)) {\r\n                    \"*** ABOUT TO FINISH ***\".postln;\r\n                };\r\n            }\r\n        });\r\n    }\r\n});\r\n)",
   "is_private" : null,
   "id" : "1-5gT",
   "labels" : [
      "code fork",
      "minimal",
      "generative",
      "graphics",
      "panola",
      "lsystem",
      "dragon"
   ]
}
