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.

167 lines
4.2KB

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