Guest User

KippleGEN or, The Empathy Box - D.L.Lythgoe (2024)

a guest
Oct 21st, 2024
38
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //////////////////////////////////////////////
  2. //                                          //
  3. //      KippleGEN or, The Empathy Box       //
  4. //      2024                                //
  5. //      Daniel L. Lythgoe                   //
  6. //                                          //
  7. //////////////////////////////////////////////
  8.  
  9. // This is a script for an (ambient) wavetable synth and sequencer with GUI.
  10. // Place the desired sound files in a subfolder called "/Samples/", relative to the folder the Supercollider document is located in.
  11. // This works best with very short sound files; longer ones can sometimes break the interpreter.
  12. // You can create your own .wav files, but a library of single cycle wave forms that can be used with the synth can be downloaded here:
  13. // https://www.adventurekid.se/akrt/waveforms/adventure-kid-waveforms/
  14. // I recommend the OVERTONE pack to start
  15. // Special thanks for Reflectives on Youtube and his excellent video "Wave Terrainish adventures with VOsc"
  16.  
  17. // Boot the server
  18. s.boot;
  19.  
  20. // Directory for recordings
  21. Platform.recordingsDir;
  22.  
  23. (
  24. // Run once to convert and resample wavetable files. This may take a few seconds. Refer to the Post Window for confirmation of completion.
  25. // After "Conversion successfully completed", the active buffers and their corresponding symbols will be posted.
  26. var paths, file, data, n, newData, outFile, bufLenChecker, shortestBuf, dataList;
  27.  
  28. dataList = List.new;
  29. paths = (thisProcess.nowExecutingPath.dirname +/+ "/Samples/*.wav").pathMatch; // <---- search relative path for all .wav files, excluding other file types
  30.  
  31. // paths = "MYPATH/Samples/*.wav".pathMatch; // <-- if the relative path doesn't work, replace the MYPATH string in this line to hard code the search path
  32.  
  33.  
  34. //////////////////////////////////////
  35. //                                  //
  36. //      Reading and Resampling      //
  37. //                                  //
  38. //////////////////////////////////////
  39. Routine({
  40.  
  41. Routine({
  42.  
  43.     // Step 1: Check for the shortest provided sample.
  44.     paths.do { |it, i|
  45.             file = SoundFile.openRead(paths[i]);
  46.             data = Signal.newClear(file.numFrames);
  47.             dataList.add(data.size);
  48.             shortestBuf = dataList.minItem({|item, i| item});
  49.             // shortestBuf.postln; //<--- Troubleshooting
  50.         };
  51.  
  52.     // Step 2: Set wavetable frame size "n". By default set to 4096.
  53.     // Since VOsc requires the length of the wavetable to be a power of 2, "shortestBuf" is always converted to the next power of two greater than or equal to the receiver.
  54.     1.do {
  55.             n = 4096;
  56.             // n.postln; //<--- Troubleshooting
  57.             // if (shortestBuf < 4096) {n = shortestBuf.nextPowerOfTwo};
  58.             if (shortestBuf > 4096) {n = shortestBuf.nextPowerOfTwo};
  59.             if (shortestBuf > 8192) {n = 8192};
  60.             ("Wavetable Frame Size is " ++ n ++ ".").postln;
  61.         };
  62.  
  63.     // Step 3: Convert the samples to wavetables
  64.     paths.do { |it, i|
  65.  
  66.         // 'protect' guarantees the file objects will be closed in case of error
  67.         protect {
  68.  
  69.             // Read original size of data
  70.             file = SoundFile.openRead(paths[i]);
  71.             data = Signal.newClear(file.numFrames);
  72.  
  73.             file.readData(data);
  74.             0.1.wait;
  75.  
  76.             // Here we use the new frame size "n" that we calculated in Step 2 to resample the .wav files to the desired equal length
  77.             newData = data.resamp1(n);
  78.             0.1.wait;
  79.             // Convert the resampled signal into a Wavetable.
  80.             // resamp1 outputs an Array, so we have to reconvert to Signal
  81.             newData = newData.as(Signal).asWavetable;
  82.             0.1.wait;
  83.  
  84.             // save to disk.
  85.             outFile = SoundFile(paths[i] ++ "_4096.wtable")
  86.             .headerFormat_("WAV")
  87.             .sampleFormat_("float")
  88.             .numChannels_(1)
  89.             .sampleRate_(44100);
  90.             if(outFile.openWrite.notNil) {
  91.                 outFile.writeData(newData);
  92.                 0.1.wait;
  93.             } {
  94.                 "Couldn't write output file".warn;
  95.             };
  96.         } {
  97.             file.close;
  98.             if(outFile.notNil) { outFile.close };
  99.         };
  100.  
  101.     };
  102.  
  103.     "Conversion successfully completed.".postln;
  104.         // 0.1.wait;
  105. }).play;
  106.  
  107. // Wait for the previous routine to finish
  108.  
  109. (paths.size * 0.41 + 0.1).wait;
  110. "...".postln;
  111. 0.1.wait;
  112.  
  113. //////////////////////////////////////////////////////
  114. //                                                  //
  115. //      Loading the Wavetables to Buffer Memory     //
  116. //                                                  //
  117. //////////////////////////////////////////////////////
  118.  
  119. Routine({
  120.     var wtsize, wtpaths, wtbuffers;
  121.  
  122.     "-----------wavetables begin-----------".postln;
  123.  
  124.  
  125.     wtsize = n;
  126.  
  127.     // Read back all the wavetables we created above
  128.     wtpaths = (thisProcess.nowExecutingPath.dirname +/+ "/Samples/*.wtable").pathMatch;
  129.  
  130.     // Allocate double the wavetable frame size to the buffer to be safe
  131.     wtbuffers = Buffer.allocConsecutive(wtpaths.size, s, wtsize * 2, 1, );
  132.  
  133.     // Here we add each wavetable to the Buffers we created above.
  134.     // We assign each buffer a name as a Symbol for easy access later on. This name is equivalent to the file name of the sample.
  135.     // The buffer number and name are added to a global variable called "~bufferReference" for easy reference. This is however not needed for the synth in this file.
  136.  
  137.     wtpaths.do { |it, i|
  138.         wtbuffers[i].read(wtpaths[i])};
  139.         ~wtbufnums = List[];
  140.         ~wavetables = ();
  141.         ~bufferReference = List.new;
  142.  
  143.         wtpaths.do { |it i|
  144.             var name, buffer;
  145.             name = wtbuffers[i].path.basename.findRegexp(".*\.wav")[0][1].splitext[0];
  146.             buffer = wtbuffers[i].bufnum;
  147.             ~wavetables[name.asSymbol] = buffer;
  148.             ~wtbufnums.add(buffer);
  149.             buffer.postln;
  150.             name.postln;
  151.             ~bufferReference.add((buffer + "=" + name).asString);
  152.         };
  153.         // ~bufferReference.postln;
  154.  
  155.     "-----------wavetables end-----------".postln;
  156. };).play;
  157. };).play;
  158. )
  159.  
  160. // For reference
  161. ~wtbufnums; //<------------ Returns an array of the loaded buffer channels
  162. ~bufferReference; //<------ Returns an array of the loaded buffers and their respective names, i.e. Symbols
  163.  
  164.  
  165. //////////////////////////////////////////////////////
  166. //                                                  //
  167. //              Deckard's Synthdef                  //
  168. //                                                  //
  169. //////////////////////////////////////////////////////
  170. (
  171. var voices;
  172. // Specify the number of chorusing oscillators
  173. voices = 8;
  174. //Specify the number of channels
  175. ~numChans = 2;
  176.  
  177. SynthDef.new(\vosc1, {|out=0, buf=0, numBufs=2, freq=200, amp=0.2, bufRate=0.01, bitRate = 44100.0, bitDepth = 24.0,atk=12,sus=6,rel=20, timeScale=1.0, detuneAmt=0.2,shaperWet=0.0, decimWet = 1.0, hpf=10,lpf=20000|
  178.     var sig, bufpos, detuneSig, env, envG, shaperDry, decimDry;
  179.     shaperWet = shaperWet.fold2(0.8).squared.sqrt;
  180.     shaperDry = 1-shaperWet;
  181.     decimDry = 1-decimWet;
  182.     env = Env([0,0.5,1,1,0.5,0],[atk/2,atk/2,sus,rel/2,rel/2], curve: [5,-5,0,4,-3]);
  183.     env.asArray.size.postln;
  184.     env = EnvGen.kr(env,timeScale:timeScale, doneAction:2);
  185.     detuneSig = LFNoise1.kr(0.2!voices).bipolar(detuneAmt).midiratio;
  186.     bufpos = buf + LFNoise1.kr(bufRate).range(0, numBufs-1);
  187.     sig = VOsc.ar(bufpos, freq*detuneSig);
  188.     sig = (Decimator.ar(sig, Lag.kr(bitRate,5.0), Lag.kr(bitDepth,5.0))*decimWet) + (sig*decimDry);
  189.     sig = (Shaper.ar(~wtbufnums[rrand(~wtbufnums.size-1,~wtbufnums[0])],sig)*shaperWet) + (sig*shaperDry);
  190.     sig = HPF.ar(sig, Lag2.kr(hpf,8.0));
  191.     sig = LPF.ar(sig, Lag2.kr(lpf,8.0));
  192.     sig = SplayAz.ar(~numChans, sig);
  193.     sig = LeakDC.ar(sig) * env * amp;
  194.     Out.ar(out, sig);
  195. }).add
  196. )
  197.  
  198. //////////////////////////////////////////////////////
  199. //                                                  //
  200. //                      Sequencer                   //
  201. //                                                  //
  202. //////////////////////////////////////////////////////
  203.  
  204. (
  205. var sequencer, dictRoutine;
  206. ~voices = [1,1,1,1];
  207. ~degrees = [0,7,9,10];
  208. ~atk = 12;
  209. ~sus = 6;
  210. ~rel = 20;
  211. ~timeScale=1.0;
  212.  
  213. ~dDict = Dictionary.newFrom([   \buf, ~wtbufnums[0],
  214.                                 \numBufs, ~wtbufnums.size-1,
  215.                                 \bufRate, 0.02,
  216.                                 \degree1, 0,
  217.                                 \degree2, 7,
  218.                                 \degree3, 9,
  219.                                 \degree4, 10,
  220.                                 \freq, rrand(24,72).nearestInScale(~degrees, 12).postln.midicps,
  221.                                 \amp, 0.2,
  222.                                 \atk, 12,
  223.                                 \sus, 6,
  224.                                 \rel, 20,
  225.                                 \timeScale, 1.0,
  226.                                 \detuneAmt, 0.17,
  227.                                 \decimWet, 1.0,
  228.                                 \bitRate, 44100,
  229.                                 \bitDepth, 24,
  230.                                 \shaperWet, 0.0,
  231.                                 \hpf, 10,
  232.                                 \lpf, 20000]);
  233.  
  234. ~dDictReset = Routine({1.do{
  235.                                 ~dDict[\buf] = ~wtbufnums[0];
  236.                                 ~dDict[\numBufs] = ~wtbufnums.size-1;
  237.                                 ~dDict[\bufRate] = 0.02;
  238.                                 ~dDict[\amp] = 0.2;
  239.                                 ~dDict[\atk] = 12;
  240.                                 ~dDict[\sus] = 6;
  241.                                 ~dDict[\rel] = 20;
  242.                                 ~dDict[\timeScale] = 1.0;
  243.                                 ~dDict[\detuneAmt] = 0.17;
  244.                                 ~dDict[\decimWet] = 1.0;
  245.                                 ~dDict[\bitRate] = 44100;
  246.                                 ~dDict[\bitDepth] = 24;
  247.                                 ~dDict[\shaperWet] = 0.0;
  248.                                 ~dDict[\hpf] = 20;
  249.                                 ~dDict[\lpf] = 20000;
  250. }});
  251.  
  252.  
  253. ~sequencer = Routine({
  254.  
  255.     inf.do{
  256.  
  257.         ///// VOICE 1 /////
  258.         1.do{
  259.             if (~voices[0] == 1) {
  260.             |it, i|
  261.             ~v1 = Synth (\vosc1,
  262.             [   \buf, ~dDict[\buf],
  263.                 \numBufs, ~dDict[\numBufs],
  264.                 \bufRate, ~dDict[\bufRate],
  265.                 \freq, rrand(24,72).nearestInScale(~degrees, 12).postln.midicps,
  266.                 \amp, ~dDict[\amp],
  267.                 \atk, ~dDict[\atk],
  268.                 \sus, ~dDict[\sus],
  269.                 \rel, ~dDict[\rel],
  270.                 \timeScale, ~dDict[\timeScale],
  271.                 \detuneAmt, ~dDict[\detuneAmt],
  272.                 \decimWet, ~dDict[\decimWet],
  273.                 \bitRate, ~dDict[\bitRate],
  274.                 \bitDepth, ~dDict[\bitDepth],
  275.                 \shaperWet, ~dDict[\shaperWet],
  276.                 \hpf, ~dDict[\hpf],
  277.                 \lpf, ~dDict[\lpf]]
  278.         );}};
  279.  
  280.         ///// VOICE 2 /////
  281.         1.do{
  282.             if (~voices[1] == 1) {
  283.             |it, i|
  284.             ~v2 = Synth (\vosc1,
  285.             [   \buf, ~dDict[\buf],
  286.                 \numBufs, ~dDict[\numBufs],
  287.                 \bufRate, ~dDict[\bufRate],
  288.                 \freq, rrand(24,72).nearestInScale(~degrees, 12).postln.midicps,
  289.                 \amp, ~dDict[\amp],
  290.                 \atk, ~dDict[\atk],
  291.                 \sus, ~dDict[\sus],
  292.                 \rel, ~dDict[\rel],
  293.                 \timeScale, ~dDict[\timeScale],
  294.                 \detuneAmt, ~dDict[\detuneAmt],
  295.                 \decimWet, ~dDict[\decimWet],
  296.                 \bitRate, ~dDict[\bitRate],
  297.                 \bitDepth, ~dDict[\bitDepth],
  298.                 \shaperWet, ~dDict[\shaperWet],
  299.                 \hpf, ~dDict[\hpf],
  300.                 \lpf, ~dDict[\lpf]]
  301.         );}};
  302.  
  303.         ///// VOICE 3 /////
  304.         1.do{
  305.             if (~voices[2] == 1) {
  306.             |it, i|
  307.             ~v3 = Synth (\vosc1,
  308.             [   \buf, ~dDict[\buf],
  309.                 \numBufs, ~dDict[\numBufs],
  310.                 \bufRate, ~dDict[\bufRate],
  311.                 \freq, rrand(24,72).nearestInScale(~degrees, 12).postln.midicps,
  312.                 \amp, ~dDict[\amp],
  313.                 \atk, ~dDict[\atk],
  314.                 \sus, ~dDict[\sus],
  315.                 \rel, ~dDict[\rel],
  316.                 \timeScale, ~dDict[\timeScale],
  317.                 \detuneAmt, ~dDict[\detuneAmt],
  318.                 \decimWet, ~dDict[\decimWet],
  319.                 \bitRate, ~dDict[\bitRate],
  320.                 \bitDepth, ~dDict[\bitDepth],
  321.                 \shaperWet, ~dDict[\shaperWet],
  322.                 \hpf, ~dDict[\hpf],
  323.                 \lpf, ~dDict[\lpf]]
  324.         );}};
  325.  
  326.         ///// VOICE 4 /////
  327.         1.do{
  328.             if (~voices[3] == 1) {
  329.             |it, i|
  330.             ~v4 = Synth (\vosc1,
  331.             [   \buf, ~dDict[\buf],
  332.                 \numBufs, ~dDict[\numBufs],
  333.                 \bufRate, ~dDict[\bufRate],
  334.                 \freq, rrand(24,72).nearestInScale(~degrees, 12).postln.midicps,
  335.                 \amp, ~dDict[\amp],
  336.                 \atk, ~dDict[\atk],
  337.                 \sus, ~dDict[\sus],
  338.                 \rel, ~dDict[\rel],
  339.                 \timeScale, ~dDict[\timeScale],
  340.                 \detuneAmt, ~dDict[\detuneAmt],
  341.                 \decimWet, ~dDict[\decimWet],
  342.                 \bitRate, ~dDict[\bitRate],
  343.                 \bitDepth, ~dDict[\bitDepth],
  344.                 \shaperWet, ~dDict[\shaperWet],
  345.                 \hpf, ~dDict[\hpf],
  346.                 \lpf, ~dDict[\lpf]]
  347.         );}};
  348.  
  349.  
  350. //4.wait; //<------ For troubleshooting purposes, ignore
  351. ((~dDict[\atk]+~dDict[\sus]+(~dDict[\rel]/7))*~dDict[\timeScale]).wait;
  352. }});
  353.  
  354.  
  355.  
  356. )
  357.  
  358. // The following controls for the "~sequencer" Routine are included in the GUI and are only included as text for troubleshooting purposes
  359. ~sequencer.reset;
  360. ~sequencer.play;
  361. ~sequencer.stop;
  362.  
  363.  
  364. //////////////////////////////////////////////////////
  365. //                                                  //
  366. //                      GUI                         //
  367. //                                                  //
  368. //////////////////////////////////////////////////////
  369.  
  370. (
  371. Routine({
  372. var displayWindow = {
  373. var synth, ampSpec, intervalSpec, window, winX=550, winY=450;
  374. var knobAtk, knobSus, knobRel, knobTimeScale, knobDetune, knobDecim, knobBitRate, knobBitDepth, knobShaper, knobBufRate, knobHPF, knobLPF;
  375. var column2, column3, column4, row1, row2,row3,row4,row5, row6, row7,row8,row9,row10,row11,row12;
  376. var vs1,vs2,vs3; //vs -> vertical spacing
  377.  
  378. ~voices = [1,1,1,1];
  379. ~degrees = [0,7,9,10];
  380.  
  381. // Resets the dictionary to its default values
  382. ~dDictReset.reset;
  383. ~dDictReset.play;
  384. 0.05.wait;
  385.  
  386. vs1 = 28;
  387. vs2 = 20;
  388. vs3 = 45;
  389. row1 = 30;
  390. row2 = (row1+vs2);
  391. row3 = (row2+vs3);
  392. row4 = (row3+vs1);
  393. row5 = (row4+vs2);
  394. row6 = (row5+vs3);
  395. row7 = (row6+vs1);
  396. row8 = (row7+vs2);
  397. row9 = (row8+vs3);
  398. row10 = (row9+vs1);
  399. row11 = (row10+vs2);
  400. row12 = (row11+vs3);
  401. column2 = 320;
  402. column3 = column2+60;
  403. column4 = column3+60;
  404.  
  405. window = Window("Do Androids Dream of Electric Sheep?", Rect(100,200,winX,winY));
  406. window.background = Color.fromHexString("#222A2D"); //#A96E6E
  407. intervalSpec = ControlSpec(0, 12,'lin',1);
  408.  
  409. // CONTROLS FOR THE 4 VOICES -> interval, on/off
  410. 4.do {|i|
  411.     var slider, text, offset, number, onOff;
  412.  
  413.     i = i + 1;
  414.     offset = 60 * i;
  415.     number = NumberBox(window, Rect(offset,255,50,20));
  416.     number.value = ~degrees[i-1];
  417.     slider = Slider(window, Rect(offset,row2,50,200));
  418.     slider.knobColor = Color.fromHexString("#B0BDE0");
  419.     slider.value = intervalSpec.unmap(~degrees[i-1]);
  420.     slider.action = {|v|
  421.         var val=intervalSpec.map(v.value);
  422.         ~degrees[i-1] = val.asInteger;
  423.         number.value=val };
  424.  
  425.     text = StaticText(window,Rect(offset,30,50,20));
  426.     text.string = "Interval" ++ i;
  427.     text.stringColor = Color.white;
  428.     text.align = \center;
  429.  
  430.     onOff = Button(window, Rect(offset, 280,50,21))
  431.         .states_([["", Color.fromHexString("#B0BDE0"), Color.fromHexString("#B0BDE0")], ["", Color.white, Color.white]])
  432.                 .action_({|view| if (view.value == 0)
  433.                                     {~voices[i-1]=1}
  434.                                     {~voices[i-1]=0}
  435.             });
  436. };
  437.  
  438. // ATTACK
  439. 1.do{|i|
  440.     var knob, text, number,spec;
  441.  
  442.         spec = ControlSpec(0.1,30,'lin');
  443.         text = StaticText(window,Rect(column2,row1,40,20));
  444.         text.string = "Atk";
  445.         text.stringColor = Color.white;
  446.         text.align = \center;
  447.         number = NumberBox(window, Rect(column2,row3,41,20));
  448.         knobAtk =Knob.new(window, Rect(column2,row2,40,40));
  449.         knobAtk.value = spec.unmap(~dDict[\atk]);
  450.         number.value= spec.map(knobAtk.value);
  451.         knobAtk.action = {|v|
  452.             var val = ~dDict[\atk];
  453.             val = spec.map(v.value);
  454.             ~dDict[\atk] = val;
  455.             ~v1.set(\atk,val);
  456.             ~v2.set(\atk,val);
  457.             ~v3.set(\atk,val);
  458.             ~v4.set(\atk,val);
  459.             number.value=val;
  460.     }};
  461.  
  462. // SUSTAIN
  463. 1.do{|i|
  464.     var knob, text, number,spec;
  465.  
  466.         spec = ControlSpec(0.1,30,'lin');
  467.         text = StaticText(window,Rect(column2,row4,40,20));
  468.         text.string = "Sus";
  469.         text.stringColor = Color.white;
  470.         text.align = \center;
  471.         number = NumberBox(window, Rect(column2,row6,41,20));
  472.         knobSus =Knob.new(window, Rect(column2,row5,40,40));
  473.         knobSus.value = spec.unmap(~dDict[\sus]);
  474.         number.value= spec.map(knobSus.value);
  475.         knobSus.action = {|v|
  476.             var val = ~dDict[\sus];
  477.             val = spec.map(v.value);
  478.             ~dDict[\sus] = val;
  479.             ~v1.set(\sus,val);
  480.             ~v2.set(\sus,val);
  481.             ~v3.set(\sus,val);
  482.             ~v4.set(\sus,val);
  483.             number.value=val;
  484.     }};
  485.  
  486. // RELEASE
  487. 1.do{|i|
  488.     var knob, text, number,spec;
  489.  
  490.         spec = ControlSpec(0.1,30,'lin');
  491.         text = StaticText(window,Rect(column2,row7,40,20));
  492.         text.string = "Rel";
  493.         text.stringColor = Color.white;
  494.         text.align = \center;
  495.         number = NumberBox(window, Rect(column2,row9,41,20));
  496.         knobRel =Knob.new(window, Rect(column2,row8,40,40));
  497.         knobRel.value = spec.unmap(~dDict[\rel]);
  498.         number.value= spec.map(knobRel.value);
  499.         knobRel.action = {|v|
  500.             var val = ~dDict[\rel];
  501.             val = spec.map(v.value);
  502.             ~dDict[\rel] = val;
  503.             ~v1.set(\rel,val);
  504.             ~v2.set(\rel,val);
  505.             ~v3.set(\rel,val);
  506.             ~v4.set(\rel,val);
  507.             number.value=val;
  508.     }};
  509.  
  510. // TIMESCALE
  511. 1.do{|i|
  512.     var knob, text, number,spec;
  513.  
  514.         spec = ControlSpec(0.1,30,'exponential');
  515.         text = StaticText(window,Rect(column2,row10,40,20));
  516.         text.string = "tScale";
  517.         text.stringColor = Color.white;
  518.         text.align = \center;
  519.         number = NumberBox(window, Rect(column2,row12,41,20));
  520.         knobTimeScale =Knob.new(window, Rect(column2,row11,40,40));
  521.         knobTimeScale.value = spec.unmap(~dDict[\timeScale]);
  522.         number.value= spec.map(knobTimeScale.value);
  523.         knobTimeScale.action = {|v|
  524.             var val = ~dDict[\timeScale];
  525.             val = spec.map(v.value);
  526.             ~dDict[\timeScale] = val;
  527.             ~v1.set(\timeScale,val);
  528.             ~v2.set(\timeScale,val);
  529.             ~v3.set(\timeScale,val);
  530.             ~v4.set(\timeScale,val);
  531.             number.value=val;
  532.     }};
  533.  
  534. // DETUNE
  535. 1.do{|i|
  536.     var knob, text, number,spec;
  537.  
  538.         spec = ControlSpec(0.0,1,'lin');
  539.         text = StaticText(window,Rect(column3,row1,40,20));
  540.         text.string = "Detune";
  541.         text.stringColor = Color.white;
  542.         text.align = \center;
  543.         number = NumberBox(window, Rect(column3,row3,41,20));
  544.         knobDetune =Knob.new(window, Rect(column3,row2,40,40));
  545.         knobDetune.value = spec.unmap(~dDict[\detuneAmt]);
  546.         number.value= spec.map(knobDetune.value);
  547.         knobDetune.action = {|v|
  548.             var val = ~dDict[\detuneAmt];
  549.             val = spec.map(v.value);
  550.             ~dDict[\detuneAmt] = val;
  551.             ~v1.set(\detuneAmt,val);
  552.             ~v2.set(\detuneAmt,val);
  553.             ~v3.set(\detuneAmt,val);
  554.             ~v4.set(\detuneAmt,val);
  555.             number.value=val;
  556.     }};
  557.  
  558. // DECIMATE
  559. 1.do{|i|
  560.     var knob, text, number,spec;
  561.  
  562.         spec = ControlSpec(0.0,1,'lin');
  563.         text = StaticText(window,Rect(column3,row4,40,20));
  564.         text.string = "dcmWet";
  565.         text.stringColor = Color.white;
  566.         text.align = \center;
  567.         number = NumberBox(window, Rect(column3,row6,41,20));
  568.         knobDecim =Knob.new(window, Rect(column3,row5,40,40));
  569.         knobDecim.value = spec.unmap(~dDict[\decimWet]);
  570.         number.value= spec.map(knobDecim.value);
  571.         knobDecim.action = {|v|
  572.             var val = ~dDict[\decimWet];
  573.             val = spec.map(v.value);
  574.             ~dDict[\decimWet] = val;
  575.             ~v1.set(\decimWet,val);
  576.             ~v2.set(\decimWet,val);
  577.             ~v3.set(\decimWet,val);
  578.             ~v4.set(\decimWet,val);
  579.             number.value=val;
  580.     }};
  581.  
  582. // BITRATE
  583. 1.do{|i|
  584.     var knob, text, number,spec;
  585.  
  586.         spec = ControlSpec(0.0,44100,'lin');
  587.         text = StaticText(window,Rect(column3,row7,40,20));
  588.         text.string = "Bitrate";
  589.         text.stringColor = Color.white;
  590.         text.align = \center;
  591.         number = NumberBox(window, Rect(column3,row9,41,20));
  592.         knobBitRate =Knob.new(window, Rect(column3,row8,40,40));
  593.         knobBitRate.value = spec.unmap(~dDict[\bitRate]);
  594.         number.value= spec.map(knobBitRate.value);
  595.         knobBitRate.action = {|v|
  596.             var val = ~dDict[\bitRate];
  597.             val = spec.map(v.value);
  598.             ~dDict[\bitRate] = val;
  599.             ~v1.set(\bitRate,val);
  600.             ~v2.set(\bitRate,val);
  601.             ~v3.set(\bitRate,val);
  602.             ~v4.set(\bitRate,val);
  603.             number.value=val;
  604.     }};
  605.  
  606. // BITDEPTH
  607. 1.do{|i|
  608.     var knob, text, number,spec;
  609.  
  610.         spec = ControlSpec(0.0,24,'lin');
  611.         text = StaticText(window,Rect(column3,row10,40,20));
  612.         text.string = "Bitdepth";
  613.         text.stringColor = Color.white;
  614.         text.align = \center;
  615.         number = NumberBox(window, Rect(column3,row12,41,20));
  616.         knobBitDepth =Knob.new(window, Rect(column3,row11,40,40));
  617.         knobBitDepth.value = spec.unmap(~dDict[\bitDepth]);
  618.         number.value= spec.map(knobBitDepth.value);
  619.         knobBitDepth.action = {|v|
  620.             var val = ~dDict[\bitDepth];
  621.             val = spec.map(v.value);
  622.             ~dDict[\bitDepth] = val;
  623.             ~v1.set(\bitDepth,val);
  624.             ~v2.set(\bitDepth,val);
  625.             ~v3.set(\bitDepth,val);
  626.             ~v4.set(\bitDepth,val);
  627.             number.value=val;
  628.     }};
  629.  
  630.  
  631. // SHAPER
  632. 1.do{|i|
  633.     var knob, text, number,spec;
  634.  
  635.         spec = ControlSpec(0.0,1,'lin');
  636.         text = StaticText(window,Rect(column4,row1,40,20));
  637.         text.string = "Shaper";
  638.         text.stringColor = Color.white;
  639.         text.align = \center;
  640.         number = NumberBox(window, Rect(column4,row3,41,20));
  641.         knobShaper =Knob.new(window, Rect(column4,row2,40,40));
  642.         knobShaper.value = spec.unmap(~dDict[\shaperWet]);
  643.         number.value= spec.map(knobShaper.value);
  644.         knobShaper.action = {|v|
  645.             var val = ~dDict[\shaperWet];
  646.             val = spec.map(v.value);
  647.             ~dDict[\shaperWet] = val;
  648.             ~v1.set(\shaperWet,val);
  649.             ~v2.set(\shaperWet,val);
  650.             ~v3.set(\shaperWet,val);
  651.             ~v4.set(\shaperWet,val);
  652.             number.value=val;
  653.     }};
  654.  
  655. // BUFRATE
  656. 1.do{|i|
  657.     var knob, text, number,spec;
  658.  
  659.         spec = ControlSpec(0.0,1,'lin');
  660.         text = StaticText(window,Rect(column4,row4,40,20));
  661.         text.string = "Bufrate";
  662.         text.stringColor = Color.white;
  663.         text.align = \center;
  664.         number = NumberBox(window, Rect(column4,row6,41,20));
  665.         knobBufRate =Knob.new(window, Rect(column4,row5,40,40));
  666.         knobBufRate.value = spec.unmap(~dDict[\bufRate]);
  667.         number.value= spec.map(knobBufRate.value);
  668.         knobBufRate.action = {|v|
  669.             var val = ~dDict[\bufRate];
  670.             val = spec.map(v.value).postln;
  671.             ~dDict[\bufRate] = val;
  672.             ~v1.set(\bufRate,val);
  673.             ~v2.set(\bufRate,val);
  674.             ~v3.set(\bufRate,val);
  675.             ~v4.set(\bufRate,val);
  676.             number.value=val;
  677.     }};
  678.  
  679. // HIGH-PASS FILTER
  680. 1.do{|i|
  681.     var knob, text, number,spec;
  682.  
  683.         spec = ControlSpec(10,20000,'exponential');
  684.         text = StaticText(window,Rect(column4,row7,40,20));
  685.         text.string = "HPF";
  686.         text.stringColor = Color.white;
  687.         text.align = \center;
  688.         number = NumberBox(window, Rect(column4,row9,41,20));
  689.         knobHPF =Knob.new(window, Rect(column4,row8,40,40));
  690.         knobHPF.value = spec.unmap(~dDict[\hpf]);
  691.         number.value= spec.map(knobHPF.value);
  692.         knobHPF.action = {|v|
  693.             var val = ~dDict[\hpf];
  694.             val = spec.map(v.value).postln;
  695.             ~dDict[\hpf] = val;
  696.             ~v1.set(\hpf,val);
  697.             ~v2.set(\hpf,val);
  698.             ~v3.set(\hpf,val);
  699.             ~v4.set(\hpf,val);
  700.             number.value=val;
  701.     }};
  702.  
  703. // LOW-PASS FILTER
  704. 1.do{|i|
  705.     var knob, text, number,spec;
  706.  
  707.         spec = ControlSpec(10,20000,'exponential');
  708.         text = StaticText(window,Rect(column4,row10,40,20));
  709.         text.string = "LPF";
  710.         text.stringColor = Color.white;
  711.         text.align = \center;
  712.         number = NumberBox(window, Rect(column4,row12,41,20));
  713.         knobLPF =Knob.new(window, Rect(column4,row11,40,40));
  714.         knobLPF.value = spec.unmap(~dDict[\lpf]);
  715.         number.value= spec.map(knobLPF.value);
  716.         knobLPF.action = {|v|
  717.             var val = ~dDict[\lpf];
  718.             val = spec.map(v.value).postln;
  719.             ~dDict[\lpf] = val;
  720.             ~v1.set(\lpf,val);
  721.             ~v2.set(\lpf,val);
  722.             ~v3.set(\lpf,val);
  723.             ~v4.set(\lpf,val);
  724.             number.value=val;
  725.     }};
  726.  
  727. // BUTTON TO START/STOP SEQUENCER
  728.     Button(window, Rect(60,(row10+6),110,83))
  729.     .states_([["START", Color.black, Color.white], ["STOP", Color.white, Color.fromHexString("#8DB38B")]]) //#70AE6E
  730.     .action_({|view|  view.value.postln;
  731.         if (view.value == 1)
  732.                         {~sequencer.reset;~sequencer.play}
  733.                         {~sequencer.stop}
  734.         });
  735.  
  736. // BUTTON TO START/STOP RECORDING
  737.     Button(window, Rect(180,(row10+6),110,83))
  738.     .states_([["REC", Color.black, Color.white], ["STOP REC", Color.white, Color.fromHexString("#D72638")]])
  739.     .action_({|view|  view.value.postln;
  740.         if (view.value == 1)
  741.                         {s.record(numChannels: ~numChans)}
  742.                         {s.stopRecording}
  743.         });
  744.  
  745.  
  746.  
  747. //Notes
  748. 1.do{var text1, text2;
  749.         text1 = StaticText.new(window, Rect(60,row10+92,200,20));
  750.         text1.string = "KippleGEN or, The Empathy Box (2024)";
  751.         text1.stringColor = Color.new(1,1,1,0.4);
  752.         text1.align = \left;
  753.         text2 = StaticText.new(window, Rect(60,row10+107,200,20));
  754.         text2.string = "Daniel L. Lythgoe";
  755.         text2.stringColor = Color.new(1,1,1,0.4);
  756.         text2.align = \left;
  757. };
  758.  
  759.  
  760. window.front;
  761. window.alwaysOnTop = true;
  762.  
  763. };
  764. displayWindow.value();
  765. }).play(AppClock))
Advertisement
Add Comment
Please, Sign In to add comment