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.3jplay-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_2usage: 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
- Descarregar jplay-sndfile
- enllaç del projecte a la wiki