Advertisement
Guest User

Arduino Euclidean Sequencer

a guest
Nov 13th, 2021
113
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <MIDI.h>
  2. #include <FastLED.h>
  3. #define MIDI_VELOCITY 123 //El CC midi 123 es la intensidad, la reduciremos a cero cuando queramos silencio
  4. #define NUM_LEDS 16
  5. #define STEPS 16
  6. #define PIN 2// Led Ring
  7. //BOTONERA:
  8. #define PREV A0
  9. #define NEXT A1
  10. #define NOTEADD A6
  11. #define NOTEDEC A7
  12. #define OFFSETADD A5
  13. #define OFFSETDEC A4
  14. #define NUMBERADD A2
  15. #define NUMBERDEC A3
  16. //ENCODER
  17. #define ENC_SW 13 //
  18. #include "EncoderStepCounter.h"
  19. #define NUMPIXELS 16 // Popular NeoPixel ring size
  20. #define DELAYVAL 200 // Time (in milliseconds) to pause between pixels
  21. #define BPM 120
  22. int Delay = 15000 / BPM;
  23. //ENCODER
  24. #define ENCODER_PIN1 21
  25. #define ENCODER_INT1 digitalPinToInterrupt(ENCODER_PIN1)
  26. #define ENCODER_PIN2 3
  27. #define ENCODER_INT2 digitalPinToInterrupt(ENCODER_PIN2)
  28. EncoderStepCounter encoder(ENCODER_PIN1, ENCODER_PIN2, HALF_STEP);
  29. //ENCODER
  30. unsigned int rotateBitShiftRight(unsigned int chunk, byte rotation) {
  31.   chunk = (chunk >> rotation) | (chunk << (16 - rotation)); //Suma lógica (OR) del valor con bitshift desde LSB y complementaria desde MSB
  32.   return chunk;
  33. }
  34. unsigned int rotateBitShiftLeft(unsigned int chunk, byte rotation) {
  35.   chunk = (chunk << rotation) | (chunk >> (16 - rotation)); //Suma lógica (OR) del valor con bitshift desde LSB y complementaria desde MSB
  36.   return chunk;
  37. }
  38. class Track {
  39.   private:
  40.     byte Note;
  41.     byte Offset;
  42.     byte Number;
  43.     unsigned int Euclidean;
  44.   public:
  45.     void setTrack() {
  46.       Note = 78; //C3
  47.       Offset = 0;
  48.       Number = 0;
  49.       Euclidean = 0b0000000000000000;
  50.     }
  51.     void populateEuclidean() {
  52.       unsigned int euclideanPatterns[17] = { //Precalculated Euclid patterns
  53.         0b0000000000000000,
  54.         0b1000000000000000,
  55.         0b1000000010000000,
  56.         0b1000010000100000,
  57.         0b1000100010001000,
  58.  
  59.         0b1001001001001000,
  60.         0b1001010010010100,
  61.         0b1001010100101010,
  62.         0b1010101010101010,
  63.  
  64.         0b1011010101101010,
  65.         0b1011010110110101,
  66.         0b1011011011011011,
  67.         0b1011101110111011,
  68.  
  69.         0b1011110111101111,
  70.         0b1011111110111111,
  71.         0b1111111111111110,
  72.         0b1111111111111111
  73.       };
  74.  
  75.       Euclidean = rotateBitShiftRight(euclideanPatterns[Number], Offset); //Rotated to Offset value
  76.     }
  77.     void addOffset() {
  78.       if ( Offset > 15 ) {
  79.         Offset = 0;
  80.       } else {
  81.         Offset++;
  82.       }
  83.       Euclidean = rotateBitShiftRight( Euclidean , 1 );
  84.     }
  85.     void decOffset() {
  86.       if (Offset > 0) {
  87.         Offset--;
  88.       } else {
  89.         Offset = 15;
  90.       }
  91.       Euclidean = rotateBitShiftLeft( Euclidean , 1 );
  92.     }
  93.     void addNumber() {
  94.       if (Number < 16) {
  95.         Number++;
  96.       }
  97.       else {
  98.         Number = 0;
  99.       }
  100.       populateEuclidean();
  101.     }
  102.     void decNumber() {
  103.       if ( Number > 0) {
  104.         Number--;
  105.       }
  106.       else {
  107.         Number = 16;
  108.       }
  109.       populateEuclidean();
  110.     }
  111.     void addNote() {
  112.       Note++;
  113.     }
  114.     void decNote() {
  115.       Note--;
  116.     }
  117.     byte getNote() {
  118.       return Note;
  119.     }
  120.     unsigned int getEuclidean() {
  121.       return Euclidean;
  122.     }
  123. };
  124. MIDI_CREATE_DEFAULT_INSTANCE();
  125. byte Pista = 0;
  126. byte Paso = 0;
  127. Track track[4];
  128. CRGBArray<NUM_LEDS> leds;
  129.  
  130. class Anillo {
  131.   private:
  132.     byte Output[16];//array 16 colores
  133.     byte Posicion;//posición del puntero
  134.     byte ColorActual;//color puntero
  135.     byte Anterior;
  136.   public:
  137.     void setAnillo() {
  138.       for (int i = 0; i < 16; i++) {
  139.         Output[i] = 0;
  140.       }
  141.       Posicion = 0;
  142.       ColorActual = 0;
  143.     }
  144.     void setAnillo(byte pos, byte col) {
  145.       Posicion = pos;
  146.       ColorActual = col;
  147.     }
  148.     voidSetPosicion(byte val) {
  149.       Posicion = val;
  150.     }
  151.     void crearFondo() {
  152.       for (int i = 15; i >= 0; i--) {
  153.         byte posibilidades[4] = {0, 0, 0, 0,};
  154.         byte contador = 0;
  155.         for (int j = 0; j < 4; j++) {
  156.           if (bitRead(track[j].getEuclidean(), i)) {
  157.             //Serial.print("1-");
  158.             posibilidades[contador] = track[j].getNote();
  159.             contador++;
  160.           }
  161.         }
  162.         if (contador > 0) {
  163.           Output[i] = posibilidades[random(contador)];
  164.           leds[i] = CHSV(map(Output[i], 60, 106, 0, 255), 200, 150); //CRGB::Blue;
  165.         }
  166.         else {
  167.           leds[i] = CRGB::Black;
  168.           Output[i] = 0;
  169.           //Serial.print("0-");
  170.         }
  171.       }
  172.     }
  173.     void crearPuntero() {
  174.       leds[Posicion] = CRGB::Orange;
  175.     }
  176.     //borrar
  177.     void borrar() {
  178.       FastLED.clear();
  179.     }
  180.     //mostrar
  181.     void mostrar() {
  182.       FastLED.show();
  183.     }
  184.     void actualiza(byte val) {
  185.       borrar();
  186.       crearFondo();
  187.       setAnillo(val, CRGB::Green);
  188.       crearPuntero();
  189.       mostrar();
  190.     }
  191.     void silencio() {
  192.       MIDI.sendNoteOff(Anterior, 0, 1);
  193.       MIDI.sendControlChange(123, 0, 1);
  194.     }
  195.     void toca(byte val) {
  196.       if (Output[val] != 0) {
  197.         MIDI.sendNoteOn(Output[val], 100, 1);
  198.         Anterior = Output[val];
  199.       }
  200.     }
  201. };
  202. Anillo seq;
  203.  
  204. void botones() {
  205.   static byte boton = 0;
  206.   static byte i = A0;
  207.   static byte contador = 0;
  208.   const int Theshold = 900;
  209.   const byte Debounce = 5;
  210.   static unsigned long int ultimaComprobacion = 0;
  211.   if (boton == 0) {
  212.     if (contador > Debounce) {
  213.       //Serial.println();
  214.       contador = 0;
  215.       boton = i;
  216.       return;
  217.     }
  218.     else if (analogRead(i) > Theshold) {
  219.       if ((millis() - ultimaComprobacion) > 1)
  220.       {
  221.         //Serial.print(analogRead(i));
  222.         contador ++;
  223.         //Serial.print(contador);
  224.         //Serial.print(" ");
  225.         ultimaComprobacion = millis();
  226.       }
  227.     }
  228.     else {
  229.       contador = 0;
  230.       i++;
  231.       if (i > A7) {
  232.         i = A0;
  233.       }
  234.     }
  235.   } else if (analogRead(boton) > Theshold) {
  236.     return; //No realiza la acción hasta soltar el boton.
  237.   }
  238.   else {
  239.     switch (boton) {
  240.       case PREV: (Pista == 0) ? Pista = 3 : Pista++; break;
  241.       case NEXT: (Pista == 3) ? Pista = 0 : Pista++; break;
  242.       case OFFSETADD: track[Pista].addOffset(); break;
  243.       case OFFSETDEC: track[Pista].decOffset(); break;
  244.       case NUMBERADD: track[Pista].addNumber(); break;
  245.       case NUMBERDEC: track[Pista].decNumber(); break;
  246.       case NOTEADD: track[Pista].addNote(); break;
  247.       case NOTEDEC: track[Pista].decNote();  break;
  248.         //Serial.println();
  249.         //Serial.print("Botón pulsado: ");
  250.         //Serial.print(boton);
  251.     }
  252.     boton = 0;
  253.     seq.actualiza(Paso); //Si hay cambios actualiza el display.
  254.   }
  255. }
  256.  
  257. bool encoderSW() {
  258.   if ( digitalRead(ENC_SW) == 1) {
  259.     return 0;
  260.   }
  261.   while ( digitalRead(ENC_SW) == 0) {} //return 1;
  262.   while ( digitalRead(ENC_SW) == 1) {}
  263.   while ( digitalRead(ENC_SW) == 0) {}
  264. }
  265.  
  266. void setup() {
  267.   MIDI.begin(MIDI_CHANNEL_OMNI);
  268.   //Serial.begin(115200);
  269.   FastLED.addLeds<NEOPIXEL, 2>(leds, NUM_LEDS);
  270.   FastLED.setBrightness(25);
  271.   pinMode(A1, INPUT);
  272.   pinMode(A2, INPUT);
  273.   pinMode(A3, INPUT);
  274.   pinMode(A4, INPUT);
  275.   pinMode(A5, INPUT);
  276.   pinMode(A6, INPUT);
  277.   pinMode(A7, INPUT);
  278.   //ENCODER
  279.   encoder.begin();
  280.   pinMode (ENC_SW, INPUT_PULLUP);
  281.   attachInterrupt(ENCODER_INT1, interrupt, CHANGE);
  282.   attachInterrupt(ENCODER_INT2, interrupt, CHANGE);
  283.   randomSeed(analogRead(A0));
  284.   for (int i = 0; i < 4; i++) {
  285.     track[i].setTrack();
  286.   }
  287.  
  288. }
  289. void interrupt() {
  290.   encoder.tick();
  291. }
  292. void loop() {
  293.   EVERY_N_MILLISECONDS_I(bpm, Delay) {
  294.     static byte cont = 0;
  295.     seq.silencio();
  296.     Paso = cont;
  297.     seq.actualiza(cont);
  298.     seq.toca(cont);
  299.     cont++;
  300.     bpm.setPeriod(Delay);
  301.     if (cont >= STEPS) {
  302.       cont = 0;
  303.     }
  304.   }
  305.   botones();
  306.   ////Serial.println(myEnc.read());
  307.   encoderSW();
  308.   static unsigned int position = BPM;
  309.   signed char pos = encoder.getPosition();
  310.   if (pos != 0) {
  311.     position += pos;
  312.     if (position == 0) {
  313.       position = 1;
  314.     }
  315.     encoder.reset();
  316.     //Serial.println(position);
  317.     Delay = 15000 / position;
  318.   }
  319. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement