[LAD] Tutorial for programming with JACK

Robin Gareus robin at linuxaudio.org
Wed Feb 22 11:30:01 UTC 2012


Hi kallipygo,

I can not answer all of your questions, but Harry may jump in and answer
them.

On 02/22/2012 10:56 AM, kallipygos at inbox.lv wrote:
> Hi experts
> I followed your discussion about JACK API tutorial.
> Actually i am beginner_from_zero in JACK programming.
> Long long time ago i writed small JACK client, but i gotta problems with
> x-runs and lost connections, and i not unterstood why.
> Even if i read all this stuff, without tutorial and step_by_step examples
> i can not programming stable JACK client.
> http://jackaudio.org/files/docs/html/group__ClientFunctions.html
> I found example
> https://github.com/harryhaaren/Linux-Audio-Programming-Documentation/blob/master/jackClient/jackClient.cpp
> but i have some beginner questions about it.
> Why it is written in C++ , not C ?
> float* inputBuffer = (float*)jack_port_get_buffer ( inputPort , nframes);
> float* outputBuffer= (float*)jack_port_get_buffer ( outputPort, nframes);
> means "read" and "write" ?

Yes, kind of.

More precisely: you actually only ask JACK for a pointer.
"Where can I read the audio-data from" -> reply: an array starting at
this memory address. similar for write.

> If so then why callback func
> process(jack_nframes_t nframes )
> have such structure ??
> INPUT_READ
> OUTPUT_WRITE
> PROCESSING ?
> float* inputBuffer = (float*)jack_port_get_buffer ( inputPort , nframes);
> float* outputBuffer= (float*)jack_port_get_buffer ( outputPort, nframes);
> for ( i = 0; i < (int) nframes; i++)
> { // copy data from input to output. Note this is not optimized for speed!
> outputBuffer[i] = inputBuffer[i];
> }
> It means that processed samples will go to output only @ next process() call ?
No.

> Why not
> INPUT_READ
> PROCESSING
> OUTPUT_WRITE ?

What's confusing you is that there is no dedicated 'read/write'. You
only ask: where to read from and where to write to.

Those pointers are valid during the whole process callback function.
You usually query them at the start of the process function.

The data that resides in the outputBuffer memory-area (float array) is
/written back/ at the end of each process callback.

(Actually, JACK uses a "zero-copy" approach which makes it rather fast
and efficient: JACK prepares a float[] array for your application to
write _output_ audio to. You ask where that float-array is and write
audio data to it. The next jack-client in the graph will be pointed to
exactly the same memory as _input_. -- although in reality the
implementation is a bit more complicated..)

> How can i detect (list) - all available ports:channels ?

 jack_get_ports()

the source of 'jack_lsp' is a good example:
https://github.com/jackaudio/tools/blob/master/lsp.c

> How to automatic connect my client i/o ports to jackd ?

Be very careful with that. Most applications should not do this, but let
the user connect ports: either manually or automatically using
studio/session patchbay tools.

In a studio: the playback1/2 outputs may correspond to a sub-woofer or
be connected to something where you don't want any JACK client to send
audio by default.. Speakers have been killed by auto-connecting JACK
applications.

That being said:
  jack_connect(c, jack_port_name(src_port), jack_port_name(dst_port))
but disable it by default or ask the user if s/he wishes to auto-connect
ports,..

> jack_lsp -t
> system:capture_1
> 32 bit float mono audio
> system:capture_2
> 32 bit float mono audio
> system:playback_1
> 32 bit float mono audio
> system:playback_2
> 32 bit float mono audio
> What means - 32 bit float mono audio ?

> 32 bit float - does JACK work with other sample formats ?
theoretically yes, practically no.

You can change the data-format for the whole JACK system. It requires
recompiling jack and adapting all jack-clients. e.g. "video-jack" does
that it uses fixed-size RGB videoframes instead of "32bit float"

> mono - is it possible operate with interleaved stereo stream ?
no

> audio - what else as audio ?

JACK as we know it officially only supports audio and MIDI.

but in principle it can any data: control information, video,..

> What about stereo stream ?
> Must i create 2 ports ausL and ausR ?
yes.

> outputPort = jack_port_register ( client,
> "ausL",
> JACK_DEFAULT_AUDIO_TYPE,
> JackPortIsOutput,
> 0 );
> outputPort = jack_port_register ( client,
> "ausR",
> JACK_DEFAULT_AUDIO_TYPE,
> JackPortIsOutput,
> 0 );

One usually uses a for loop and an array of ports:
  outputPort[0], outputPort[1]

> If so, then how to write data and sync both seperate(d) channels?
> With interleaved stream i do not care about sync between channels.

Neither with separate ports.
The First sample is outputPort[0] is played at the same time as the
first sample in outputPort[N].

Some example code to de-interleave N-channel audio:
https://github.com/erikd/sndfile-tools/blob/master/src/jackplay.c

With JACK, two channel (stereo) audio is no different than forty-two
channel sound (or 5.1 or whatever).

One of the big features of jack is its simple interface. There's exactly
ONE format for audio: 32bit float mono channels. No interleaving, no
16/24 bit conversions, no overflow/clipping inside the JACK graph
(floats can go beyond -1.0 .. +1.0).

Clipping is done as last step before the audio goes back to the device.
Bit-dithering [if necessary and wanted] happens inside the server
back-end that interfaces with the audio-device.


Cheers!
robin



More information about the Linux-audio-dev mailing list