Peinture Poesie Musique

Alètheia ( ἀλήθεια )

Espace programmation

Première page Page précédente Page suivante Dernière page

Base SFML

Projet SpaceMeter64 - présentation

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

SpaceMeter64

Archive

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.

  • DspFaust.cpp et DspFaust.h concerne le contrôleur des entrées audios
  • spaceMeter64.cpp est l'interface proposée au DSP
  • spaceMeter64 et spaceMeter sont des exécutables.
  • Le dossier renferme les images nécessaires au fonctionnement de l'application.

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 ` 

spaceMeter64 - le code

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 :

SFML boucle

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

Ces adresses sont passées au DSP qui retourne la valeur associée à chacune:

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.

License

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

Première page Page précédente Page suivante Dernière page