6b_effect_presets.scd 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. // Module 6: Test Functions & Effect Chain Setup - FIXED FOR MEMORY MANAGEMENT
  2. // Save as "6_test_functions.scd"
  3. (
  4. // Function to start effects chain
  5. ~startEffectsChain = {
  6. // Stop existing effects first
  7. ~stopEffectsChain.value;
  8. // Create audio buses for effects chain
  9. ~sourceBus = Bus.audio(s, 2);
  10. ~reverbBus = Bus.audio(s, 2);
  11. ~delayBus = Bus.audio(s, 2);
  12. ~filterBus = Bus.audio(s, 2);
  13. // Create control buses for modulation
  14. ~lfoControlBus = Bus.control(s, 1);
  15. // Create effects synths in chain with error handling
  16. try {
  17. ~filterSynth = Synth(\lpf, [
  18. \in, ~sourceBus,
  19. \out, ~delayBus,
  20. \cutoff, 1000,
  21. \res, 0.5
  22. ]);
  23. ~delaySynth = Synth(\delay, [
  24. \in, ~delayBus,
  25. \out, ~reverbBus,
  26. \delaytime, 0.4,
  27. \feedback, 0.3,
  28. \mix, 0.3
  29. ], ~filterSynth, \addAfter);
  30. ~reverbSynth = Synth(\reverb, [
  31. \in, ~reverbBus,
  32. \out, 0,
  33. \mix, 0.2,
  34. \room, 0.5,
  35. \damp, 0.5
  36. ], ~delaySynth, \addAfter);
  37. // Create LFO separately
  38. ~lfoSynth = Synth(\lfoEffect, [
  39. \out, ~lfoControlBus,
  40. \freq, 1,
  41. \min, 100,
  42. \max, 5000,
  43. \waveform, 0
  44. ]);
  45. // Wait for server sync then map LFO
  46. s.sync;
  47. ~filterSynth.map(\cutoff, ~lfoControlBus);
  48. // Store the effects chain nodes in an array for easy access
  49. ~effectsChain = [~filterSynth, ~delaySynth, ~reverbSynth, ~lfoSynth];
  50. "Effects chain started successfully".postln;
  51. } { |error|
  52. "Error starting effects chain: %".format(error).postln;
  53. ~stopEffectsChain.value;
  54. };
  55. };
  56. // Function to stop effects chain
  57. ~stopEffectsChain = {
  58. if(~effectsChain.notNil, {
  59. ~effectsChain.do({ |synth|
  60. if(synth.notNil and: { synth.isPlaying }, {
  61. synth.free;
  62. });
  63. });
  64. ~effectsChain = nil;
  65. });
  66. // Free individual synth references
  67. [~filterSynth, ~delaySynth, ~reverbSynth, ~lfoSynth].do({ |synth|
  68. if(synth.notNil and: { synth.isPlaying }, {
  69. synth.free;
  70. });
  71. });
  72. ~filterSynth = nil;
  73. ~delaySynth = nil;
  74. ~reverbSynth = nil;
  75. ~lfoSynth = nil;
  76. // Free buses
  77. [~sourceBus, ~reverbBus, ~delayBus, ~filterBus, ~lfoControlBus].do({ |bus|
  78. if(bus.notNil, {
  79. bus.free;
  80. });
  81. });
  82. ~sourceBus = nil;
  83. ~reverbBus = nil;
  84. ~delayBus = nil;
  85. ~filterBus = nil;
  86. ~lfoControlBus = nil;
  87. "Effects chain stopped and cleaned up".postln;
  88. };
  89. // Function to reset the entire system
  90. ~resetSystem = {
  91. // Stop all effects
  92. ~stopEffectsChain.value;
  93. // Clear OSC system if it exists
  94. if(~cleanupOSCSystem.notNil, { ~cleanupOSCSystem.value; });
  95. // Clear MIDI system if it exists
  96. if(~cleanupAllMIDISynths.notNil, { ~cleanupAllMIDISynths.value; });
  97. // Clear all OSC definitions
  98. OSCdef.freeAll;
  99. // Reset touch synths tracking
  100. ~touchSynths = ();
  101. "System reset complete".postln;
  102. // Restart effects chain
  103. ~startEffectsChain.value;
  104. };
  105. // Test function for parameter changes - FIXED to not use problematic timing
  106. ~testParameters = {
  107. // Start effects chain if not already running
  108. if(~effectsChain.isNil, { ~startEffectsChain.value; });
  109. // Test different oscillator types with varying parameters
  110. var testParams = [
  111. [\rgbSynth, 440, 0.2, -0.5, 0.05, 0.5],
  112. [\rgbSynth, 330, 0.15, 0, 0.01, 0.8],
  113. [\rgbSynth, 220, 0.1, 0.5, 0.1, 1.2],
  114. [\rgbSynth, 550, 0.18, -0.2, 0.02, 0.7],
  115. [\rgbSynth, 660, 0.15, 0.3, 0.05, 1.0]
  116. ];
  117. testParams.do { |params, i|
  118. var synthType, freq, amp, pan, attack, release;
  119. #synthType, freq, amp, pan, attack, release = params;
  120. // Create the synth with the specified parameters
  121. Synth(synthType, [
  122. \out, ~sourceBus ? 0,
  123. \freq, freq,
  124. \amp, amp,
  125. \pan, pan,
  126. \ampAttack, attack,
  127. \ampRelease, release,
  128. \redAmt, ~synthParams.redAmt ? 0.5,
  129. \greenAmt, ~synthParams.greenAmt ? 0.5,
  130. \blueAmt, ~synthParams.blueAmt ? 0.5
  131. ]);
  132. // Change effect parameters for demonstration
  133. if(~filterSynth.notNil and: { ~filterSynth.isPlaying }, {
  134. ~filterSynth.set(\cutoff, 500 + (i * 1000));
  135. });
  136. if(~delaySynth.notNil and: { ~delaySynth.isPlaying }, {
  137. ~delaySynth.set(\mix, 0.2 + (i * 0.1));
  138. });
  139. if(~reverbSynth.notNil and: { ~reverbSynth.isPlaying }, {
  140. ~reverbSynth.set(\room, 0.3 + (i * 0.1));
  141. });
  142. // Log the current sound
  143. ["Testing synth:", synthType, freq, amp].postln;
  144. };
  145. "Parameter test complete".postln;
  146. };
  147. // Test function that creates sounds with scheduled timing (safer approach)
  148. ~testSequence = {
  149. var sounds = [
  150. [440, 0.2, 0.1, 1.0],
  151. [330, 0.15, 0.2, 0.8],
  152. [550, 0.18, 0.3, 0.7],
  153. [660, 0.12, 0.4, 0.9],
  154. [220, 0.25, 0.5, 1.2]
  155. ];
  156. // Start effects chain if needed
  157. if(~effectsChain.isNil, { ~startEffectsChain.value; });
  158. sounds.do { |params, i|
  159. var freq, amp, delay, release;
  160. #freq, amp, delay, release = params;
  161. // Schedule each sound with SystemClock (safer than Routine)
  162. SystemClock.sched(delay * i, {
  163. Synth(\rgbSynth, [
  164. \out, ~sourceBus ? 0,
  165. \freq, freq,
  166. \amp, amp,
  167. \ampRelease, release,
  168. \redAmt, ~synthParams.redAmt ? 0.5,
  169. \greenAmt, ~synthParams.greenAmt ? 0.5,
  170. \blueAmt, ~synthParams.blueAmt ? 0.5
  171. ]);
  172. ["Scheduled sound:", freq, amp].postln;
  173. nil; // Don't reschedule
  174. });
  175. };
  176. "Test sequence scheduled".postln;
  177. };
  178. // Function to simulate touch input safely
  179. ~simulateTouch = { |count=5|
  180. var touchCount = 0;
  181. "Simulating % touch events".format(count).postln;
  182. // Start the effects chain if needed
  183. if(~effectsChain.isNil, { ~startEffectsChain.value; });
  184. // Schedule touch events
  185. count.do { |i|
  186. SystemClock.sched(i * 0.5, {
  187. var x = (-0.5 + 1.0.rand);
  188. var y = (-0.5 + 1.0.rand);
  189. var pressure = 1 + 7.rand;
  190. // Update pad values
  191. ~currentPadValues.x = x;
  192. ~currentPadValues.y = y;
  193. ~currentPadValues.pressure = pressure;
  194. // Trigger the change effect params function
  195. if(~changeEffectParams.notNil, {
  196. ~changeEffectParams.value;
  197. });
  198. // Trigger sound if using appropriate pen type
  199. if(~triggerSound.notNil, {
  200. ~triggerSound.value;
  201. });
  202. touchCount = touchCount + 1;
  203. ["Simulated touch #%: x=%, y=%, pressure=%".format(touchCount, x.round(0.01), y.round(0.01), pressure.round(0.01))].postln;
  204. nil; // Don't reschedule
  205. });
  206. };
  207. // Schedule completion message
  208. SystemClock.sched(count * 0.5 + 1, {
  209. "Touch simulation complete".postln;
  210. nil;
  211. });
  212. };
  213. // Memory monitoring function
  214. ~checkMemory = {
  215. var serverStatus = s.queryAllNodes;
  216. var activeSynths = s.numSynths;
  217. var activeGroups = s.numGroups;
  218. "=== Memory Status ===".postln;
  219. "Active synths: %".format(activeSynths).postln;
  220. "Active groups: %".format(activeGroups).postln;
  221. if(~midiSynths.notNil, {
  222. "Active MIDI synths: %".format(~midiSynths.size).postln;
  223. });
  224. if(~activeSynths.notNil, {
  225. "Active OSC synths: %".format(~activeSynths.size).postln;
  226. });
  227. // Warning if too many synths
  228. if(activeSynths > 50, {
  229. "WARNING: High number of active synths (%). Consider running cleanup.".format(activeSynths).postln;
  230. });
  231. "===================".postln;
  232. };
  233. // Emergency cleanup function
  234. ~emergencyCleanup = {
  235. "EMERGENCY CLEANUP - Stopping all sounds".postln;
  236. // Free all synths on server
  237. s.freeAll;
  238. // Clear all tracking dictionaries
  239. if(~midiSynths.notNil, { ~midiSynths.clear; });
  240. if(~activeSynths.notNil, { ~activeSynths.clear; });
  241. if(~touchSynths.notNil, { ~touchSynths.clear; });
  242. // Clear buses
  243. ~stopEffectsChain.value;
  244. // Reset counters
  245. ~synthCounter = 0;
  246. "Emergency cleanup complete".postln;
  247. // Wait a moment then restart effects
  248. SystemClock.sched(1, {
  249. ~startEffectsChain.value;
  250. nil;
  251. });
  252. };
  253. // Register emergency cleanup with Cmd+Period
  254. CmdPeriod.add({
  255. ~emergencyCleanup.value;
  256. });
  257. "Test functions loaded with memory management.".postln;
  258. "Available test functions:".postln;
  259. " ~testParameters.value - Test different synth parameters".postln;
  260. " ~testSequence.value - Test scheduled sound sequence".postln;
  261. " ~simulateTouch.value(10) - Simulate 10 touch events".postln;
  262. " ~checkMemory.value - Check current memory usage".postln;
  263. " ~emergencyCleanup.value - Emergency cleanup all sounds".postln;
  264. " ~resetSystem.value - Complete system reset".postln;
  265. )