Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Author: Sebastian Grygiel (Sebi)
- // Spring 2015
- // Demo video: https://www.youtube.com/watch?v=MJAmfSJmgrA
- // Instructions:
- // See the supercollider file: https://pastebin.com/D46ZVmPD also see the youtube video
- // Serial port speed: 115200
- // LED is the pin for the first led
- // i.e. if led == 2 -> leds are connected to pins 2, 3, 4, 5
- const int LED = 2;
- // Buttons are pulled up, connect to ground to activate - left/right controls
- const int BTNL = 6;
- const int BTNR = 7;
- // if SWITCH_AUTO pin is grounded, it will automatically advance the sequence at random intervals
- const int SWITCH_AUTO = 13;
- // Hook up a voltage (eg. a potentiometer) to pin A5, apply 0-5V for volume control.
- // Volumes below approx 1.7V will be further attenuated, low-pitch notes are attenuated less.
- void setup() {
- Serial.begin(115200);
- randomSeed(analogRead(0) + random(1000));
- pinMode(A5, INPUT);
- pinMode(11, OUTPUT);
- pinMode(LED, OUTPUT);
- pinMode(LED+1, OUTPUT);
- pinMode(LED+2, OUTPUT);
- pinMode(LED+3, OUTPUT);
- pinMode(BTNL, INPUT_PULLUP);
- pinMode(BTNR, INPUT_PULLUP);
- pinMode(SWITCH_AUTO, INPUT_PULLUP);
- randomSeed(analogRead(0) + random(1000));
- }
- const uint8_t notes[] {
- // notes from a SPU script by OmicroN from wiremod.com :D
- // http://www.wiremod.com/forum/cpu-gpu-hi-speed-discussion-help/25493-gpu-spu-examples-pack-graphics-library.html#post231991
- // 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.
- // here is the archived post which was the source for this melody
- // 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
- /// END EDIT
- 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,
- 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,
- 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,
- 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
- }; // 128 notes (4 groups)
- uint16_t counter = 0;
- uint8_t curnote = 0;
- uint8_t curgroup = 0;
- uint8_t nextgroup = 0;
- uint8_t blinkflag = 0;
- uint8_t randval = 0;
- void setLed(int8_t led) {
- digitalWrite(LED, led == 0);
- digitalWrite(LED+1, led == 1);
- digitalWrite(LED+2, led == 2);
- digitalWrite(LED+3, led == 3);
- }
- uint8_t pressed = 0; // store pressed buttons as separate bits (1 & 2)
- uint8_t pressed_delay = 0;
- void loop() {
- delayMicroseconds(200); // this determines the timing of everything
- // There should be independent timing for switch debouncing etc but this is a rough script
- counter++;
- if(!digitalRead(BTNL) && pressed & 1 && !pressed_delay) {
- nextgroup = nextgroup - 1;
- if(nextgroup > 3) nextgroup = 3; // when uint8 underflows, it becomes 255
- blinkflag = 1;
- pressed_delay = 10; // increase here and below if your buttons are registered multiple times
- }
- if(!digitalRead(BTNR) && pressed & 2 && !pressed_delay) {
- nextgroup = nextgroup + 1;
- if(nextgroup > 3) nextgroup = 0;
- blinkflag = 1;
- pressed_delay = 10;
- }
- // store pressed buttons as separate bits
- pressed = digitalRead(BTNL) + 2*digitalRead(BTNR);
- if(!blinkflag) {
- if(counter % 8 == 0) {
- setLed(curgroup);
- }else{
- setLed((curnote / 4) % 4);
- }
- }else{
- if(counter % 8 == 0) {
- setLed((curnote / 4) % 4);
- }else{
- // below, (curnote % 2) * 4 makes it blink by attempting to set non-existent led index
- setLed(nextgroup + (curnote % 2) * 4);
- }
- }
- if(counter % 50 == 0) {
- if(pressed_delay) pressed_delay--;
- uint16_t val = map(constrain(analogRead(A5),50,970), 50, 970, 0, 1000);
- uint8_t noteval = notes[curgroup * 32 + curnote];
- if(val < 350) {
- float diff = val/350.0f; // 0 quiet 1 full
- float notediff = (noteval - 60)/4.0f; // 0 full 1 -6db
- diff = diff*diff;
- if(notediff < 1)
- notediff = 1;
- // first part val*diff == val(val/350) == val*(0..1) applies exponential curve, making quiet sounds quieter
- // second part val*(1-diff)/notediff/notediff cancels out the effect of the first part exactly if notediff is 1
- // making low tones less attenuated at low volume levels. This makes high tones appear more with volume.
- // note: this only applies to analogue values less than 350 (approx 1/3 of the volume range)
- val = (val * diff) + (val * (1-diff) / notediff / notediff);
- }
- // 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)
- analogWrite(11, (int)(constrain(((uint16_t)noteval - 64) * 14,0,255) * (float)(constrain(val,0,500)/500.0f)));
- // Send the actual command
- Serial.println(String(noteval - 24) + " " + val );
- }
- if(counter == 550) {
- counter = 0;
- curnote++;
- if(curnote == 32) {
- if(!digitalRead(SWITCH_AUTO) && !blinkflag) {
- if(random(4) <= randval) {
- nextgroup = nextgroup + 1;
- if(nextgroup > 3) nextgroup = 0;
- randval = 1;
- }else{
- randval++;
- }
- }
- curnote = 0;
- blinkflag = 0;
- if(nextgroup != curgroup) {
- curgroup = nextgroup;
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement