jardínBit

Visualización de audio

Processing cuenta con la biblioteca Sound que nos permite realizar operaciones de reproducción y análisis de audio. En estas notas describimos algunos ejemplos básicos.

La referencia completa de la biblioteca está en el sitio de Processing: Sound / libraries / Processing.org

1 Preparación

1.1 Instalar biblioteca

Instala la biblioteca Sound desde el menú Sketch -> Importar biblioteca… -> Añadir biblioteca…, y buscando por la que se llama Sound con autoría de The Processing Foundation.

Selecciónala, presiona el botón de Install, espera a que salga el ícono de palomita verde, y listo.

1.2 Archivos de audio

Para agregar archivos de audio a nuestro sketch, tenemos dos opciones:

  1. Arrastrar los archivos desde nuestro navegador de archivos hacia la ventana del código. Veremos un mensaje de Archivo añadido con éxito
  2. Crear una carpeta de nombre data dentro de la carpeta donde está nuestro sketch, y copiar dentro de esa carpeta a nuestro archivo de audio.

Nota que la primera opción realiza en el fondo lo que está descrito en la segunda opción.

En principio la biblioteca Sound va a poder manejar archivos de tipo WAV o tipo MP3. Los archivos MP3 pueden causar problemas en algunos sistemas operativos, así que si no funcionan conviene utiliar WAV.

2 Reproducir sonido

El siguiente ejemplo muestra lo sencillo que es reproducir sonido desde un sketch de Processing.

Nota que el archivo de audio tiene que estar agregado al sketch previamente.

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(){
  
}

Puedes empezar a incorporar interactividad haciendo que la reproducción del sonido inicie pero cuando algún evento suceda, o se detenga (con .pause() o .stop()) cuando suceda algún otro.

3 Visualización de amplitud

Podemos entender a una señal de audio como el cambio a gran velocidad de una amplitud numérica que corresponde al movimiento oscilante de una bocina.

Processing Sound nos permite leer esa cantidad numérica para entonces utilizarla como parámetro de cualquier elemento de nuestros sketches.

3.1 Amplitud de archivo de sonido

Este ejemplo muestra cómo “conectar” el reproductor del archivo de sonido con un medidor de amplitud que nos permite utilizar ese valor numérico en cada cuadro animación de draw().

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);
  float d = amplitud.analyze(); // rango: de 0 a 1

  // dibujo de un círculo con diámetro que va de 100 a 600
  float diametro = d*500+100;
  circle( width/2, height/2, diametro);
}

3.2 Amplitud de micrófono

El siguiente ejemplo muestra cómo empezar a leer nuestro micrófono y cómo obtener su amplitud como parámetro numérico. En este caso ese parámetro se toma como diámetro de un círculo.

Nota las similitudes con el ejemplo anterior.

import processing.sound.*;

AudioIn in; // variable para el sonido del mic
Amplitude amplitud;

void setup(){
  size( 640, 480 );
  background( 255 );
  
  in = new AudioIn(this, 0);
  in.start();
  
  amplitud = new Amplitude(this);
  amplitud.input( in );
}

void draw(){
  background(255);
  strokeWeight(5);
  float d = amplitud.analyze(); // rango: de 0 a 1
  
  // dibuja un círculo con un diámetro que va a ir de 100 a 600
  float diametro = d*500+100;
  circle( width/2, height/2,  diametro);
  
}

4 Visualización de frecuencias

Processing Sound también nos permite hacer un análisis llamado FFT (Fast Fourier Transform) que analia la intensidad de diferentes bandas de frecuencia del sonido en reproducción.

Podemos obtener como valores numéricos las intensidades de las frecuencias bajas, medias y altas.

Estos valores numéricos son almacenados en un arreglo.

4.1 Estructura repetitiva

El siguiente ejemplo utiliza un ciclo for para dibujar una fila de círculos, donde la posición de cada uno es obtenida del valor de cada una de las 8 bandas de frecuencias medidas.

Nota: La cantidad de bandas tiene que ser una potencia del 2: 2, 4, 8, 16, 32, 64, 128, 256, etc.

import processing.sound.*;

SoundFile sonido;
FFT fft;
int bandas = 8;
float[] espectro = new float[bandas];

void setup(){
 size(1024, 480);
 
 
 sonido = new SoundFile( this, "audio.mp3");
 sonido.play();
 //sonido.jump( 60 );
 
 fft = new FFT(this, bandas);
 fft.input( sonido );
 
}

void draw(){
  // fondo parcialmente transparente
  fill(0, 10);
  rect(0, 0, width, height);

  // analiza y guarda valores en `espectro`
  fft.analyze( espectro );
  
  fill(255);
  float x = 100;
  for( int i=0; i<bandas; i++){
    float d = espectro[i]*200;
    circle( x, 240, d);
    x += 100;
  } // cierra for()
  
}// cierra draw()

4.2 Parámetros individuales

En ocasiones puede convenir no utilizar el ciclo for y más bien leer como parámetros individuales a cada elemento del arreglo.

Esto nos permite tener más flexibilidad de dónde utilizamos a cada parámetro correspondiente a cada banda de frecuencia.

import processing.sound.*;

SoundFile sonido;
FFT fft;
int bandas = 8;
float[] espectro = new float[bandas];

void setup(){
 size(800, 480);
 
 sonido = new SoundFile( this, "audio.mp3");
 sonido.play();
 //sonido.jump( 60 );
 
 fft = new FFT(this, bandas);
 fft.input( sonido );
 
}

void draw(){
  fft.analyze( espectro );
  
  // obtiene los elementos del arreglo como parámetros individuales
  float d0 = espectro[0]; 
  float d1 = espectro[1]; 
  float d2 = espectro[2];
  float d3 = espectro[3];
  float d4 = espectro[4]; 
  float d5 = espectro[5]; 
  float d6 = espectro[6];
  float d7 = espectro[7];

  
  // dibuja con algunos de esos parámetros
  background( d0*255 );
  circle( 200, 240, d1*200);
  circle( 400, 240, d2*200);
  circle( 600, 240, d3*200);
  
}// cierra draw()