Archives par mot-clé : minim

Analyse audio et l’utilisation de données FFT

L’animation d’images synchronisées sur une musique est un procédé reconnu et utilisé depuis longtemps tant dans le VJing que dans les divers domaines de l’animation. De nombreux outils comme after effect nous permettent de synchroniser, de manière automatique ou plus maîtrisée, une animation sur un son, il en est de même avec les outils de creative coding.
Processing permet, par l’utilisation de la librairie Minim, de jouer et analyser un son. Les valeurs récupérées peuvent ensuite être utilisées de manière différente comme dans l’exemple ci-dessous où l’analyse audio permet de gérer la déformation d’un mesh 3D ou le comportement d’un flocon de neige.

Nous verrons ici comment utiliser la librairie Minim et créer un objet nous permettant de récupérer l’amplitude des bandes FFT (issues de la transformation de Fourier) afin d’animer des objets.

Analyse audio et les FFT

Lorsque nous écoutons un son nous entendons les diverses notes jouées. Cependant lorsque nous analysons un son, ce dernier n’est pas représenté en terme de notes mais en amplitudes/temps.
D’une manière simple, l’amplitude à un instant T d’un son correspond à son volume à ce même instant T. Si nous souhaitons représenter un son nous obtenons alors le graphique suivant :

son-amplitude-01-01

Nous pouvons facilement utiliser l’amplitude d’un son comme valeur pour une animation. Dans l’exemple suivant nous avons mappé la valeur y d’une ellipse sur l’amplitude de notre musique.
Pour ce faire, nous avons utilisé after effect afin de convertir les données audio en keyFrame afin de pouvoir lire cette amplitude. Nous avons ensuite mappé la valeur y de notre objet à l’aide de l’expression suivante.

Nous obtenons alors l’animation suivante :

Dans le cas d’une animation simple cela pourrait nous suffir, mais dans le cadre d’un clip génératif par exemple nous souhaitons obtenir plus de variations et pouvoir différencier des notes, des graves ou des aïgues. Pour ce faire nous allons utiliser la transformée de Fourier. La transformée de Fourier est une fonction inventée par Jean Baptiste Joseph Fourier permettant de transformer un spectre en fréquences. Dans notre cas nous allons nous en servir pour transposer l’amplitude de notre son en fréquences Hertz.

Un son est composé d’un ensemble de fréquences Hertz, chacun de ces hertz aura une amplitude différente. Si nous traçons cela nous obtenons le graphique suivant (pour l’instant T, l’amplitude des fréquence changeant à chaque instant)

son-hertz-01-01

Cependant on pourrait se demander en quoi cela nous intéresse de transformer l’amplitude d’un son en fréquence.
Il faut savoir que chaque son possède une fréquence majeure, il s’agit de la fréquence dont l’amplitude sera la plus haute. Chaque son étant différent il est alors possible d’isoler pour chacun d’entre un leur fréquence majeure, cela devient leur empreinte. On peut donc facilement reconnaître une note par sa fréquence majeure, ainsi la fréquence d’un La (octave 2) sera de 220hz.
Evidemment dans le cadre d’une musique, il faut prendre en compte le fait que plusieurs instruments joueront en même temps, il sera donc très difficile d’extraire une note exacte par sa fréquence puisque nous obtenons l’amplitude des fréquences pour l’ensemble des instruments enregistrés.

Un autre élément intéressant des fréquences est leur ordre croissant. Les fréquences audible par l’homme vont en moyenne de 3 hz à 22 000 hz, et il est intéressant de savoir que les sons associés aux fréquences les plus basses sont les sons graves contre les sons aux fréquences hautes qui seront les plus aiguës. Les fréquences peuvent donc nous aider à obtenir des variations tant sur les graves, les médiums que les aiguës. Ils nous offrent alors beaucoup de possibilités en terme d’animation.

Nous avons vu, dans les grandes lignes, ce que nous pouvons analyser d’un son. Passons à la pratique en essayant d’extraire les données de notre musique à l’aide de processing.

L’utilisation d’une librairie intégrée dans processing

Processing ne gère pas de manière « native » la lecture/analyse d’un son. Pour se faire nous allons utiliser une librairie intégrée : Minim. Il s’agit d’une librairie dédiée au traitement de son et permettant à la fois la gestion, lecture, écriture, analyse d’un son. Cette librairie fait depuis longtemps partie du package processing étant donné ses grandes capacités. Minim étant une librairie nous aurons besoins de l’importer dans notre skecth afin de pouvoir accéder à ses méthodes. Pour se faire nous utilisons le code suivant :

Création d’une classe FFTObject – variables et constructeur

Afin de faciliter l’analyse des fréquences tout au long de notre code nous allons créer un objet que nous appellerons fftObject. Cet objet nous permettra à la fois de charger et jouer un son mais aussi d’accéder à l’analyse des bandes FFT de ce même son.

