Harpe MIDI

Un projet perso, puis dévelopé pour un musicien.

Le principe est d'envoyer une note MIDI avec velocitée suivant la distance d'entrée de la main dans le faiseau, puis d'envoyer un polyaftertoutch suivant le déplacement de la main dans le faiseau. Et ca fonctionne plutot pas mal. Le nombre de notes est limité par le nombre d'entrée de l'arduino nano, ne voulant pas multiplexer, pour garder une truc tres réactif. 7 notes on donc été choisie, et la derniere entrée était pour un capteur supplémentaire envoyant un pitchbend. Celui-ci n'a pas survecu a une erreur de cablage. Deux switchs ont été ajoutés pour glisser d'octave, et trois leds pour indiquer l'octave actuel.

Coté logiciel, le musicien étant sous PetitLogiciel Fenêtre on utilise LoopMidi et Hairless MIDIserial.

Le sketch arduino, pas cleané et sûrement a ameliorer mais qui fonctionne:

#include <MIDI.h> // Includes the MIDI library

int count = 0; // boucle1
int count2= 0; // Boucle 2
int calc = 0;
int reading = 0;
int octave = 4;  // Octave actuel
int midiNOTEselect [] = {60, 62, 64, 65, 67, 69, 71}; //MidiNotes
int midiNOTEvalue [] = {0, 0, 0, 0, 0, 0, 0};
int AnalogValue [] = {0,0,0,0,0,0,0,0};
int oldAnalogValue [] = {0,0,0,0,0,0,0,0};
int DigitalValue [] = {1,1};
int lastDigitalValue [] = {1,1};
int firstPitchValue = 0; // valeur de départ du pitch
double pitchValue = 0;
//float uMinMax [] = {0.4, 2.5};
const int bitMinMax [] = {100, 300};
boolean ledState [] = {0,0,0};
int timeMesure = 0;

// POur le smoothing des entrées analog

// Define the number of samples to keep track of.  The higher the number,
// the more the readings will be smoothed, but the slower the output will
// respond to the input.  Using a constant rather than a normal variable lets
// use this value to determine the size of the readings array.
const int numReadings = 8;

int readings[7][numReadings];      // the readings from the analog input
int index[7] = {0, 0, 0, 0, 0, 0, 0};                  // the index of the current reading
int total[7] = {0, 0, 0, 0, 0, 0, 0};                  // the running total
int average[7] = {0, 0, 0, 0, 0, 0, 0};                // the average
int lastaverage[7] = {0, 0, 0, 0, 0, 0, 0};                // the average
/* tentative de timer par interuption
void wait(int time){
  if time && timeMesure != time {
          timeMesure ++;
          return 0;
  }
  if time && timeMesure == time {
         timeMesure = 0;
          return 1:
  }
}
*/
void setup(){

MIDI.begin(MIDI_CHANNEL_OMNI);
MIDI.turnThruOff();

pinMode(2, INPUT_PULLUP); // Switch octave-
pinMode(3, INPUT_PULLUP); // Switch octave+
pinMode(4, OUTPUT); // Led Octave-
pinMode(5, OUTPUT); // Led Octave0
pinMode(6, OUTPUT); // Led Octave+
       

//Serial.begin(31250); // MIDI
        Serial.begin(38400); // debug

        // Initialisation du tableau pour le moyenage
        for (int i = 0; i < 7; i++) {
            for (int j = 0; j < numReadings; j++) {
                readings[i][j] = 0;
            }
        }
       
        digitalWrite(13, HIGH);
        delay(150);
        digitalWrite(13, LOW);
        delay(150);
        digitalWrite(13, HIGH);
        delay(500);
        digitalWrite(13, LOW);

// tension min - max des capteurs
//bitMinMax[0] = map(uMinMax[0], 0, 5, 0, 1023);
//bitMinMax[1] = map(uMinMax[1], 0, 5, 0, 1023);
/*
        Serial.print("BitMinMax = ");
        Serial.print(bitMinMax[0]);
        Serial.print(" ");
        Serial.println(bitMinMax[1]);
*/
}

