Dimanche, 10 mai

Nous avons essentiellement terminé notre projet, ayant complété la majorité de nos buts. L’application contient maintenant quatre tambours, dont une cymbale, un tom, un hi-hat et un snare, qui sont tous interchangeables et remplaçables. Il suffit simplement de se rendre dans le fichier data du fichier Airdrum et de changer les fichiers audio .mp3 ou de changer leurs noms. Cependant, on doit conserver les noms des fichiers audio existants, sinon on doit les changer à l’intérieur du code aussi. Nous avons trouvé que ce projet a testé nos connaissances de programmation. Bien sûr, sans le changement de plans nécessaire, il y aurait eu beaucoup plus de physique et de mathématiques à réaliser, mais nous avons fait notre possible pour en conserver le plus possible.

Voici une vidéo explicative sur notre projet:

Ci-dessous se retrouve le code écrit en Java contenu dans le logiciel Processing, si vous voulez simplement télécharger le projet au complet, rendez vous sur le site principal et cliquez sur le bouton pour télécharger ce dernier.

/* ATTENTION: Attendre deux secondes avec les 
couleurs devant la webcam avant de frapper. */

/* Pour un meilleur fonctionnement, utiliser 
une webcam sans balance des blancs automatique. */

import processing.video.*;
import processing.sound.*;
import lord_of_galaxy.timing_utils.*;

// Pour capturer la vidéo de la webcam
Capture video;

// Fichiers de sons
SoundFile snareFile;
SoundFile crashFile;
SoundFile tomFile;
SoundFile hihatFile;

// Couleur rouge et bleue
color trackColorRed;
color trackColorBlue;
float thresholdRed = 125; // changer ces valeurs pour trouver les meilleures
float thresholdBlue = 80;  // selon votre caméra et votre éclairage

// Tambours (instruments)
boolean snareSound = true;
boolean crashSound = true;
boolean tomSound = true;
boolean hihatSound = true;

// Pour stocker les valeurs de Y pendant 1 seconde
ArrayList<Float> listAvgYRed = new ArrayList<Float>(59);
float frameRed = 0;
ArrayList<Float> listAvgYBlue = new ArrayList<Float>(59);
float frameBlue = 0;

// Pour le temps
boolean timeRestartRed = true;
Stopwatch timeRed = new Stopwatch(this);
boolean timeRestartBlue = true;
Stopwatch timeBlue = new Stopwatch(this);

// Vitesse à laquelle vous allez jouer
float playSpeed = 10;

void setup() {
  // Détermine la taille de l'écran pour visionner la vidéo de la webcam
  size(640, 480);
  
  // Fait une liste des caméras, vous devez choisir la vôtre
  String[] cameras = Capture.list();
  // printArray(cameras);
  video = new Capture(this, cameras[1]);  // (choisissez l'indice de la caméra ici)
  
  // Fichiers de sons
  snareFile = new SoundFile(this, "snare.mp3");
  crashFile = new SoundFile(this, "cymbal.mp3");
  tomFile = new SoundFile(this, "tom.mp3");
  hihatFile = new SoundFile(this, "hihat.mp3");
  
  // Commence l'enregistrement de la webcam
  video.start();
  
  // Ce sont les couleurs à reconnaître (changez si vous avez d'autres couleurs)
  trackColorRed = color(255,0,0);  // en code RGB, donc 0 à 255
  trackColorBlue = color(14, 138, 209);  // exemple: jaune -> (255, 255, 0)
}

void captureEvent(Capture video) 
{
  // Permet de lire la vidéo
  video.read(); 
}

