Programant amb l'API de JACK
Contingut
http://dis-dot-dat.net/index.cgi?item=/jacktuts/starting/
Els fitxers amb què treballo estan a 50.../way6/jack. (aquesta podria ser una de les maneres de tocar a baix nivell, programant l'API de JACK). Segueixo
per fer el primer codi, que consisteix en tocar una nota.
$gcc -std=c99 -o playc `pkg-config --cflags --libs jack` playc.c $ ./playc hola the sample rate is now 44100/sec engine sample rate: 44100
Efectivament, veig que apareix hola en la pestanya Audio de les connexions JACK, i que està connectat al system, i escolto el Do central en la targeta de so.
Per enviar missatges MIDI (apareix el client en la pestanya MIDI del JACK) ho tinc documentat a:
També es podria fer un seqüenciador amb l'API d'ALSA, i en aquest cas el client apareixeria en la pestanya ALSA del JACK.
He estat fent bastantes proves i documentant-me, que bàsicament estan a sax_trainer/programacio_jack. midisine.c (i midisine_comentat.c), midiseq.c, simple_client. Concretament estic fent proves amb jack_bridge.c, que ha d'assentar les bases per tal que el sax_trainer el pugui connectar a un foot controller.
- http://trac.jackaudio.org/browser/trunk/jack/example-clients
- http://trac.jackaudio.org/browser/trunk/jack/example-clients/midisine.c
També seria interessant mirar:
El secret per entendre l'API de Jack és pensar una mica a baix nivell, en els buffers i la informació de buffers de memòria que s'intercanvies les aplicacions clients.
example-clients dels repositoris
jackmp significa JACK multi-processador, que és el mateix que dir JACK2, i aquesta és la diferència gran entre JACK2 i JACK1: està optimitzat per ordinadors amb multi-processador.
$ svn co http://subversion.jackaudio.org/jack/jack2/trunk/jackmp dins d'example-clients, compilo els exemples:
gcc -D jack -o showtime `pkg-config --cflags --libs jack` showtime.c ./showtime gcc -D jack -o samplerate `pkg-config --cflags --libs jack` samplerate.c ./samplerate gcc -D jack -o cpu_load `pkg-config --cflags --libs jack` cpu_load.c ./cpu_load jack DSP load 0.997674 jack DSP load 0.843427 jack DSP load 0.843836 gcc -D jack -o alias `pkg-config --cflags --libs jack` alias.c ./alias gcc -D jack -o alsa_in `pkg-config --cflags --libs jack` alsa_in.c ./alsa_inno compila llegir: *http://permalink.gmane.org/gmane.comp.audio.jackit/18384 gcc -D jack -o alsa_out `pkg-config --cflags --libs jack` alsa_out.c gcc -D jack -o bufsize `pkg-config --cflags --libs jack` bufsize.c ./bufsize buffer size = 256 sample rate = 44100 gcc -D jack -o capture_client `pkg-config --cflags --libs jack` capture_client.c no em compila gcc -D jack -o metro `pkg-config --cflags --libs jack` metro.c ./metro (és un client de JACK que és un metrònom). per a l'exemple transport.c és necessari incloure la llibreria -lreadline $ gcc -D jack -o transport -lreadline `pkg-config --cflags --libs jack` transport.c o també: $ gcc -Wall transport.c -o transport -ljack -lreadline $ ./transport transport> help activate Call jack_activate(). exit Exit transport program. deactivate Call jack_deactivate(). help Display help text [<command>]. locate Locate to frame <position>. master Become timebase master [<conditionally>]. play Start transport rolling. quit Synonym for `exit'. release Release timebase. stop Stop transport. tempo Set beat tempo <beats_per_min>. timeout Set sync timeout in <seconds>. ? Synonym for `help'. transport> play transport> stop transport> tempo 100 transport> play transport> master transport> tempo 80 transport> tempo 120 transport> stop
Què és una funció callback?
Del Synthesis ToolKit in C++ trobo una bona definició de callback:
An alternative scheme for audio input/output is to define a specific function in which audio computations are performed and to let the audio system call this function when more input/output data can be accepted by the hardware (referred to as a callback scheme). In this section, we show how the previous rtsine.cpp program can be modified to work in a callback scenario. There is no "single-sample" interface for this functionality. The callback function will be invoked automatically by the audio system controller (RtAudio) when new data is needed and it is necessary to compute a full audio buffer of samples at that time (see Blocking vs. Callbacks for further information).
La idea és que tenim un servidor d'àudio, i aquest servidor és el que s'encarrega de fer crides als clients quan detecta que el buffer de la interface està buida.
Exemples didàctics
He fet algunes aplicacions petites amb la idea d'ilustrar com es programa la API de JACK i com es poden fer coses bàsiques a nivell Audio i MIDI.
Exemples importants: realtime, ringbuffer,...(per imprimir i provar)
S'han recopilat els articles en un sol document i s'ha penjat al servidor:
- Article Time waits for nothing: http://www.rossbencina.com/code/real-time-audio-programming-101-time-waits-for-nothing
- sndfile-jackplay.c (/home/joan/projectes/jplay-sndfile). thread. Fem playback mentre llegim el fitxer. Comentaris sobre l'ús de threads a Fils/threads_amb_C++
- JACK_i_Ringbuffer: http://harryhaaren.blogspot.com/2011/11/tutorial-jack-ringbuffers.html, Circular_buffer_/_Ringbuffer
- Gravar del micro: jcapture
- Gravar del micro: capture_client.c (https://github.com/jackaudio/example-clients/blob/master/capture_client.c). Comentaris sobre l'ús de threads a Fils/threads_amb_C++
- http://harryhaaren.blogspot.com/2011/12/tutorial-load-loop-samples.html (Harry Haaren). This tutorial will show you how to load a sample into memory, and then play it back trough a JACK port, continually looping. There's not really that much to it, just a bit of thinking of the order things happen, and arrays.
- http://harryhaaren.blogspot.com/2010/06/tutorials.html
- JACK MIDI Examples
- http://harryhaaren.blogspot.com/2009/12/tut-5-callbacks-with-gtkmm.html. Callbacks with GTKmm (senyals)
- Writing Audio To File: http://harryhaaren.blogspot.com/2009/12/tut-4-writing-audio-to-file.html
- JACK tuner. http://freecode.com/projects/jack-tuner. compte!! aquest programa produciex tons, no és un afinador, i per tant no té res a veure amb la FFT. De totes maneres, pot ser interessant estudiar i compilar el codi.
capture_client.c
És un exemple important doncs mostra com s'utilitza la comunicació entre els fils de JACK i del fitxer. A la callback no hi ha cap operació que no sigui realtime safe, però és possible que l'operació d'escriure a disc ralentitzi el procés i apareguin XRuns, que podem calcular (això només hauria de passar si tenim algun problema d'un disc que va lent, o estem utilitzant una latència molt baixa i no hi ha temps a escriure. Recordem que per a captura convé augmentar la latència).
$ gcc -Wall -o jackrec -ljack -lsndfile capture_client.c $ ./jackrec usage: jackrec -f filename [ -d second ] [ -b bitdepth ] [ -B bufsize ] port1 [ port2 ... ] $ ./jackrec -f foo.wav system:capture_1
Però fixem-nos bé que amb aquesta tècnica de programació controlada per fils no hi ha un bucle principal del programa. Ara bé, com es pot veure estudiant el codi, la única manera de sortir del codi pel final del main() i poder tancar de manera polida el JACK i alliberar recursos és utilitzar l'opció -d, que limita el funcionament a un número de segons determinat. Si no utilitzo -d aleshores es tanca fent Ctrl-C, però el codi original no gestiona l'ús de Ctrl-C.
$ gcc -Wall -o jackrec -ljack -lsndfile capture_client.c $ ./jackrec -f aaa.wav -d 1 system:capture_1 disk thread finished
creat per Joan Quintana Compte, setembre 2010