void loop () {
        digitalWrite(13, HIGH);
// changement octaves

        DigitalValue[0] = digitalRead(2); // lecture Switch1
        DigitalValue[1] = digitalRead(3); // lecture Switch2
       
for (count = 0; count<=1; count++){
                  /* debug octave
                  Serial.print(count, DEC);
                  Serial.print("\t");
                  Serial.print(lastDigitalValue[count], DEC);
                  Serial.print(DigitalValue[count], DEC);
                  Serial.print("\t");
                  */

if((lastDigitalValue[count] != DigitalValue[count]) && DigitalValue[count] == 0){
switch (count){
case 0: //si le switch 1 est enfoncé
                                    if(octave >= 2){
octave-- ;
for (count2 = 0; count2 < 7; count2 ++) {
if (midiNOTEvalue[count2] != 0){
MIDI.sendNoteOff(midiNOTEselect[count2], 0, 1); //send note OFF avant le changement d'octave
                                                        lastaverage[count2] = 0;
                                                        midiNOTEvalue[count2] = 0;
                                                       
}
midiNOTEselect[count2] = (midiNOTEselect[count2] - 12);
                                                //Serial.print(midiNOTEselect[count2], DEC);
                                                //Serial.print(" ");
}
                                    }
                                Serial.println("");
break;
case 1: // si le switch 2 est enfoncé
                                    if(octave <= 6){
octave++ ;
for (count2 = 0; count2 < 7; count2 ++) {
if (midiNOTEvalue[count2] != 0){
MIDI.sendNoteOff(midiNOTEselect[count2], 0, 1); //send note OFF avant le changement d'octave
                                                        lastaverage[count2] = 0;
                                                        midiNOTEvalue[count2] = 0;
}
midiNOTEselect[count2] = (midiNOTEselect[count2] + 12);
                                                //Serial.print(midiNOTEselect[count2], DEC);
                                                //Serial.print(" ");
}
                                    }
                                //Serial.println("");
break;
}
          }

                  lastDigitalValue[count] = DigitalValue[count];
                  /* debug octave
                  Serial.print(lastDigitalValue[count], DEC);
                  Serial.print(DigitalValue[count], DEC);
                  */
  }

        //Serial.println("");
// etat des leds
switch (octave){
case 4:
ledState[0] = 0;
ledState[1] = 1;
ledState[2] = 0;
break;
case 3:
ledState[0] = 1;
ledState[1] = 1;
ledState[2] = 0;
break;
case 2:
ledState[0] = 1;
ledState[1] = 0;
ledState[2] = 0;
break;
case 5:
ledState[0] = 0;
ledState[1] = 1;
ledState[2] = 1;
break;
case 6:
ledState[0] = 0;
ledState[1] = 0;
ledState[2] = 1;
break;
}
// etat des pin
for (count = 0; count<=2; count++) {
if (ledState[count] == 1){
digitalWrite((count+4), HIGH);
}
else{
digitalWrite((count+4), LOW);
}
}
digitalWrite(13, LOW);
// lecture, mise en forme et envoi du midi
for (count = 0; count<7; count++) {
                delay(3); //debug
                reading = analogRead(count);
                calc = map(reading, bitMinMax[0], bitMinMax[1], 0, 127);
                AnalogValue[count] = constrain(calc, 0, 127); // Lecture de la valeur analogique et mise a l'échelle
               
                if(AnalogValue[count] < 0){
                    AnalogValue[count] = 0; // Treshold
                }
               
                // moyenage
                // subtract the last reading:
                total[count]= total[count] - readings[count][index[count]];       
                // read from the sensor: 
                readings[count][index[count]] = AnalogValue[count];
                // add the reading to the total:
                total[count]= total[count] + readings[count][index[count]];     
                // advance to the next position in the array: 
                index[count] = index[count] + 1 ;                   
             
                // if we're at the end of the array...
                if (index[count] >= numReadings){
                  // ...wrap around to the beginning:
                  index[count] = 0;
                }
             
                // calculate the average:
                average[count] = total[count] / numReadings;
               
                // pick older value
                oldAnalogValue[count] = readings[count][(index[count] + 1)%numReadings];
               
//                Serial.print(count);
//                Serial.print("\t");
                 /*
                                    if (count == 0){
                                        Serial.print("\t");
                                        Serial.print(count);
                                    }
                                    if (count == 0){
                                        Serial.print("\t");
                                        Serial.print(average[count]);
                                    }
                                    if (count == 0){
                                        Serial.print("\t");
                                        Serial.print(AnalogValue[count]);
                                    }
                                    if (count == 0){
                                         Serial.print("\t");
                                         Serial.print(lastaverage[count]);
                                    }
                                    if (count == 0){
                                         Serial.print("\t");
                                         Serial.println(oldAnalogValue[count]);
                                    }
              
                */
if (lastaverage[count] != average[count]) { // check if analog input has changed
if (abs(lastaverage[count] - average[count]) > 5 && (oldAnalogValue[count] != 0) && (AnalogValue[count] != 0) && (midiNOTEvalue[count] == 0)) {
midiNOTEvalue[count] = AnalogValue[count];
MIDI.sendNoteOn(midiNOTEselect[count], midiNOTEvalue[count], 1); //send note ON
//                                       Serial.print("NoteOn : ");
//                                       Serial.print(midiNOTEselect[count]);
//                                       Serial.print(" ");
//                                       Serial.println(midiNOTEvalue[count]);
                                     
}
else if ((average[count] == 0) && (lastaverage[count] != 0) && (midiNOTEvalue[count] != 0)) {
midiNOTEvalue[count] = average[count];
MIDI.sendNoteOff(midiNOTEselect[count], midiNOTEvalue[count], 1); //send note OFF
//                                       Serial.print("NoteOff : ");
//                                       Serial.print(midiNOTEselect[count]);
//                                       Serial.print(" ");
//                                       Serial.println(midiNOTEvalue[count]);
}
else if ((average[count] != 0) && (lastaverage[count] != 0) && (midiNOTEvalue[count] != 0)) {
MIDI.sendPolyPressure(midiNOTEselect[count], constrain((average[count] - midiNOTEvalue[count] + 50), 0, 127), 1); //send polyaftertouch
//                                       Serial.print("Aftertoutch : ");
//                                       Serial.print(midiNOTEselect[count]);
//                                       Serial.print(" ");
//                                       Serial.println((average[count] - midiNOTEvalue[count] + 64));
}

        lastaverage[count] = average[count]; // mise a jour du la precedente valeur moyennee
}
}
       
        // Et maintenant le Pitch
/*if (1 == 0){
        if (firstPitchValue == 0 && AnalogValue[count] != 0){
firstPitchValue = AnalogValue[count]; //pitch présent
}
else if (firstPitchValue != 0 && AnalogValue[count] == 0){
firstPitchValue = AnalogValue[count]; //pitch absent
MIDI.sendPitchBend(0, 1);
}
if (firstPitchValue != 0 && AnalogValue[count] != 0){
pitchValue = constrain(map((AnalogValue[count] - firstPitchValue), 0, 1023, -1, 1), -1, 1);
MIDI.sendPitchBend(pitchValue, 1);
}
}*/

//          delay(2);
//          Serial.println("-- -- --");
}

A base de capteurs Sharp et d'arduino. Désolé pour la qualitée des photos, les images originales sont dans le coma...

Ce projet m'interesse. qui es

Ce projet m'interesse. qui es-tu exactement ?
Etant donnE le rapport vitesse de la main et vitesse du cpu, si tu savais utiliser les interrupts en temps reel tu ne dirais jamais que multiplexer ralentit la reponse du systeme. Contacte-moi pour toute question, y compris des references sur le M.I.D.I.
Masterzee.