jardínBit

Proyecto Final: Audio Visualizer

Utiliza Processing y las herramientas del semestre de Código Creativo para crear una visualización de audio animada que consista en al menos tres estados distintos.

Aprovecha las estrategias de repetición y de diseño paramétrico, y las herramientas de transformación multimedia (texto y sonido) para generar y explorar comportamientos complejos en diálogo con el sonido.

Algunas preguntas para tu consideración:

Realiza el proyecto individualmente o en parejas.

1 Requerimientos técnicos

Duración mínima de la visualización en su totalidad: 1 minuto.

Desde el punto de vista del código, considera cómo los temas del semestre pueden ayudar en tu composición:

Importante: no utilices/copies códigos que no hayas escrito tú o que no estén basados en los materiales de clase, en especial cuando contengan conceptos computacionales y/o geométricos que no puedas explicar al resto del grupo.

1.1 Opcional, pero recomendable

2 Entrega

La entrega del proyecto consistirá en tres partes:

2.1 Avances del proceso

Publica en el foro del Proyecto Final tus referencias, avances, bocetos, código, resultados, dudas, comentarios, etc. al final de cada sesión de trabajo.

Es indispensable que tengas un post por cada sesión de workshop del proyecto

2.2 Presentación en vivo

Presentarás tu proyecto al grupo en la última sesión del curso, el lunes 6 de junio de 2022.

En primer lugar presentarás la visualización en acción, corriendo desde Processing.

Después, utiliza unos 5 minutos para compartirnos:

2.3 Dossier en PDF + Video

Complementa tu presentación con un dossier en PDF a entregar a más tardar en la última sesión del curso, en la sección correspondiente de Actividades.

Adjunta además un video de la visualización en funcionamiento: Lo más recomendable es que lo subas a tu cuenta de YouTube de Centro.

Incluye en el dossier:

Puedes utilizar este dossier como apoyo visual para tu presentación en vivo

3 Workshop

Durante las sesiones de workshop tendremos tiempo para trabajar en el proyecto, resolver dudas individuales o grupales, asesorar posibles soluciones, repasar temas de ser necesario, y documentar los avances en el notebook correspondiente.

Para cualquier duda fuera del horario de clase, entre semana, escríbeme a jvegac arroba centro.edu.mx

4 Posibles referencias

5 Plantillas de código interactivo

En la página de Visualización de audio hay varias opciones para realizar gráficos que responden al sonido:

5.1 Dibuja algo distinto según el estado

Este código dibuja una figura distinta según la última tecla que fue presionada:

void setup(){
    size(800, 600);
}

void draw(){
    background(0);
   
    if( key == '1' ){
        noStroke();
        square( 350, 250, 100);
    }
    else if( key == '2' ){
        noStroke();
        circle( 400, 300, 100);
    }
    else if( key == '3') {
        stroke(255);
        strokeWeight(5);
        line(0,300,  800, 300);
    }

}

5.1.1 Con funciones

Este código es similar pero las acciones a realizar en cada estado se encuentran en sus propias funciones:

void setup(){
    size(800, 600);
}

void draw(){
    background(0);
   
    if( key == '1' ){
        uno();
    }
    else if( key == '2' ){
        dos();
    }
    else if( key == '3') {
        tres();
    }

}

void uno(){
    noStroke();
    square( 350, 250, 100);
}

void dos(){
    noStroke();
    circle( 400, 300, 100);
}

void tres(){
    stroke(255);
    strokeWeight(5);
    line(0,300,  800, 300);
}

5.1.2 Con análisis de amplitud

Este ejemplo utiliza visualización de amplitud en las funciones para que cada estado tenga gráficos que responden al sonido.

En las notas de audio hay más información de cómo funciona la visualización de amplitud:

import processing.sound.*;

SoundFile sonido;
Amplitude amplitud;

void setup() {
  size(640, 480);

  sonido = new SoundFile( this, "audio.mp3");
  sonido.play();

  amplitud = new Amplitude(this);
  amplitud.input( sonido );
}

void draw() {
  background(255);
  strokeWeight(5);
  
  if( key == '1'){
    uno();
  }
  else if (key == '2'){
   dos(); 
  }

}

void uno(){
  float d = amplitud.analyze(); // rango: de 0 a 1
  // dibujo de un círculo con diámetro que va de 0 a 500
  float diametro = d*500;
  circle( 320, 240, diametro);
}

void dos(){
  float d = amplitud.analyze(); // rango: de 0 a 1
  // dibujo de un círculo con posición en X que va de 0 a 640
  float x = d*640;
  circle( x, 240, 100);
}

