RPIJERS: Raspberry Pi Internet Jazz European Radio Stations


Vols escoltar jazz tot el sant dia? A Internet tens bastant per escollir, per exemple, http://www.listenlive.eu/jazz.html. En aquest projecte hem indexat totes aquestes estacions de radio per escoltar-les d’una forma simple i amb una interfície mínima. I això ho hem aconseguit amb la Blackberry Pi. Només necessitem alimentar-la, endollar-la a un cable de xarxa, connectar-la a un amplificador, i un botó que ens serveix per arrencar el servei mpd (Music Player Daemon) i per seleccionar fins a 40 canals.

Pots descarregar-te de la wiki (http://wiki.joanillo.org/index.php/Raspberry_Pi:_Internet_Ràdio) el bash script i el fitxer amb la llista de totes les emissores. Si vols que el sistema funcioni de forma totalment desatesa has de fer que el script arrenqui en l’inici del sistema. L’electrònica necessària és mínima, crec que en el video queden clares les connexions, i si no a la wiki hi ha més informació (encara que en català).

Us desitjo un feliç 2013 i molt de jazz! Aquí va el vídeo:

Programant amb GIMP II. Pintar pixels a la pantalla

La veritat és que no hi ha molta informació i exemples per programar plugins amb GIMP. Però el cert és que la llibreria està ben documentada i s’entén força ràpid si un està familiaritzat amb la programació d’altres APIs i els conceptes de GIMP (capes, brushes,…).

GIMP Library Reference Manual:

A mode d’exemple anem a fer allò que considerem més bàsic: pintar pixels individuals sobre la pantalla. De l’enllaç anterior fem un repàs a les diferents possibilitats que ens ofereix la llibreria i ens fixem en la següent entrada:

gimppixelfetcher — Functions for operating on pixel regions:

i aquí tenim unes poques funcions, concretament la que necessitarem per pintar pixels és

void gimp_pixel_fetcher_put_pixel (GimpPixelFetcher *pf,
gint x,
gint y,
const guchar *pixel);

el primer argument és un punter a un objecte GimpPixelFetcher que hem inicialitzat prèviament.

\tGimpPixelFetcher *pf;
\tpf = gimp_pixel_fetcher_new (drawable,FALSE);

S’inicialitza a partir del drawable, que representa la capa sobre la que volem pintar. Per tant aquest punter ens dóna un espai de memòria que podem associar a un pixel d’una capa.

Els arguments x, y són evidenment les coordenades on volem escriure el pixel.

Finalment el punter *pixel conté la informació del pixel, concretament les 3 components del color.

Seguidament mostrem la funció principal pintar_pixel() del nostre plugin, que el que fa és pintar 5 pixels per pantalla, en les posicions (20,0),…, (24,0). El codi (fitxer gimp_pixel_fetcher_put_pixel.c) el pots descarregar a la wiki, tot i que està una mica brut. El primer pixel tindrà el mateix color que el foreground que tinc seleccionat en aquell moment; per al segon pixel estableixo un color amb la funció gimp_rgb_set(); el tercer pixel serà igual que el pixel de la posició (0,0), utilitzo la funció gimp_pixel_fetcher_get_pixel(); per als quart i cinquè pixel fico directament les coordenades RGB del color.

Per compilar:

$ gimptool-2.0 –install gimp_pixel_fetcher_put_pixel.c

i el codi:

static void pintar_pixel (GimpDrawable *drawable)
{
\tGimpPixelFetcher *pf;
\tgint x1, y1;
\tguchar *px; //pixel is an array of bpp bytes.
\tGimpRGB color;

\tx1=0;
\ty1=0;

\tpf = gimp_pixel_fetcher_new (drawable,FALSE);
\tpx = g_new (guchar, 1);

\t//1. escric un pixel amb el color del foreground
\tgimp_context_get_foreground (&color);
\t//g_message (“%d,%d,%d”,(int)(&color)->r,(int)(&color)->g,(int)(&color)->b);
\tpx[0] = 255*(&color)->r; //vermell (0-255)
\tpx[1] = 255*(&color)->g; //verd (0-255)
\tpx[2] = 255*(&color)->b; //blau (0-255)
\tgimp_pixel_fetcher_put_pixel (pf, x1+20, y1, px);

\t//2. escric un pixel i dic quin color vull amb la funció gimp_rgb_set
\tgimp_rgb_set (&color, 0.0, 1.0, 1.0);
\tpx[0] = 255*(&color)->r; //vermell (0-255)
\tpx[1] = 255*(&color)->g; //verd (0-255)
\tpx[2] = 255*(&color)->b; //blau (0-255)
\tgimp_pixel_fetcher_put_pixel (pf, x1+21, y1, px);

\t//3. escric un pixel igual que el de la posició (0,0)
\tgimp_pixel_fetcher_get_pixel (pf,x1, y1, px);
\t//g_message (“%d,%d,%d”,(int)px[0],(int)px[1],(int)px[2]); //puc obtenir informació del pixel (components RGB)
\tgimp_pixel_fetcher_put_pixel (pf, x1+22, y1, px);

\t//4. escric un pixel i dic quin color vull
\tpx[0] = 255; //vermell (0-255)
\tpx[1] = 0; //verd (0-255)
\tpx[2] = 0; //blau (0-255)
\tgimp_pixel_fetcher_put_pixel (pf, x1+23, y1, px);
\t// o bé
\t*px=0; //vermell (0-255)
\t*(px+1)=0; //verd (0-255)
\t*(px+2)=255; //blau (0-255)
\tgimp_pixel_fetcher_put_pixel (pf, x1+24, y1, px);

\tg_free (px);

\tgimp_pixel_fetcher_destroy (pf);

\tgimp_drawable_flush (drawable);
\tgimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
\tgimp_drawable_update (drawable->drawable_id,20,0,5,1);

}

Programant amb GIMP I. Executar plugins des de la consola

Amb aquest article vull encetar una sèrie de posts sobre la programació amb GIMP. No és un tutorial per aprendre a programar GIMP, tan sols és posar en ordre unes quantes idees enfocades a un futur projecte, que bàsicament és desenvolupar un framework per poder explicar històries tot dibuixant sobre la pantalla amb una wacom, i on es succeeixin múltiples efectes visuals i sonors. Si aquesta sèrie de posts s’acaba, en l’últim podrem veure com es toca una melodia on el pentagrama està dibuixat sobre el GIMP i les notes les dibuixo amb el ratolí o la wacom.

Primer de tot necessitem les llibreries de desenvolupament del GIMP:

$ sudo apt-get install libgimp2.0-dev

i aprenem a programar un plugin a partir d’un tutorial que si cerques per Google segur que trobes:

Amb aquest tutorial, que implementa un blur (difuminador) aprenem els conceptes bàsics de la programació amb GIMP. Els nostres plugins els programarem amb llenguatge C. Per compilar el plugin farem:

$ gimptool-2.0 –install myblur.c

Per executar el plugin ho farem des de dins del GIMP amb Filtres > Difumina > My Blur. O també ho podem fer amb un script Script-Fu: Filtres > Script-Fu > Consola

(plug-in-myblur run-mode image drawable)

on substituim run-mode, image i drawable pels valors correctes. Per exemple:

(plug-in-myblur RUN-NONINTERACTIVE 1 2)

Però a mi el que m’interessa és executar plugins des de fora del GIMP, des de la consola. La primera manera de fer-ho és amb el llenguatge de script propi del GIMP, el llenguatge Scheme.

example_script.scm:

(
define (example-script inputFilename outputFileName)
(
let* (
(image (car (gimp-file-load RUN-NONINTERACTIVE inputFilename inputFilename)))
(drawable (car (gimp-image-get-active-layer image)))
)
(plug-in-myblur RUN-NONINTERACTIVE image drawable)
(gimp-file-save RUN-NONINTERACTIVE image drawable outputFileName outputFileName)
)
)

Els script l’he de guardar en la carpeta de scripts del GIMP: ~/.gimp-2.6/scripts. Per executar-lo puc invocar al GIMP en mode comanda (opció -b):

$ gimp -i -b “(example-script \\”confirmacion.jpg\\” \\”confirmacion_out.jpg\\”)” -b “(gimp-quit 0)”
batch command executed successfully

Però encara no em convenç aquesta manera de fer. Jo el que vull és poder aplicar un plugin a una imatge oberta del GIMP, executant el plugin des de la consola, no des de dins del GIMP. I la clau està en saber que el GIMP té un servidor, el servidor Script-Fu, que treballa per defecte pel port 10008 i que escolta les peticions TCP que li vénen de la xarxa (socket). Primer de tot hem d’arrencar el servidor:

Filtres > Script-Fu > Inicia el servidor

i efectivament puc connectar-me al servidor:

$ telnet localhost 10008

però això no serveix de res si no sé el protocol per comunicar-me amb aquest servidor. Aquest protocol està explicat en aquest enllaç:

no és un protocol difícil d’entendre o implementar. Per sort, al Google trobem el script servertest.py que implementa aquest protocol. Per exemple el podem trobar en un d’aquests enllaḉos:

Ara ja puc executar el meu plugin des de la shell:

$ python servertest.py
Trying ::1.
Trying 127.0.0.1.
Script-Fu-Remote – Testclient
> (plug-in-myblur RUN-NONINTERACTIVE 1 2)
(OK): Success
>

servertest.py treballa de forma interactiva. No em convenç. Faig una modificació de manera que pugui treballar de forma totalment desatesa: script servertest_v2.py (http://wiki.joanillo.org/index.php/Programaci%C3%B3_GIMP#Servidor_Script-Fu)

$ python servertest_v2.py localhost 10008 “(plug-in-myblur RUN-NONINTERACTIVE 1 2)”
HOST: localhost
PORT: 10008
COMMAND: (plug-in-myblur RUN-NONINTERACTIVE 1 2)
Trying ::1.
Trying 127.0.0.1.
(plug-in-myblur RUN-NONINTERACTIVE 1 2)
(OK): Success

És a dir, executo l’anterior comanda des de la consola, i de forma màgica la imatge que tinc oberta en el GIMP queda difuminada.

Ara només falta executar aquesta comanda no des de la consola, sinó des d’un executable de C, que és el meu llenguatge de referència per desenvolupar futurs projectes:

// gcc -o execute_blur execute_blur.c
int main(int argc, char *argv[])
{
\tsystem(“python servertest_v2.py localhost 10008 \\”(plug-in-myblur RUN-NONINTERACTIVE 1 2)\\””);
}

$ ./execute_blur

HOST: localhost
PORT: 10008
COMMAND: (plug-in-myblur RUN-NONINTERACTIVE 1 2)
Trying ::1.
Trying 127.0.0.1.
(plug-in-myblur RUN-NONINTERACTIVE 1 2)
(OK): Success

i la imatge que tinc oberta en el GIMP queda difuminada.

Interfície Wii Rockband drumset

L’altre dia vaig comprar al Cash Converter, per 18e, una bateria Wii de segona mà, amb la idea de fer-la sonar en el meu Ubuntu. Aquestes bateries van sortir al mercat el 2007, ara ja fa cinc anys. Evidentment hi ha altra gent que ha portat aquestes consoles a l’entorn Linux, i m’he beneficiat del codi que he trobat per aquí i per allà. Tanmateix, el codi que he trobat no era per al meu model (també existeixen versions per a PS2, PS3 i X360), així que he hagut d’esbrinar els codis que envia el drumset (amb la dificultat que quan toques les dues baquetes a l’hora, o les dues baquetes i el bombo, s’envien d’altres codis). No tenia experiència prèvia en la programació de la llibreria libusb. Utilitzant aquesta llibreria ha estat la única manera possible de detectar la força amb que colpeges la baqueta, i per tant fer una mica de control de volum, encara que amb poca resolució.

Per tal de fer sonar la bateria es necessita generar missatges MIDI i enviar-los a un sintetitzador. He utilitzat Hydrogen com a sintetitzador de sons de bateria. He programat quatre presets diferents que s’accedeixen amb els botons de la consola (els típics botons 1, 2, A i B de la Wii). S’ha fet dues versions del codi, una que utilitza ALSA de forma nadiua, i una altra per al servidor d’audio JACK. Pots descarregar-te el codi del projecte:
projecte jrbdrum

Stop motion: puzzle de 1000 peces

Només hi ha una època en la vida on fer puzzles és interessant: quan ets nen. Com el Pere, que disfruta fent el puzzle de pirates de 40 peces. Quan ets adult fer puzzles és una autèntica pèdua de temps. Dit això, jo tenia l’espina clavada doncs en el seu dia no vaig poder acabar un puzzle que corria per casa de 750 peces. M’ho devia. Així que un dia que vaig entrar al Cash&Converter vaig agafar un puzzle per 5 euros (no vaig poder triar la foto, però m’era ben bé igual), i em vaig posar a fer el puzzle a estones, igual que un nen.

Stop motion. Quantes fotos s’han de fer a mida que desmunto el puzzle? Quantes peces trec entre foto i foto? Anem a fer el petit càlcul. Si el puzzle és de 1000 peces i trec dues peces entre foto i foto són 500 fotos, que seran 500 frames del video. Si vull muntar un video a 20 fps (20 frames cada segon), sortirà un vídeo de 500f/20fps = 25 segons.

Amb un script es pot muntar el video. Primer de tot es renombren les fotos de manera que la primera passi a ser la última, i la última la primera. De manera que la última és la foto que es diu 99999.JPG. Després es tornen a renombrar de manera que la primera passi a ser la 00000.JPG, etc. I seguidament es munta el video concatenant totes les fotos. Finalment, amb l’editor de video Open Shot es posa la portada, la contraportada, la música i es fan les foses.

#!/bin/bash
#rename files in reverse
START=99999 #allows for an hour of jpegs
i=$START
for f in *.JPG
do
mv $f $i.JPG
i=$(($i -1))
echo $i
done

c=0;
for i in *.JPG;
do mv “$i” “`printf %05d $c`.JPG”;
c=$((c+1));
done

ffmpeg -r 20 -sameq -i %05d.JPG output.mp4

El resultat final:

Non, non, fillet. Cancó de bressol que em va escriure el meu pare.

Una altra cançó de bressol del meu pare. Però aquesta vegada és antiga, la va escriure per a mi fa 42 anys. Passo de posar una foto meva de quan era bebè, o sigui que poso la primera foto que he pillat en el Google Images per tal d’il·lustrar el post.

La transcripció de l’original s’ha fet amb Lilypond. S’ha reproducido amb fluidsynth a través de JACK, i s’ha grabat directament en l’Audacity. Tot això sobre GNU/Linux (Ubuntu 10.04).

La lletra:

\tNon, non, Joan, amb molta pau. Que la soneta va arribant;
\tNon, non, fillet, dorm ben aviat, tens la mareta al teu costat.

\tLes veus del dia ja s’han fos. Dorm en silenci i bon repòs;
\tNon, non, Joan, en el teu llit, que els dolços somnis van venint.

Non, non, Joan (cançó de bressol, lullaby) by joanillo

Descarrega la partitura: Non, non, fillet (escrita pel meu pare ara fa 42 anys i que em va dedicar) (JM Quintana, 1970)

Cançó de bressol (del meu pare als seus néts)


Una altra cançó de bressol del meu pare. Dedicada als seus néts (els 10 que té, el que vindrà, i els que poden venir). Entre ells la Maria i el Pere, els meus. Una cançó dolça i de melodia senzilla, sense sobresalts, com es correspon a una cançó que té per objectiu fer venir la son, cosa a vegades no gens fàcil.

Dorm, infantó, la dolça son.
noneta non canta la mare;
somnis de pau t’envoltaran;
noneta non, dins del bressol,
noneta non, canta l’amor.

Canco bressol 2 (lullabye) by joanillo

Descarrega la partitura: canco_bressol (dedicada als meus néts) (JM Quintana, 2012)

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:

Google no l’encerta a l’hora de dibuixar una funció sinus

Avui és el 155 aniversari del naixement de Heinrich Rudolf Hertz (155 no és un número gens significatiu, no tenien res millor que explicar la gent de Google?). Per il·lustrar-ho han fet una animació d’una ona sinuoidal bastant desastrosa. Tot el món sap que la derivada del sinus és el cosinus, i que per tant el pendent del sinus en l’origen val 1,

sin'(0) = cos(0) = 1

Si els eixos x i y tenen la mateixa escala vol dir que el pendent quan la funció sinus creua l’eix horitzontal ha de ser una recta de 45º. Com la funció cosinus agafa valors entre -1 i 1, el pendent en qualsevol dels punts no pot ser una recta vertical!!

Vaja, que hi ha gent que per dibuixar ones sinusoidals es dedica a enllaçar semicercles… una mica de cultura matemàtica si us plau…