Arxiu de la categoria: Audio programming

diatonicbaixos v1.0: ajuda per als baixos de l’acordió diatònic

La Maria està estudiant l’acordió diatònic (i de passada jo també m’hi he enganxat). Una de les coses que sempre he trobat difícils és la coordinació de la mà dreta (amb la que toquem la melodia) i la mà esquerra (els baixos). Igual que passa amb el piano, que sempre m’ha semblat difícil tocar amb les dues mans alhora.

Aquí va un petit programa per ajudar a posar la mà esquerra en l’acordió diatònic. Mentre sona la melodia (es necessita el fitxer midi de la melodia), per pantalla es mostren les posicions dels baixos que s’han de tocar (en l’acordió diatònic hi ha 8 botons per als baixos/acords, que sonen diferent si obres o tanques la manxa). Quan es mostra un botó en color verd vol dir que s’ha de tancar la manxa; en color vermell s’ha d’obrir.

Per a la interfície gràfica s’ha utilitzat la llibreria ncurses, que és la primera vegada que programava en aquesta llibreria (i estic molt content del resultat obtingut). El programa és un client de JACK (el servidor d’audio per a Linux, www.jackaudio.org), i de fet és el time master, és a dir, controla el transport. Per utilitzar l’aplicatiu el millor és llençar el script bash que es proporciona, diatonicbaixos.sh, on es posa de manifest tota la cadena de programes que s’utilitzen.

Primer de tot canvio el tempo desitjat al fitxer midi mitjançant el script change_tempo_smf (es proporciona el codi font). Tot seguit s’arrenca el servidor JACK, i el sintetitzador fluidsynth, que és el que farà sonar la melodia. Després arrenquem la utilitat jack-smf-player, que s’encarregarà de fer sonar la melodia. També arrenco el klick, que és un metrònom client de JACK. Finalment ja puc llençar la meva aplicació, diatonicbaixos. El resultat, com es veu en el video, és que sona la melodia mentre es van mostrant les posicions dels baixos. Es pot canviar el tempo, es pot habilitar o no el metrònom, i hi ha un altre paràmetre amb el qual es mostra el següent baix que s’haurà de pitjar.

Per fer-se una idea del funcionament del programa el millor és veure el video:

Descarrega diatonicbaixos v1.0

Jugant amb la FFT

