Advertisement
Sebi

Arduino + SuperCollider

Jul 3rd, 2015
578
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.60 KB | None | 0 0
  1. // Author: Sebastian Grygiel (Sebi)
  2. // Spring 2015
  3.  
  4. // Demo video: https://www.youtube.com/watch?v=MJAmfSJmgrA
  5.  
  6. // Instructions:
  7. // See the supercollider file: https://pastebin.com/D46ZVmPD also see the youtube video
  8. // Serial port speed: 115200
  9.  
  10. // LED is the pin for the first led
  11. // i.e. if led == 2 -> leds are connected to pins 2, 3, 4, 5
  12. const int LED = 2;
  13.  
  14. // Buttons are pulled up, connect to ground to activate - left/right controls
  15. const int BTNL = 6;
  16. const int BTNR = 7;
  17. // if SWITCH_AUTO pin is grounded, it will automatically advance the sequence at random intervals
  18. const int SWITCH_AUTO = 13;
  19.  
  20. // Hook up a voltage (eg. a potentiometer) to pin A5, apply 0-5V for volume control.
  21. // Volumes below approx 1.7V will be further attenuated, low-pitch notes are attenuated less.
  22.  
  23. void setup() {
  24.   Serial.begin(115200);
  25.   randomSeed(analogRead(0) + random(1000));
  26.   pinMode(A5, INPUT);
  27.   pinMode(11, OUTPUT);
  28.   pinMode(LED, OUTPUT);
  29.   pinMode(LED+1, OUTPUT);
  30.   pinMode(LED+2, OUTPUT);
  31.   pinMode(LED+3, OUTPUT);
  32.   pinMode(BTNL, INPUT_PULLUP);
  33.   pinMode(BTNR, INPUT_PULLUP);
  34.   pinMode(SWITCH_AUTO, INPUT_PULLUP);
  35.   randomSeed(analogRead(0) + random(1000));
  36. }
  37.  
  38. const uint8_t notes[] {
  39.     // notes from a SPU script by OmicroN from wiremod.com :D
  40.     // http://www.wiremod.com/forum/cpu-gpu-hi-speed-discussion-help/25493-gpu-spu-examples-pack-graphics-library.html#post231991
  41.     // EDIT: Year 2019: RIP Wiremod.com forums, I will never forget what I learned inspired by Wiremod. Special thanks to core contributors who made project possible.
  42.     // here is the archived post which was the source for this melody
  43.     // http://web.archive.org/web/20150427134923/http://www.wiremod.com/forum/cpu-gpu-hi-speed-discussion-help/25493-gpu-spu-examples-pack-graphics-library.html#post231991
  44.     /// END EDIT
  45.     73,65,70,65, 73,65,70,65, 73,65,70,65, 73,65,70,65, 73,67,70,67, 73,67,70,67, 73,67,70,67, 73,67,70,67,
  46.     78,70,75,70, 78,70,75,70, 78,70,75,70, 78,70,75,70, 75,68,72,68, 75,68,72,68, 75,68,72,68, 75,68,72,68,
  47.     73,77,82,77, 73,77,82,77, 73,77,82,77, 73,77,82,77, 73,79,82,79, 73,79,82,79, 73,79,82,79, 73,79,82,79,
  48.     78,82,75,82, 78,82,75,82, 78,82,75,82, 78,82,75,82, 75,80,72,80, 75,80,72,80, 75,80,72,80, 75,80,72,80
  49. }; // 128 notes (4 groups)
  50.  
  51. uint16_t counter = 0;
  52. uint8_t curnote = 0;
  53. uint8_t curgroup = 0;
  54. uint8_t nextgroup = 0;
  55. uint8_t blinkflag = 0;
  56. uint8_t randval = 0;
  57.  
  58. void setLed(int8_t led) {
  59.   digitalWrite(LED, led == 0);
  60.   digitalWrite(LED+1, led == 1);
  61.   digitalWrite(LED+2, led == 2);
  62.   digitalWrite(LED+3, led == 3);
  63. }
  64.  
  65. uint8_t pressed = 0; // store pressed buttons as separate bits (1 & 2)
  66. uint8_t pressed_delay = 0;
  67.  
  68. void loop() {
  69.   delayMicroseconds(200); // this determines the timing of everything
  70.   // There should be independent timing for switch debouncing etc but this is a rough script
  71.   counter++;
  72.  
  73.   if(!digitalRead(BTNL) && pressed & 1 && !pressed_delay) {
  74.     nextgroup = nextgroup - 1;
  75.     if(nextgroup > 3) nextgroup = 3; // when uint8 underflows, it becomes 255
  76.     blinkflag = 1;
  77.     pressed_delay = 10; // increase here and below if your buttons are registered multiple times
  78.   }
  79.   if(!digitalRead(BTNR) && pressed & 2 && !pressed_delay) {
  80.     nextgroup = nextgroup + 1;
  81.     if(nextgroup > 3) nextgroup = 0;
  82.     blinkflag = 1;
  83.     pressed_delay = 10;
  84.   }
  85.   // store pressed buttons as separate bits
  86.   pressed = digitalRead(BTNL) + 2*digitalRead(BTNR);
  87.  
  88.   if(!blinkflag) {
  89.     if(counter % 8 == 0) {
  90.       setLed(curgroup);
  91.     }else{
  92.       setLed((curnote / 4) % 4);
  93.     }
  94.   }else{
  95.     if(counter % 8 == 0) {
  96.       setLed((curnote / 4) % 4);
  97.     }else{
  98.       // below, (curnote % 2) * 4 makes it blink by attempting to set non-existent led index
  99.       setLed(nextgroup + (curnote % 2) * 4);
  100.     }
  101.   }
  102.  
  103.   if(counter % 50 == 0) {
  104.     if(pressed_delay) pressed_delay--;
  105.     uint16_t val = map(constrain(analogRead(A5),50,970), 50, 970, 0, 1000);
  106.     uint8_t noteval = notes[curgroup * 32 + curnote];
  107.     if(val < 350) {
  108.       float diff = val/350.0f; // 0 quiet 1 full
  109.       float notediff = (noteval - 60)/4.0f; // 0 full 1 -6db
  110.       diff = diff*diff;
  111.  
  112.       if(notediff < 1)
  113.         notediff = 1;
  114.  
  115.       // first part val*diff == val(val/350) == val*(0..1) applies exponential curve, making quiet sounds quieter
  116.       // second part val*(1-diff)/notediff/notediff cancels out the effect of the first part exactly if notediff is 1
  117.       // making low tones less attenuated at low volume levels. This makes high tones appear more with volume.
  118.       // note: this only applies to analogue values less than 350 (approx 1/3 of the volume range)
  119.       val = (val * diff)  +  (val * (1-diff) / notediff / notediff);
  120.     }
  121.     // Analogue indicator output - for hooking up to an LED or a meter (see the youtube video https://www.youtube.com/watch?v=MJAmfSJmgrA - white LED and the voltage meter)
  122.     analogWrite(11, (int)(constrain(((uint16_t)noteval - 64) * 14,0,255) * (float)(constrain(val,0,500)/500.0f)));
  123.     // Send the actual command
  124.     Serial.println(String(noteval - 24) + " " + val );
  125.   }
  126.  
  127.   if(counter == 550) {
  128.     counter = 0;
  129.    
  130.     curnote++;
  131.     if(curnote == 32) {
  132.       if(!digitalRead(SWITCH_AUTO) && !blinkflag) {
  133.         if(random(4) <= randval) {
  134.           nextgroup = nextgroup + 1;
  135.           if(nextgroup > 3) nextgroup = 0;
  136.           randval = 1;
  137.         }else{
  138.           randval++;
  139.         }
  140.       }
  141.       curnote = 0;
  142.       blinkflag = 0;
  143.       if(nextgroup != curgroup) {
  144.         curgroup = nextgroup;
  145.       }
  146.     }
  147.   }
  148. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement