---
title: "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](https://processing.org/reference/libraries/sound/index.html)

# Preparación

## 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.

## 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.

# 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.

```java
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.


# 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.

## 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()`.

```java
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);
}
```

## 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.

```java
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);
  
}
```


# 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*.

## 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.

```java
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()
```

## 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.

```java
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()
```