void draw(){
  // Pour transmettre la vidéo à l'écran
  video.loadPixels();
  
  // Pour la vidéo avec effet miroir
  pushMatrix();
  translate(width,0);
  scale(-1,1);
  image(video, 0, 0, width, height);  // affiche la vidéo
  popMatrix();
  
  // Pour le rouge
  float avgXRed = 0;
  float avgYRed = 0;
  int countRed = 0;
  
  // Pour le snare
  rect(540, 300, 100, 100);
  
  // Pour le hi-hat
  rect(420, 300, 100, 100);
  
  // On trouve la concentration de rouge dans la vidéo
  for (int x = 0; x < video.width; x++) {
    for (int y = 0; y < video.height; y++){
      int locRed = x + y*video.width;
      color currentColor = video.pixels[locRed];
      float r1 = red(currentColor);
      float g1 = green(currentColor);
      float b1 = blue(currentColor);
      float rRed = red(trackColorRed);
      float gRed = green(trackColorRed);
      float bRed = blue(trackColorRed);
      float dRed = dist(r1, g1, b1, rRed, gRed, bRed);
      
      if (dRed < thresholdRed){
        avgXRed += x;
        avgYRed += y;
        countRed++;
      }
    }
  }
  
  // Pour le bleu
  float avgXBlue = 0;
  float avgYBlue = 0;
  int countBlue = 0;
  
  // Rectangle de la cymbale
  rect(0, 300, 100, 100);
  
  // Rectangle du tom
  rect(120, 300, 100, 100);
  
  // On trouve la concentration de bleu dans la vidéo
  for(int x = 0; x < video.width; x++) {
    for(int y = 0; y < video.height; y++) {
      int locBlue = x + y*video.width;
      color currentColor = video.pixels[locBlue];
      float r2 = red(currentColor);
      float g2 = green(currentColor);
      float b2 = blue(currentColor);
      float rBlue = red(trackColorBlue);
      float gBlue = green(trackColorBlue);
      float bBlue = blue(trackColorBlue);
      float dBlue = dist(r2, g2, b2, rBlue, gBlue, bBlue);
      
      if (dBlue < thresholdBlue){
        avgXBlue += x;
        avgYBlue += y;
        countBlue++;
      }
    }
  }
  
      // Pour le rouge
      if (countRed > 0 ) 
      {
        // On positionne un cercle où la moyenne du rouge est situé dans l'écran
        avgXRed = avgXRed / countRed;
        avgYRed = avgYRed / countRed;
      
        // On rempli les rectangles et le cercle de rouge
        fill(trackColorRed);
        strokeWeight (4.0);
        stroke(0);
        
        // Pour suivre le rouge avec x inversé
        ellipse(-avgXRed +width,avgYRed,16,16);
        
        // On ajoute la position à la liste de valeurs Y de rouge
        listAvgYRed.add(avgYRed);
        frameRed++;
        
        // À chaque fois que le frame spécifié est enregistré
        if (frameRed % playSpeed == 0 && timeRestartRed == true)
        {  
           timeRed.start();  // on commence le timer
           timeRestartRed = false;
        }
        
        // Si une frappe de snare est détectée
        if(snareSound == true && avgYRed>=300 && avgYRed<=400 && avgXRed<=105)
        {
          // Calcule la vitesse de la frappe
          float distance = 300 - listAvgYRed.get(56); // 0.06 sec avant la frappe
          float temps = timeRed.time();  // temps écoulé depuis le 56ième frame
          float vitesse = (distance/temps) * 100;  /* fois 100 pour avoir des
                                                      plus gros ratios */
          // Frappe plus forte
          if (vitesse >= 10)
          {
            snareFile.amp(1);
          }
          
          // Frappe moins forte
          if (vitesse < 10)
          {
            snareFile.amp(0.3); 
          }
          
          // Joue le son du snare
          snareFile.play();
          snareSound = false;
          
          // Permet de recommencer le timer
          timeRestartRed = true;
        }
        
        // Après une frappe de snare
        if(snareSound == false && avgYRed<=300)
        {
          snareSound = true;  // permet de refrapper le snare
        }
        
        // Si une frappe de hihat est détectée
        if(hihatSound == true && avgYRed>=300 && avgYRed<=400 && avgXRed<=225 && avgXRed>=115)
        {
          // Calcule la vitesse de la frappe
          float distance = 300 - listAvgYRed.get(56); // 0.06 sec avant la frappe
          float temps = timeRed.time();  // temps écoulé depuis le 56ième frame
          float vitesse = (distance/temps) * 100;  /* fois 100 pour avoir des
                                                      plus gros ratios */
          // Frappe plus forte
          if (vitesse >= 10)
          {
            hihatFile.amp(0.6);
          }
          
          // Frappe moins forte
          if (vitesse < 10)
          {
            hihatFile.amp(0.1); 
          }
          
          // Joue le son du hi-hat
          hihatFile.play();
          hihatSound = false;
          
          // Permet de recommencer le timer
          timeRestartRed = true;
        }
        
        // Après une frappe de hihat
        if (hihatSound == false && avgYRed<=300)
        {
           hihatSound = true;  // permet de refrapper le hihat 
        }
      }
      
  // Si la liste de valeurs du Y du rouge est plein
  if (listAvgYRed.size() >= 59)
  {
    listAvgYRed.remove(0);  // on enlève le premier élément
  }
      
      // Pour le bleu
      if (countBlue > 0) 
      {
        // On positionne un cercle où la moyenne du bleu est situé dans l'écran
        avgXBlue = avgXBlue / countBlue;
        avgYBlue = avgYBlue / countBlue;
      
        // On rempli les rectangles et le cercle de bleu
        fill(trackColorBlue);
        strokeWeight(4.0);
        stroke(0);
        
        // Pour suivre le bleu avec x inversé
        ellipse(-avgXBlue + width, avgYBlue, 16, 16);
        
        // On ajoute la position à la liste de valeurs Y de bleu
        listAvgYBlue.add(avgYBlue);
        frameBlue++;
        
        // À chaque fois que le frame spécifié est enregistré
        if (frameBlue % playSpeed == 0 && timeRestartBlue == true)
        {  
           timeBlue.start();  // on commence le timer
           timeRestartBlue = false;
        }
        
        // Si une frappe de cymbale est détectée
        if (crashSound == true && avgYBlue>=300 && avgYBlue<=400 && avgXBlue>=535)
        {
          // Calcule la vitesse de la frappe
          float distance = 300 - listAvgYBlue.get(56); // 0.06 sec avant la frappe
          float temps = timeBlue.time();  // temps écoulé depuis le 56ième frame
          float vitesse = (distance/temps) * 100;  /* fois 100 pour avoir des
                                                      plus gros ratios */
          // Frappe plus forte
          if (vitesse >= 10)
          {
            crashFile.amp(0.8);
          }
          
          // Frappe moins forte
          if (vitesse < 10)
          {
            crashFile.amp(0.2); 
          }
          
          crashFile.play();  // on joue le son du crash (cymbale)
          crashSound = false;
          
          // Permet de recommencer le timer
          timeRestartBlue = true;
        }
        
        // Après la frappe de cymbale
        if (crashSound == false && avgYBlue<=300)
        {
          crashSound = true;  // permet de refrapper la cymbale
        }
        
        // Si une frappe de tom est détectée
        if (tomSound == true && avgYBlue>=300 && avgYBlue<=400 && avgXBlue<=525 && avgXBlue>=415)
        {
          // Calcule la vitesse de la frappe
          float distance = 300 - listAvgYBlue.get(56); // 0.06 sec avant la frappe
          float temps = timeBlue.time();  // temps écoulé depuis le 56ième frame
          float vitesse = (distance/temps) * 100;  /* fois 100 pour avoir des
                                                      plus gros ratios */
          // Frappe plus forte
          if (vitesse >= 10)
          {
            tomFile.amp(0.8);
          }
          
          // Frappe moins forte
          if (vitesse < 10)
          {
            tomFile.amp(0.2); 
          }
          
          tomFile.play();  // on joue le son du tom
          tomSound = false;
          
          // Permet de recommencer le timer
          timeRestartBlue = true;
        }
        
        // Après la frappe de tom
        if (tomSound == false && avgYBlue<=300)
        {
          tomSound = true;  // permet de refrapper le tom
        }
      }
      
  // Si la liste de valeurs du Y du rouge est plein
  if (listAvgYBlue.size() >= 59)
  {
    listAvgYBlue.remove(0);  // on enlève le premier élément
  }
}

Laisser un commentaire

Concevoir un site comme celui-ci avec WordPress.com
Commencer