Sampler in ChucK
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

175 lines
4.6KB

  1. // TODO: turn off adcThru when recording
  2. // TODO: Effects break panning for some unknown reason
  3. // TODO: currently I don't turn ADC thru back on after recording
  4. // Effects chain with limiters, reverb, filters
  5. NRev reverb => LPF lpf => HPF hpf => Dyno outputLimiter => dac;
  6. outputLimiter.limit();
  7. reverb @=> UGen @ outputWet; // Reference to wet output
  8. outputLimiter @=> UGen @ outputDry; // Reference to dry output
  9. outputLimiter @=> UGen @ mainOutput; // Reference to main output
  10. // Capture mic/line in and monitor through DAC. Limit
  11. adc => Dyno inputLimiter => Gain adcThru => mainOutput; // Monitor input
  12. inputLimiter.limit();
  13. inputLimiter @=> UGen @ mainInput;
  14. // Default parameters
  15. .5 => adcThru.gain;
  16. 10000 => lpf.freq;
  17. 10 => hpf.freq;
  18. //1::second => dur loopTime;
  19. // Plug in the pedals
  20. LoopPedal pedals[4];
  21. for( 0 => int i; i < pedals.cap(); i++ ) {
  22. pedals[i].recordFrom(mainInput);
  23. pedals[i].outputTo(outputWet, outputDry);
  24. }
  25. // Create the metronome
  26. Metronome metronome;
  27. spork ~metronome.run();
  28. // Start listening to OSC messages
  29. OscIn oin; 9000 => oin.port;
  30. oin.listenAll();
  31. OscMsg msg;
  32. // Event loop
  33. while (true) {
  34. oin => now;
  35. while (oin.recv(msg)) {
  36. if (msg.address=="/input") {
  37. msg.getFloat(0) => adc.gain;
  38. msg.getFloat(1) => adcThru.gain;
  39. }
  40. else if(msg.address=="/delay") {
  41. msg.getFloat(0)::second => dur loopTime;
  42. msg.getFloat(1) => float feedback;
  43. for( 0 => int i; i < pedals.cap(); i++ ) {
  44. pedals[i].setLoopPoint(loopTime);
  45. pedals[i].setFeedback(feedback);
  46. }
  47. }
  48. else if(msg.address=="/channel") {
  49. msg.getInt(0) => int i;
  50. pedals[i].setGain(msg.getFloat(1));
  51. pedals[i].setPan(msg.getFloat(2));
  52. pedals[i].setWet(msg.getFloat(3));
  53. }
  54. else if(msg.address=="/arm") {
  55. msg.getInt(0) => int channel;
  56. for( 0 => int i; i < pedals.cap(); i++ ) { pedals[i].arm(i==channel); }
  57. }
  58. else if(msg.address=="/metronome") {
  59. //msg.getInt(0) => metronomeLevel;
  60. }
  61. else if(msg.address=="/clear") {
  62. msg.getInt(0) => int channel;
  63. pedals[channel].clear();
  64. }
  65. else if(msg.address=="/fx") {
  66. (100+msg.getFloat(0)*10000) => lpf.freq;
  67. (100+msg.getFloat(1)*10000) => hpf.freq;
  68. msg.getFloat(2) => reverb.mix;
  69. }
  70. else if(msg.address=="/master") {
  71. msg.getFloat(0) => mainOutput.gain;
  72. }
  73. }
  74. }
  75. class LoopPedal
  76. {
  77. // We are wrapping a live sampler, LiSa
  78. LiSa sample;
  79. sample => Gain wet;
  80. sample => Gain dry;
  81. // Setup
  82. 10::second => sample.duration; // Allocate max 10 secs of memory
  83. 0::second => sample.recPos => sample.playPos;
  84. 1.0 => sample.feedback;
  85. 1 => sample.loop;
  86. setLoopPoint(1::second);
  87. setWet(0.5);
  88. public void setLoopPoint( dur length ) { length => sample.loopEnd => sample.loopEndRec; }
  89. public void setFeedback( float fb ) { fb => sample.feedback; }
  90. public void setGain( float gain ) { gain => sample.gain; }
  91. public void setPan( float pan ) { } //pan => panner.pan; }
  92. public void setWet( float ratio ) { ratio => wet.gain; 1-ratio => dry.gain;}
  93. public void clear() { sample.clear(); }
  94. public void recordFrom(UGen ugen) { ugen => sample; }
  95. public dur remaining() { return sample.loopEnd() - sample.playPos(); }
  96. public void outputTo(UGen wetSink, UGen drySink) {
  97. 1 => sample.play;
  98. wet => wetSink;
  99. dry => drySink;
  100. }
  101. public void arm(int value) {
  102. 0 => adcThru.gain;
  103. sample.playPos() => sample.recPos;
  104. value => sample.record;
  105. }
  106. }
  107. class Metronome
  108. {
  109. // A simple metronome
  110. SinOsc s => ADSR a => dac;
  111. 0.5 => s.gain;
  112. a.set(0.01, .1, .5, .2);
  113. 0.01::second => dur plipTime;
  114. fun void run()
  115. {
  116. while(true){
  117. pedals[0].remaining() => now;
  118. a.keyOn();
  119. plipTime => now;
  120. a.keyOff();
  121. }
  122. }
  123. }
  124. /*
  125. // Start the metronome and the vu meter (optional)
  126. //0 => int metronomeLevel;
  127. //spork ~plip();
  128. //spork ~vu_meter();
  129. // TODO timing here should be done using events
  130. fun void metronome()
  131. {
  132. SinOsc s => dac;
  133. 0.01::second => dur plipTime;
  134. while(true){
  135. for( 0 => int i; i < 4; i++ ) {
  136. if (i==0){2000 => s.freq;} else {1000 => s.freq;}
  137. .1*metronomeLevel => s.gain;
  138. plipTime => now;
  139. 0 => s.gain;
  140. loopTime/4 - plipTime => now;
  141. }
  142. }
  143. }
  144. */