SFML permet de construire rapidement des interfaces très réactives parfaitement adaptées aux flux audios.
Dans ce document je me contenterai de présenter une première application qui permet de rendre compte visuellement de l'intensité relative de 64 canaux dans un espace 3D. Pour ce faire j'utilise un langage spécifique dédié aux applications audios :
le langage Faust.
La présentation de ce langage est proposée sur une page dédié.
La première chose à faire est de décompresser l'archive des sources dans un dossier. Vous obtenez 5 fichiers et un dossier d'images.
Ce programme est sous licence GNU General Public License. Voir plus loin.
J'utilise une adaptation de l'exemple dbmeter donné sur le site de Grame dans la rubrique "Analysis" . Vous n'avez pas besoin de comprendre comment fonctionne ce code pour compiler le programme proposé. La génération des fichiers DspFaust.cpp et DspFaust.h est expliquée ailleurs. Pour compiler ce code vous devez vous placer dans votre terminal dans le dossier où vous avez décompressé l'archive et ensuite taper la ligne de commande suivante :
g++ DspFaust.cpp spaceMeter64.cpp -o spaceMeter64 -lsfml-graphics
-lsfml-window -lsfml-system `pkg-config --cflags --libs jack `
Une application SFML repose sur l'ouverture d'une ou plusieurs fenêtres disposant de son propre gestionnaire d'événements et d'une boucle de gestion des objets graphiques. Cela se présente ainsi :
#include <SFML/Graphics.hpp>
#include <iostream>
#include <stdlib.h>
#include "DspFaust.h"
using namespace std;
int main()
{
DspFaust *dspFaust = new DspFaust();
dspFaust->start();
cout << "Faust is Running =" << dspFaust->isRunning()<< endl;
// Start the game loop
while (window.isOpen()){
// Process events
sf::Event event;
while (window.pollEvent(event))
{
// Close window: exit
if (event.type == sf::Event::Closed){
dspFaust->stop();
cout << "Faust is Running =" << dspFaust->isRunning()<< endl;
window.close();
}
}
// Clear screen
window.clear();
window.draw(bkgimage);
.....
}
window.display();
}
return EXIT_SUCCESS;
}
Dans un premier temps, il est nécessaire de procéder à l'initialisation d'un certain nombre de variables. Ceci ce fait avant la boucle générale de la fenêtre.
Dans le cadre de ce projet, un tableau permet de définir le positionnement de chaque projecteur de son (enceinte) sur l'image d'arrière-plan suivant un codage des entrées bien précis (voir le schéma de référence du studio 64):
float enc[64][3];
enc[0][0]=258; // première enceinte : coordonnée x
enc[0][1]=222; // : coordonnée y
enc[0][2]=-76; // : gain;
Pour disposer correctement les entrée audios (64), j'utilise une image d'arrière plan afin de donner l'illusion de l'espace 3D.
sf::Texture image; // je commence par charger une image comme texture
if (!image.loadFromFile("./images/volume.png"))
return EXIT_FAILURE; // cette texture est affecté.
sf::Sprite bkgimage(image);// à un sprite nommé bkgimage.
Comme je souhaite symboliser l'intensité du son j'utilise 7 images :
sf::Texture texture1;
if (!texture1.loadFromFile("./images/g4971.png"))
return EXIT_FAILURE;
sf::Sprite sprite1(texture1);
sf::Texture texture2;
if (!texture2.loadFromFile("./images/path4488.png"))
return EXIT_FAILURE;
sf::Sprite sprite2(texture2);
sf::Texture texture3;
if (!texture3.loadFromFile("./images/path4487.png"))
return EXIT_FAILURE;
sf::Sprite sprite3(texture3);
sf::Texture texture4;
if (!texture4.loadFromFile("./images/path4486.png"))
return EXIT_FAILURE;
sf::Sprite sprite4(texture4);
sf::Texture texture5;
if (!texture5.loadFromFile("./images/path4489.png"))
return EXIT_FAILURE;
sf::Sprite sprite5(texture5);
sf::Texture texture6;
if (!texture6.loadFromFile("./images/path4490.png"))
return EXIT_FAILURE;
sf::Sprite sprite6(texture6);
sf::Texture texture7;
f (!texture7.loadFromFile("./images/path4485.png"))
return EXIT_FAILURE;
sf::Sprite sprite7(texture7);
Un tableau résume les commandes de lecture des informations du DSP fournit lors de la compilation du DSP et contenu dans le fichier README.md.
encAdd[0]="/Meter/0/0x56447ad09bb0";
encAdd[1]="/Meter/1/0x56447ad0e980";
encAdd[10]="/Meter/10/0x56447ad3c5c0";
encAdd[11]="/Meter/11/0x56447ad41480";
encAdd[12]="/Meter/12/0x56447ad46420";
encAdd[13]="/Meter/13/0x56447ad4b490";
......
dspFaust->getParamValue(encAdd[i])
Dans la boucle principale de la fenêtre, je définis les paramètres des images (nature et dimension avec ajustement de la position) correspondants aux 64 entrées du DSP:
for(int i=0;i<64;i++){
enc[i][2]=dspFaust->getParamValue(encAdd[i]);
if (enc[i][2]<-50){
sprite1.setPosition(sf::Vector2f(enc[i][0]-2, enc[i][1]-2));
window.draw(sprite1);
}
if (enc[i][2]>-50 && enc[i][2]<-40){
sprite2.setPosition(sf::Vector2f(enc[i][0]-15, enc[i][1]-15));
window.draw(sprite2);
}
if (enc[i][2]>-40 && enc[i][2]<-35){
sprite3.setPosition(sf::Vector2f(enc[i][0]-20, enc[i][1]-20));
window.draw(sprite3);
}
if (enc[i][2]>-35 && enc[i][2]<-25){
sprite4.setPosition(sf::Vector2f(enc[i][0]-25, enc[i][1]-25));
window.draw(sprite4);
}
if (enc[i][2]>-25 && enc[i][2]<-20){
sprite5.setPosition(sf::Vector2f(enc[i][0]-35, enc[i][1]-35));
window.draw(sprite5);
}
if (enc[i][2]>-20 && enc[i][2]<-10){
sprite6.setPosition(sf::Vector2f(enc[i][0]-45, enc[i][1]-45));
window.draw(sprite6);
}
if (enc[i][2]>-10){
sprite7.setPosition(sf::Vector2f(enc[i][0]-64, enc[i][1]-64));
window.draw(sprite7);
}
}
Ce code est très simple, mais efficace et ne consomme pas trop de ressource DSP. La simplicité de connexion au DSP Faust est déconcertante.
La structure des fenêtres SFML est également remarquable pour ce genre d'application.
Vous disposez également d'un fichier "spaceMeter" qui contient 3 lignes :
#!/bin/bash
cd ~/bin/spaceMeter64
./spaceMeter64
afin de pouvoir créer un lanceur sur le bureau sans passer par un terminal.
L'utilisation de ce programme exige que Jack soit actif. Par ailleurs il appartient à chacun d'assurer la connexion des entrées à dbmeter en fonction de la structure de son studio. Voir cette page.
This Architecture section is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; If not, see http://www.gnu.org/licenses.
EXCEPTION : dbmeter license : "BSD".