>Fa ja molt de temps (realment molt de temps) que estudiava la Transformada de Fourier (http://en.wikipedia.org/wiki/Fourier_transform) a la facultat, i fins i tot vaig utilitzar l’algorisme de la FFT (Fast Fourier Transform, http://en.wikipedia.org/wiki/Fast_Fourier_transform) en un aplicatiu escrit amb C per a processament digital d’imatges. Des d’aleshores ençà que no m’havia preocupat de la FFT i realment ho tenia molt oblidat.

Aquests dies he tornat a la càrrega amb la FFT doncs, amb la idea d’aprendre les tècniques de programació d’aplicacions d’audio, volia fer o un afinador o un analitzador de la potència espectral d’un senyal, que fos compatible amb JACK.

Primer de tot he mirat quin algorisme de FFT es podria utilitzar, amb llicència GPL, i ràpidament he vist que la tria seria FFTW (http://www.fftw.org/):

FFTW is a C subroutine library for computing the discrete Fourier transform (DFT) in one or more dimensions, of arbitrary input size, and of both real and complex data (as well as of even/odd data, i.e. the discrete cosine/sine transforms or DCT/DST). We believe that FFTW, which is free software, should become the FFT library of choice for most applications.

M’he posat a compilar uns quants exemples i familiaritzar-me amb els càlculs. En definitiva jo el que vull és calcular la potència espectral d’un senyal d’audio, per tant el senyal d’entrada seran unes mostres reals (una sola dimensió). La sortida de la FFT seran uns valors complexos, i he de tenir en compte tant la part real com la part imaginària per tal de calcular la potència espectral.

fftPlan = fftwf_plan_dft_r2c_1d(fftSize, fftIn, fftOut, FFTW_MEASURE); //r2c_1d: real to complex, one dimension

Mirant si hi ha algun afinador de codi lliure, que treballi per la consola, i compatible amb JACK, m’he trobat amb aquests dos projectes, que precisament utilitzen la llibreria FFTW:

i també m’ha sigut últil per fer el meu propi codi el projecte capture_client:

He dividit el problema en dues parts:

  • Primer de tot capturo el senyal que prové del micròfon, i com a resultat obtinc dos fitxers: el fitxer de so wav i un fitxer de text on fico un número suficient de mostres.
  • Segon: obro el fitxer de mostres, aplico una finestra de Hanning a les mostres com és habitual, calculo la FFT, calculo la potència espectral del senyal, i obtinc un fitxer de sortida per a ser processat amb la utilitat de creació de gràfics gnuplot (http://www.gnuplot.info/).

No havia treballat mai amb gnuplot, que seria l’equivalent a Matlab per al món Linux. Veient la demo de gnuplot que es distribueix amb el codi font, i que mostra de forma ràpida totes les possibilitats de gnuplot, m’he quedat realment sorprès. En el meu cas dibuixar el gràfic és molt fàcil:

$ gnuplot
gnuplot> plot “data_440_trumpet_output.txt”

La prova que presento s’ha gravat amb mini teclat Casio SK-8, un mini-teclat dels anys 80, escollint el so de trompeta, i obtinc el següent resultat.

Casio SK-8 440Hz (A) trumpet, 44100 fps by joanillo

Ara vull comparar el resultat dels meus càlculs amb els obtinguts amb Audacity i Ardour, per comprovar que els càlculs són correctes:

Els meus càlculs i Gnuplot Audacity Ardour

Perfecte! L’he clavat!

jcapture: gravar el so del micro a un fitxer wav

jcapture és un petit programa desenvolupat amb C++ que capta el senyal del micròfon i escriu un fitxer d’audio amb format wav. Bàsicament és un client de JACK que es connecta automàticament a system:capture_1, que és el port físic que representa l’entrada del micro de la targeta de so, i mitjançant la llibreria libsndfile va escribint les dades del micro en el buffer del fitxer d’audio.

A més, mostra el nivell del senyal d’entrada de forma gràfica en la consola (doncs és un programa que funciona per la consola, no té interfície gràfica). Si t’interessa la programació de l’API de JACK pots descarregar jcapture:

jplay-sndfile: una aplicació educativa per a Processament Digital del Senyal

jplay-sndfile és una aplicació que he estat programant la última setmana i que té un caràcter didàctic. Bàsicament és un reproductor de fitxers d’àudio, que a més pot aplicar un canvi de freqüència, i també pot fer un escombrat continu de freqüències sobre la mostra d’àudio. És un client de JACK (el servidor d’audio de Linux), i està basat com a punt de partida en sndfile-jackplay que es troba dins les utilitats de la llibreria libsndfile (http://www.mega-nerd.com/libsndfile/tools/#jackplay).

Per tothom és sabut que quan es reprodueix un fitxer d’àudio al doble de la freqüència dura la meitat de temps. Seria equivalent a agafar una mostra de cada dues, i reproduir-les a la mateixa freqüència de mostreig original.

Ara anem a fer el cas contrari, volem dividir la freqüència per dos, i el temps que durarà la reproducció hauria de ser el doble. Per fer-ho, el més fàcil és doblar cada mostra en dues, i reproduir-ho a la freqüència de mostreig original.

Aquests dos casos especials, multiplicar per dos i dividir per dos, són els casos fàcils i més evidents. Un anàlisi d’aquests casos i estudiar el codi proporcionat pot aclarir molts conceptes per als estudiants del Processament Digital del Senyal. Ara bé, més difícil és fer freqüències intermitges entre 0.5 i 2; i més difícil encara és fer un escombrat continu de freqüencies en un rang determinat. Tot això és el que es pot veure i es pot estudiar en aquesta aplicació que té un caràcter didàctic.

La sortida de l’ajuda del programa proporciona la següent informació:

$ jplay-sndfile -h

jplay-sndfile 1.00
Created by Joan Quintana Compte (joanillo)
joanqc arroba gmail.com – www.joanillo.org
Licensed under GPL v.3

jplay-sndfile is a JACK client intended for playing audio files (wav) and pitch shifting, written basically for learning, testing and educational purposes, and the first stage for future developments. A part of playing an audio file, you can change the pitch (between *0.5 and *2) of your audio file, you can play the audio file combing the pitch between two ranges. For testing is useful a sine wave, but remember that you can use any mono (one channel) audio files.
This Jack Audio client connects automatically to system:playback_1 and system:playback_2

usage: jplay-sndfile [-h] [[pitch-shift] | [pitch-shift-start pitch-shift-end]] wav-file

\t-h –help: this usage information
\t[pitch-shift] (0.5,2): shifting pitch
\t[pitch-shift-start] (0.5,2): shifting pitch start range
\t[pitch-shift-end] (0.5,2): shifting pitch end range
\twav file: mono channel audio file
\t

\tExamples:
\t./jplay_sndfile samples/hellosine.wav
\t./jplay_sndfile 0.65 samples/hellosine.wav
\t./jplay_sndfile 0.5 2 samples/hellosine.wav

La mostra d’audio que es presenta vol ser un compendi de què pot fer jplay-sndfile, i contempla els següents casos:

  • ./jplay_sndfile samples/test_44100.wav
  • ./jplay_sndfile .5 samples/test_44100.wav
  • ./jplay_sndfile .8 samples/test_44100.wav
  • ./jplay_sndfile 1.4 samples/test_44100.wav
  • ./jplay_sndfile 2 samples/test_44100.wav
  • ./jplay_sndfile .5 2 samples/test_44100x3.wav
  • ./jplay_sndfile samples/sine_440_44100.wav
  • ./jplay_sndfile .5 1 samples/square_440_44100.wav
  • ./jplay_sndfile 1 2 samples/saw_440_44100.wav
  • ./jplay_sndfile .5 samples/waves.wav
  • ./jplay_sndfile 2 samples/waves.wav

jplay-sndfile-examples by joanillo

Una de les coses més interessants és estudiar la funció callback de la API de JACK, que ha quedat bastant petita, i on està tot el moll de l’os de l’aplicació. Bàsicament la funció callback() la crida el servidor d’àudio cada vegada que la interfície d’àudio (la targeta de so hardware) necessita omplir el seu buffer amb dades.

static int process (jack_nframes_t nframes, void * arg)
{

\tjack_default_audio_sample_t buf ;
\tunsigned int i;
\touts = (jack_default_audio_sample_t *)jack_port_get_buffer (output_port, nframes) ;

\tinfo_t *info = (info_t *) arg;
\t
\tmemcpy (outs_original, buffer2 + frames_counter_original, sizeof (jack_default_audio_sample_t) * nframes * DOUBLE_SAMPLES * 2);

\tint k=0;
\tfloat k2;
\tk2 = nframes/info->shift_pitch;
\tfloat var, var2 = 0;
\tint part_entera = 0;
\tvar = 1/info->shift_pitch – 1;

\tfor (i = 0 ; i < nframes ; i++)
\t{\t

\t\tif (info->shift_pitch < 1) {
\t\t\tif (frames_counter + i >= info->numFrames / shift_pitch_equivalent) { // shift_pitch_equivalent = info.shift_pitch quan no faig un escombrat
\t\t\tinfo->play_done=1;
\t\t\treturn 0;
\t\t\t}
\t\t} else { // >= 1
\t\t\tif (frames_counter_original + i >= info->numFrames * DOUBLE_SAMPLES) {
\t\t\tinfo->play_done=1;
\t\t\treturn 0;
\t\t\t}
\t\t}
\t\t
\t\tif (info->shift_pitch > 1) {
\t\t\tk=(int)(i*DOUBLE_SAMPLES*info->shift_pitch + .5);
\t\t\touts[i] = outs_original[k];\t
\t\t} else if (info->shift_pitch <= 1) {
\t\t\touts[k] = outs_original[i*DOUBLE_SAMPLES];
\t\t\tif ((int)var2 != part_entera) {
\t\t\t\touts[k+1] = outs_original[i*DOUBLE_SAMPLES+1];
\t\tpart_entera = int(var2);
\t\tk++;
\t\t\t}
\t\t\tvar2 = var2 + var;
\t\t\tk++;\t\t\t
\t\t}

\t}
\tframes_counter += nframes;
\tframes_counter_original += nframes * DOUBLE_SAMPLES * info->shift_pitch ;
\t
\treturn 0 ;
} /* process */

I per a què serveix tot això? És una aplicació didàctica, serveix sobretot per aprendre:

  • per aprendre: teoria del Processamet del Senyal
  • per aprendre: API de libsndfile
  • per aprendre: API de JACK, exemple de com funciona la funció de callback

però a part d’aprendre, s’ha desenvolupat amb una idea en ment, que ha de ser el següent projecte: utilitzar una tauleta gràfica Wacom, les que fan servir els dissenyadors gràfics, per produir sons realístics, sensibles al moviment i a la pressió del llapis, però això serà el següent projecte: Reconeixement real de gestos amb la wacom i Síntesi d’àudio

Wacom Theremin

El Theremin és un instrument inventat per Léon Theremin el 1918 que té la particularitat de què es toca amb els gestos de les mans. Està considerat un dels primers instruments electrònics, i el seu so sintètic i característic s’ha utilitzat moltes vegades per a pel·lícules de ciència ficció i efectes especials.

En aquest projecte s’implementa la manera de tocar i el so d’un theremin amb un controlador poc convencional: una tauleta gràfica Wacom de les que fan servir els dissenyadors gràfics. Si saps com es toca un theremin la implementació és evident: amb l’eix x canvies el to (Pitch Bend amb terminologia MIDI; amb l’eix y canvies el volum; i clar: apretar el llapis produeix el so de la nota (missatge MIDI NoteOn) i aixecar el llapis apaga la nota (NoteOff). A més de la posició XY, la tecnologia wacom proporciona altres sensors que donen informació com és la pressió i la inclinació. Encara que no s’ha fet en aquest projecte, es podria haver associat la pressió i la inclinació a altres missatges MIDI CC (Continuous Controller) com ara la modulació (efecte de vibrato).

S’ha utilitzat un sintetitzador Roland JV-2080 per tal de produir un so de Theremin, tot i que no estic molt content amb el resultat obtingut. Allò bo del JV-2080 és que té un espai de memòria per guardar els patch d’usuari i motls paràmetres, oscil·ladors i efectes per poder anar jugant si tens suficient temps. I el que és millor del JV-2080 és que pots configurar el pitch bend (variació del to) amb una amplitud molt gran, també configurable, cosa que normalment no passa en altres sintes (sobretot els sintes software).

Una de les coses que m’ha agradat més del projecte és la integració de l’aplicació desenvolupada amb llenguatge C (hi ha l’enllaç per descarregar el codi més avall) amb Gimp (l’editor d’imatges i fotos de referència en el món Linux). Això dóna peu a múltiples possibilitats i idees per fer projectes que combinin Gimp amb efectes sonors i interactius.

Evidentment, la idea no és nova, hi ha altra gent que ha fet Theremins amb wacom’s i altres controladors com la Wii, però en el projecte 50 Ways to Play Una Plata d’Enciam no podia faltar un Wacom Theremin fet exclusivament amb eines de Codi Lliure.

smf_parser v1.01: SMF (Standard Midi File) Parser


jplayfine (http://wiki.joanillo.org/index.php/Jplayfine) és un projecte musical que estic desenvolupant, que consisteix en poder fer un play-along sobre un fitxer midi (fitxer SMF), i que puguis obtenir una nota relacionada amb la similitud entre el que has tocat i el que se suposa que has de tocar. Per fer-ho, el programa ha de saber en quin canal està la melodia en el teu fitxer midi, i per quin canal toca el teu controlador midi. jplayfine és un client JACK que conviu bé dins de l’ecosistema de les aplicacions d’àudio i midi per a Linux.
Bé, parlaré del jplayfine en una altra ocasió.

Tot i que jplayfine utilitza un seqüenciador extern per fer sonar el fitxer midi (les proves les estic fent amb jack-smf-player), el tema és que desenvolupant el projecte jplayfine m’he trobat amb la necessitat de parsejar el fitxer midi que conté la melodia i l’acompanyament. Podia utilitzar la llibreria smf.h que utilitza jack-smf-player. La veritat és que, amb els objectius de buscar la simplicitat, tenir el màxim control del codi, i entendre amb profunditat el format MIDI, m’he embarcat en fer un parsejador de SMF amb C++. Aquí va la versió 1.01, per si algú se la vol mirar. D’una
banda hi ha una aplicació standalone; i d’altra banda hi ha la llibreria i una aplicació de test que mostra com utilitzar la llibreria. També hi ha una carpeta midi/ amb els midifiles que s’han utilitzat per testejar. Per utiltizar la llibreria necessites un compilador C++ per a Linux (g++).

Enllaç del projecte: http://wiki.joanillo.org/index.php/Fitxers_MIDI_(SMF)._Format#smf_parser
Informació sobre el protocol MIDI: http://www.sonicspot.com/guide/midifiles.html
Descarregar smf_parser1.01