5.2 Cambio de estado con eventos

Estos ejemplos se parecen a los de arriba, pero el cambio de estado sucede dentro de los eventos keyPressed() o mousePressed().

Esta plantilla ayuda para cuando queremos que algo suceda justo al cambiar de estado, y no durante el estado.

5.2.1 Teclado

Usa los condicionales dentro de keyPressed() para realizar las acciones que quieres que sucedan al iniciar dicho estado. Por ejemplo, puedes usar la plantilla para iniciar la reproducción del sonido al presionar alguna tecla.

int estado = 1; // estado inicial

void setup() {
  size( 800, 600 );
}

void draw() {
  background(0);
  if ( estado == 1 ) {
    noStroke();
    square(350, 250, 100);
  } else if ( estado == 2 ) {
    noStroke();
    circle(400, 300, 100);
  } else if ( estado == 3 ) {
    stroke(255);
    strokeWeight(5);
    line(0, 300, 800, 300);
  }
} // cierra draw()

void keyPressed() {
  if ( key == '1' ) {
    // inicia estado 1
    estado = 1;
  } else if ( key == '2' ) {
    // inicia estado 2
    estado = 2;
  } else if ( key == '3' ) {
    // inicia estado 3
    estado = 3;
  }
} // cierra keyPressed

5.2.2 Mouse

Este ejemplo es muy parecido al de arriba, pero aquí se usa el evento mousePressed() para cambiar al siguiente estado.

Nota el uso del condicional para regresar al estado inicial.

Lo que sucede dentro de mousePressed() podrías agruparlo en otro condicional que haga que las acciones sucedan solo cuando las coordenadas del mouse (mouseX y mouseY) se encuentren dentro de cierto rango.

int estado = 1; // estado inicial

void setup() {
  size( 800, 600 );
}

void draw() {
  background(0);
  if ( estado == 1 ) {
    noStroke();
    square(350, 250, 100);
  } else if ( estado == 2 ) {
    noStroke();
    circle(400, 300, 100);
  } else if ( estado == 3 ) {
    stroke(255);
    strokeWeight(5);
    line(0, 300, 800, 300);
  }
} // cierra draw()

void mousePressed(){
  estado = estado + 1; // siguiente estado
  if( estado > 3 ){
   estado = 1; 
  }
} // cierra mousePressed

5.3 Cambio de estado con el tiempo

Esta plantilla utiliza el método .position() de SoundFile para cambiar de estado de acuerdo a la posición de la playhead del archivo de sonido, en segundos.

import processing.sound.*;
SoundFile sonido;

void setup() {
  size(640, 480);

  sonido = new SoundFile( this, "audio.mp3");
  sonido.play();
  //sonido.loop(); // equivalente a play() pero repitiendo la reproducción
  //sonido.jump(60); // "salta" al segundo 60
}

void draw() {
  background(0);

  // si tiempo es menor a 3
  if ( sonido.position() < 3 ) {
    // sucede entre 0 y 2.9999
    square( 320, 240, 100);
  }
  else if ( sonido.position() < 6 ) {
    // sucede entre 3 y 5.9999
    circle( 320, 240, 100);
  }
  else if ( sonido.position() < 9 ) {
    // sucede entre 6  y 8.999
    stroke(255);
    strokeWeight(5);
    line( 0, 240, width, 240);
  }
}

5.4 Modifica un parámetro con el teclado

Este código utiliza una variable global que corresponde a la separación entre elementos repetidos. Esa variable es decrementada o incrementada con las teclas ‘j’ y ‘k’ respectivamente.

Esta plantilla te puede servir de base para modificar otros parámetros de una manera similar.

float separacion = 80; // separación entre círculos

void setup(){
    size(800, 600);
}
void draw(){
    background( 0 );
    stroke(255);
    strokeWeight(10);
    noFill();

    for( float x=0; x<=width; x+= separacion ){
        circle( x, 300, 50);
    }
}

void keyPressed(){ // se realiza cuando una tecla se presiona
    if( key == 'j' ){
        separacion -= 10; // decrementa la separación
    }
    else if( key == 'k' ){
        separacion += 10;
    }
} 

5.5 Modifica un parámetro con el mouse

Este código utiliza a la variable mouseX como parámetro del ciclo for correspondiente al límite de las repeticiones.

void setup(){
    size(800, 600);
}
void draw(){
    background( 0 );
    stroke(255);
    strokeWeight(10);
    noFill();

    for( float x=0; x<= mouseX; x+= 50 ){
        circle( x, 300, 50);
    }
}