====== light-synth ====== * Porteur du projet : fenshu [[:user:resonance|resonance]] * Date : 09/07/2017/ - ... * Licence : [[http://creativecommons.org/licenses/by-sa/3.0/legalcode|CC-by-sa-3.0]] * Description : synthé qui marche avec la lumiere * Fichiers sources : voir plus bas pour les codes , design : {{ :projets:light-synth:lightsynthdesign.ai |}} * Lien : //mettre un lien// {{tag>esadmm lumiere, son, arduino, puredata}} ===== Note d'intention ===== Synthé qui marche avec la lumiere : Plusieurs pistes sont possible, notamment en changeant les fréquences des pwm avec library Tone et Mozzi {{projets:light-synth:accueil:instrument_lumiere_minuscule.jpg?800|light-synth}} ===== Codes ===== Voici quelques codes pas mal... Certains utilisent les libraries Tone et Mozzi pour transformer l'arduino en petit synthé ! On capte le son emis en lumiere par des leds, via un panneau solaire. Ca donne ceci : {{youtube>nbi2d_UTToQ?large}} //Le troisieme synth de la video est l'exemple de la librarie mozzi : Sensor/lighttemperature...// ==== Boite a rythme a led ==== On fait clignoter 3 led a la noire, croche triolet, et on controle le temp avec un potentiometre et une photoresistance... ++++ Le code | // 3 led a jouant a la noire, croche et triolet // un potentiometre 10k en A0 : controle le tempo général... // une photo resistance en A1 : controle un effet de delay #define led1 5 #define led2 9 #define led3 10 #define factor 6 //factor for pwm tone ! unsigned long previousMillis[3]; //[x] = number of leds void setup() { pinMode(led1, OUTPUT); pinMode(led2, OUTPUT); pinMode(led3, OUTPUT); Serial.begin(9600); } void loop() { int sensorValue = analogRead(A0); sensorValue = map(sensorValue, 0, 1023, 0, 2000); if(sensorValue > 1990) { sensorValue == 10000; } int sensorValueB = analogRead(A1); sensorValueB = map(sensorValueB, 0, 1023, 1023, 0); if(sensorValueB > 800) { BlinkLedSimple(led1, sensorValue, 0,sensorValueB); //BlinkLed( which led, interval, one of the stored prevMillis BlinkLedSimple(led2, sensorValue/3, 1,sensorValueB); //last parameters must be different for each led BlinkLedSimple(led3, sensorValue/2, 2,sensorValueB); } if(sensorValueB > 400 && sensorValueB < 800 ) { BlinkLed(led1, sensorValue, 0,sensorValueB); //BlinkLed( which led, interval, one of the stored prevMillis BlinkLed(led2, sensorValue/3, 1,sensorValueB); //last parameters must be different for each led BlinkLed(led3, sensorValue/2, 2,sensorValueB); } if(sensorValueB < 400) { BlinkLedSuper(led1, sensorValue, 0,sensorValueB); //BlinkLed( which led, interval, one of the stored prevMillis BlinkLedSuper(led2, sensorValue/3, 1,sensorValueB); //last parameters must be different for each led BlinkLedSuper(led3, sensorValue/2, 2,sensorValueB); } Serial.print("potentiometre"); Serial.println(sensorValue); Serial.print("ldr"); Serial.println(sensorValueB); delay(1); } ///Simple blink void BlinkLedSimple (int led, int interval, int array, int pwm){ if (((long)millis() - previousMillis[array]) >= interval){ previousMillis[array]= millis(); //stores the millis value in the selected array digitalWrite(led, !digitalRead(led)); //changes led state }} ///delayyyy blink void BlinkLed (int led, int interval, int array, int pwm){ if (((long)millis() - previousMillis[array]) >= interval){ previousMillis[array]= millis(); //stores the millis value in the selected array digitalWrite(led, !digitalRead(led)); //changes led state delay (pwm/factor); digitalWrite(led, !digitalRead(led)); //changes led state delay (pwm/factor); digitalWrite(led, !digitalRead(led)); //changes led state } } ///super delayyyy blink void BlinkLedSuper (int led, int interval, int array, int pwm){ if (((long)millis() - previousMillis[array]) >= interval){ previousMillis[array]= millis(); //stores the millis value in the selected array digitalWrite(led, !digitalRead(led)); //changes led state delay (pwm/factor); digitalWrite(led, !digitalRead(led)); //changes led state delay (pwm/factor); digitalWrite(led, !digitalRead(led)); //changes led state delay (pwm/factor); digitalWrite(led, !digitalRead(led)); //changes led state delay (pwm/factor); digitalWrite(led, !digitalRead(led)); //changes led state delay (pwm/factor); digitalWrite(led, !digitalRead(led)); //changes led state delay (pwm/factor); digitalWrite(led, !digitalRead(led)); //changes led state delay (pwm/factor); digitalWrite(led, !digitalRead(led)); //changes led state delay (pwm/factor); digitalWrite(led, !digitalRead(led)); //changes led state } } ++++ ==== Synth fm avec 5 potentiomètres avec MOZZI ==== On controle un synthe fm avec 5 potards, le son passe par la led en pin 9... ++++ Le code | /* Use 5 Analogic inputs to control fm synth (A0 - ... - A4 ) Output Pin 9 - led ... */ #include #include // oscillator #include // table for Oscils to play #include #include // maps unpredictable inputs to a range // int freqVal; // desired carrier frequency max and min, for AutoMap const int MIN_CARRIER_FREQ = 22; const int MAX_CARRIER_FREQ = 440; const int MIN = 1; const int MAX = 10; const int MIN_2 = 1; const int MAX_2 = 15; // desired intensity max and min, for AutoMap, note they're inverted for reverse dynamics const int MIN_INTENSITY = 700; const int MAX_INTENSITY = 10; // desired mod speed max and min, for AutoMap, note they're inverted for reverse dynamics const int MIN_MOD_SPEED = 10000; const int MAX_MOD_SPEED = 1; AutoMap kMapCarrierFreq(0,1023,MIN_CARRIER_FREQ,MAX_CARRIER_FREQ); AutoMap kMapIntensity(0,1023,MIN_INTENSITY,MAX_INTENSITY); AutoMap kMapModSpeed(0,1023,MIN_MOD_SPEED,MAX_MOD_SPEED); AutoMap mapThis(0,1023,MIN,MAX); AutoMap mapThisToo(0,1023,MIN_2,MAX_2); const int KNOB_PIN = 0; // set the input for the knob to analog pin 0 const int LDR1_PIN=1; // set the analog input for fm_intensity to pin 1 const int LDR2_PIN=2; // set the analog input for mod rate to pin 2 const int LDR3_PIN=3; const int LDR4_PIN=4; Oscil aCarrier(COS2048_DATA); Oscil aModulator(COS2048_DATA); Oscil kIntensityMod(COS2048_DATA); int mod_ratio = 5; // brightness (harmonics) long fm_intensity; // carries control info from updateControl to updateAudio // smoothing for intensity to remove clicks on transitions float smoothness = 0.95f; Smooth aSmoothIntensity(smoothness); void setup(){ Serial.begin(115200); // set up the Serial output so we can look at the light level startMozzi(); // :)) } void updateControl(){ // freqVal = map(LDR3_PIN, 0, 1023, 1, 100); int freqVal = mozziAnalogRead(LDR3_PIN); // value is 0-1023 int FRQ = mapThis(freqVal); int knob2 = mozziAnalogRead(LDR4_PIN); // value is 0-1023 int knob2Val = mapThis(knob2); // read the knob int knob_value = mozziAnalogRead(KNOB_PIN); // value is 0-1023 // map the knob to carrier frequency int carrier_freq = kMapCarrierFreq(knob_value); //calculate the modulation frequency to stay in ratio int mod_freq = carrier_freq * mod_ratio * FRQ; // set the FM oscillator frequencies aCarrier.setFreq(carrier_freq); aModulator.setFreq(mod_freq); // read the light dependent resistor on the width Analog input pin int LDR1_value= mozziAnalogRead(LDR1_PIN); // value is 0-1023 // print the value to the Serial monitor for debugging int LDR1_calibrated = kMapIntensity(LDR1_value); // calculate the fm_intensity fm_intensity = ((long)LDR1_calibrated * knob2Val * (kIntensityMod.next()+128))>>8; // shift back to range after 8 bit multiply // read the light dependent resistor on the speed Analog input pin int LDR2_value= mozziAnalogRead(LDR2_PIN); // value is 0-1023 Serial.print("LDR0 = "); Serial.print(knob_value); Serial.print("\t"); // prints a tab Serial.print("LDR1 = "); Serial.print(LDR1_value); Serial.print("\t"); // prints a tab Serial.print("LDR2 = "); Serial.print(LDR2_value); Serial.print("\t"); // prints a tab Serial.print("LDR3 = "); Serial.print(freqVal); Serial.print("\t"); // prints a tab Serial.print("LDR4 = "); Serial.print(knob2); Serial.print("\t"); // prints a tab // use a float here for low frequencies float mod_speed = (float)kMapModSpeed(LDR2_value)/1000; kIntensityMod.setFreq(mod_speed); Serial.println(); // finally, print a carraige return for the next line of debugging info } int updateAudio(){ long modulation = aSmoothIntensity.next(fm_intensity) * aModulator.next(); return aCarrier.phMod(modulation); } void loop(){ audioHook(); } ++++ ==== Code pour communiquer avec PureData COMPORT (2 led branché en 9 et 10): ==== On controle ainsi deux pins avec tone depuis Pure Data... **Patch PureData :** voir fichier 4 dans la page ressource [[http://reso-nance.org/wiki/logiciels/serial/accueil?s[]=puredata&s[]=serial]] ++++ Le code | String inputString = ""; // chaine de caractères pour contenir les données boolean stringComplete = false; // pour savoir si la chaine est complète String fct =""; String arg=""; int index; #include Tone freq1; Tone freq2; void setup() { Serial.begin(9600); // port série freq1.begin(9); freq2.begin(10); } void loop() { if (stringComplete) { //Serial.println(inputString); index = inputString.indexOf(' '); // on récupère la position du séparateur (l'espace " ") fct = inputString.substring(0,index); // on coupe la chaine en deux : la fonction et l'argument arg = inputString.substring(index,inputString.length()); if (fct == "LED10") { freq2.play(arg.toInt(),300); } else if (fct == "LED9") { freq1.play(arg.toInt(),300); } inputString = ""; // vide la chaine stringComplete = false; } } /* SerialEvent est déclenché quand de nouvelles données sont reçues. Cett routine tourne entre chaque loop(), donc utiliser un delay la fait aussi attendre */ void serialEvent() { while (Serial.available()) { char inChar = (char)Serial.read(); // Récupérer le prochain octet (byte ou char) inputString += inChar; // concaténation des octets if (inChar == '\n') { // caractère de fin pour notre chaine stringComplete = true; } } } ++++ ==== Code sympa fluctuant Mozzi ==== 2 pot volume et pitch ++++ Le code | #include #include // oscillator template #include // sine table for oscillator const char KNOB_PIN = 0; // set the input for the knob to analog pin 0 const char LDR_PIN = 1; // set the input for the LDR to analog pin 1 // use: Oscil oscilName (wavetable), look in .h file of table #included above Oscil aSin(SIN2048_DATA); byte volume; void setup(){ startMozzi(); // :)) } void updateControl(){ // read the potentiometer int knob_value = mozziAnalogRead(KNOB_PIN); // value is 0-1023 // map it to an 8 bit volume range for efficient calculations in updateAudio volume = knob_value >> 2; // 10 bits (0->1023) shifted right by 2 bits to give 8 bits (0->255) // read the light dependent resistor int light_level = mozziAnalogRead(LDR_PIN); // value is 0-1023 light_level = map(light_level,0,1023,0,12); light_level = light_level*100 + 200; // set the frequency aSin.setFreq( light_level); } int updateAudio(){ // cast char output from aSin.next() to int to make room for multiplication return ((int)aSin.next() * volume) >> 8; // shift back into range after multiplying by 8 bit value } void loop(){ audioHook(); // required here delay(100); } ++++ ==== Theremin fluctuant Mozzi ==== 2 pot (selecteur si pot ou ldr pour controler le pitch, pitch ) un ldr (pitch).... ++++ Le code | /* */ #include #include // oscillator template #include // sine table for oscillator #include #include #define INPUT_PIN 0 // analog control input #define INPUT_PINA 2 // analog control input #define MIX_PIN 3 // analog control input unsigned int echo_cells_1 = 32; unsigned int echo_cells_2 = 60; unsigned int echo_cells_3 = 127; int bumpy_input = 12; #define CONTROL_RATE 64 ControlDelay <128, int> kDelay; // 2seconds // oscils to compare bumpy to averaged control input Oscil aSin0(SIN2048_DATA); Oscil aSin1(SIN2048_DATA); Oscil aSin2(SIN2048_DATA); Oscil aSin3(SIN2048_DATA); // use: RollingAverage myThing RollingAverage kAverage; // how_many_to_average has to be power of 2 int averaged; void setup(){ kDelay.set(echo_cells_1); startMozzi(); } void updateControl(){ int mix = mozziAnalogRead(MIX_PIN); int pot = mozziAnalogRead(INPUT_PINA) ; int ldr = mozziAnalogRead(INPUT_PIN) ; if (mix > 500) { bumpy_input = ldr; } else { bumpy_input = pot; } averaged = kAverage.next(bumpy_input); aSin0.setFreq(averaged); aSin1.setFreq(kDelay.next(averaged)); aSin2.setFreq(kDelay.read(echo_cells_2)); aSin3.setFreq(kDelay.read(echo_cells_3)); } int updateAudio(){ return 3*((int)aSin0.next()+aSin1.next()+(aSin2.next()>>1) +(aSin3.next()>>2)) >>3; } void loop(){ audioHook(); } ++++ ===== Matériaux et outils ===== Liste de matériel et outils nécessaires. ===== Photos ===== Code pour afficher les images du projet : {{gallery>?&crop&lightbox}}