Nous aurons besoins de divers objets liés à la librairie Minim, à savoir :

  • Un objet minim de type Minim permettant de gérer l’ensemble des objets de chargement, lecture et analyse d’un son
  • Un objet music de type AudioPlayer afin de lire notre musique
  • Un objet fft de type FFT afin de réaliser et utiliser la transformée de fourier

Nous aurons ensuite besoins de la variable suivant :

  • Une variable timeSize définissant la taille du buffer de notre son à analyser

Nous pouvons donc commencer à créer notre classe fftObject de la manière suivante :

Passons maintenant au constructeur de notre objet.
Nous allons définir notre variable timeSize à 1024. Il s’agit de la taille du buffer dédié au son. Le buffer est une mémoire tampon, il permet de stocker à l’avance les données du son devant être lues. Ce buffer nous servira lors de l’initialisation de l’objet music.

Nous devons ensuite initialiser notre objet minim de la manière suivante :

Nous remarquons l’ajout d’une variable parent, celle-ci correspond au contexte. En effet lors de son initialisation l’objet minim a besoins de connaitre le contexte dans lequel il va être appelé. Dans notre cas il s’agit de notre application processing. Si nous avions initialisé notre objet dans le setup, nous aurions utilisé la variable this permettant de cibler notre application comme étant le contexte.
Puisque nous somme dans un objet, la variable this ne cible plus l’application comme contexte mais l’objet en lui même. Il nous faudra alors la passer dans notre objet lors de son initialisation. Pour ce faire nous avons ajouté au constructeur une variable parent de type PApplet.

Nous pouvons ensuite initialisé l’objet music. Ce dernier aura besoins de l’url de notre son à jouer ainsi que de la taille du buffer que l’application devra lui allouer.

L’objet fft aura aussi besoins de la taille du buffer ainsi que la fréquence à laquelle la musique a été échantillonné. Cette dernière valeur nous est donnée par l’objet music à l’aide de la méthodes suivante :

Nous obtenons donc pour l’objet fft

Enfin, une fois l’ensemble de nos objets construit nous lançons la lecture de notre son à l’aide de la méthode suivante

Nous obtenons alors, pour notre classe fftObject le constructeur suivant :

Création d’une classe FFTObject – les méthodes

Une fois notre constructeur défini nous avons besoins de créer les diverses méthodes dont notre objet aura besoins. Dans notre cas nous avons besoins des méthodes suivantes :

  • Une méthode getFFTLevel nous renvoyant l’amplitude d’une fréquence souhaitée
  • Une méthode displayFFT permettant de dessiner les amplitudes de chacune de nos fréquences sous forme d’égaliseur

Commençons par la méthode getFFTLevel, celle-ci sera relativement simple.
Nous allons utiliser une méthode de type float. Les méthodes typées (float, int, boolean…) sont des méthodes renvoyant des variables une fois exécutée.

Si on écrit :

Alors x sera égale à valeur
Dans notre cas nous souhaitons pouvoir connaitre l’amplitude d’une bande i et ceux à n’importe quel endroit de notre code. Nous allons donc créer une méthode nous permettant par la suite de dire :

où x sera égale à la valeur de l’amplitude de la fréquence i.

Cette méthode getFFTLevel se composera alors de la manière suivante :

Nous allons désormais définir la méthode displayFFT. Celle-ci nous permettra d’afficher sous forme d’égaliseur les amplitudes de nos fréquences.
Nous aurons besoins de passer diverses variables dans cette méthode, à savoir :

  • la position x de notre égaliseur
  • la position y de notre égaliseur
  • la hauteur maximum heightBande de nos fréquences
  • le nombre nbBandes de fréquences voulues (de nombreuses fréquences n’étant pas couvertes ou non présentes dans notre échantillons nous n’aurons pas besoins de dessiner les 22000 hertz)

enfin à l’aide d’une boucle for nous dessinerons l’ensemble de nos fréquences. Cela nous donnera :

Utilisation de notre class FFTObject

Maintenant que nous avons créé notre classe FFTObject il ne nous reste plus qu’à l’utiliser. Dans notre feuille principale nous allons déclarer un objet fftObj de type FFTObject ainsi qu’une variable parent de type PApplet.

Nous initialisons l’ensemble de nos variables et objets dans notre setup

Nous pouvons désormais dessiner notre égaliseur dans notre boucle draw() à l’aide de la méthode suivante

De la même manière nous pouvons dessiner un lot de 20 ellipses dont la taille pourra varier en fonction de bandes FFT comprises en 0 et 20.

Ils ne vous reste plus qu’à expérimenter à votre tour à créer votre propre application réactive au son.

taille

Bibliographie

Ce cours a été réalisé à l’aide des informations suivantes :

Amplitude et Décibels, Topos générals préliminaires sur l’audio numérique.

Transformation de Fourier

Définition des Hertz

Notes de musique et correspondance en fréquences hertz

échantillonage d’un son

Minim, références