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.

134 lines
3.5KB

  1. // TODO: turn off adcThru when recording
  2. // Effects chain
  3. adc => Dyno limitIn => Gain adcThru => dac; // Monitor input through a mixer
  4. // Global effects break panning for some unknown reason
  5. Dyno limitOut => PRCRev rev => dac;
  6. .3 => rev.mix;
  7. limitIn.limit(); limitOut.limit();
  8. SampleChan channels[4];
  9. // Levels
  10. //0 => adc.gain;
  11. .5 => adcThru.gain;
  12. // Global loop time
  13. 1::second => dur loopTime;
  14. // Each channel should output to the mixer
  15. for( 0 => int i; i < channels.cap(); i++ ) { channels[i].outputTo(limitOut); }
  16. // Listen to OSC messages
  17. OscIn oin; 9000 => oin.port;
  18. oin.listenAll();
  19. OscMsg msg;
  20. // Start the metronome
  21. 0 => int metronomeLevel;
  22. //spork ~metronome();
  23. //spork ~vu_meter();
  24. // Event loop
  25. while (true) {
  26. oin => now;
  27. while (oin.recv(msg)) {
  28. if (msg.address=="/input") {
  29. msg.getFloat(0) => adc.gain;
  30. msg.getFloat(1) => adcThru.gain;
  31. }
  32. else if(msg.address=="/delay") {
  33. msg.getFloat(0)::second => loopTime;
  34. msg.getFloat(1) => float feedback;
  35. for( 0 => int i; i < channels.cap(); i++ ) {
  36. channels[i].setLoopPoint(loopTime);
  37. channels[i].setFeedback(feedback);
  38. }
  39. }
  40. else if(msg.address=="/channel") {
  41. msg.getInt(0) => int i;
  42. channels[i].setGain(msg.getFloat(1));
  43. channels[i].setPan(msg.getFloat(2));
  44. }
  45. else if(msg.address=="/arm") {
  46. msg.getInt(0) => int channel;
  47. for( 0 => int i; i < channels.cap(); i++ ) { channels[i].arm(i==channel); }
  48. }
  49. else if(msg.address=="/metronome") {
  50. msg.getInt(0) => metronomeLevel;
  51. }
  52. else if(msg.address=="/clear") {
  53. msg.getInt(0) => int channel;
  54. channels[channel].clear();
  55. }
  56. }
  57. }
  58. public class SampleChan
  59. {
  60. // Chain
  61. adc => LiSa sample => Pan2 panner;
  62. // Setup
  63. 10::second => sample.duration; //This is the max duration
  64. 0::second => sample.recPos => sample.playPos;
  65. 1.0 => sample.feedback;
  66. 1 => sample.loop;
  67. setLoopPoint(1::second);
  68. public void setLoopPoint( dur length ) { length => sample.loopEnd => sample.loopEndRec; }
  69. public void setFeedback( float fb ) { fb => sample.feedback; }
  70. public void setGain( float gain ) { gain => panner.gain; }
  71. public void setPan( float pan ) { pan => panner.pan; }
  72. public void clear() { sample.clear(); }
  73. public void outputTo(UGen ugen) {
  74. 1 => sample.play;
  75. panner => ugen;
  76. }
  77. public void arm(int value) {
  78. sample.playPos() => sample.recPos;
  79. value => sample.record;
  80. }
  81. }
  82. fun void vu_meter()
  83. {
  84. // Analysis stuff
  85. adc => FFT fft =^ RMS rms => blackhole;
  86. 1<<12 => int fftsize;
  87. fftsize => fft.size;
  88. Windowing.hann(fftsize) => fft.window;
  89. // Comms
  90. OscOut xmit; xmit.dest( "localhost", 6649 );
  91. // Infinite loop: get RMS and send to GUI
  92. while(true)
  93. {
  94. rms.upchuck() @=> UAnaBlob blob;
  95. xmit.start("/vu");
  96. blob.fval(0) => xmit.add;
  97. xmit.send();
  98. fft.size()::samp => now;
  99. }
  100. }
  101. // TODO timing here should be done using events
  102. fun void metronome()
  103. {
  104. SinOsc s => dac;
  105. 0.01::second => dur plipTime;
  106. while(true){
  107. for( 0 => int i; i < 4; i++ ) {
  108. if (i==0){2000 => s.freq;} else {1000 => s.freq;}
  109. .1*metronomeLevel => s.gain;
  110. plipTime => now;
  111. 0 => s.gain;
  112. loopTime/4 - plipTime => now;
  113. }
  114. }
  115. }