jackclient
Client that dumps samples directly to the jack client with the jack
package.
Note
The latest version of raspiOS (bullseye) causes a lot of problems with the Jack audio that we have not figured out a workaround for. If you intend to use sound, we recommend sticking with Buster for now (available from their legacy downloads section).
Data:
After initializing, JackClient will register itself with this variable. |
|
Sampling rate of the active server |
|
Blocksize, or the amount of samples processed by jack per each |
|
Queue to be loaded with frames of BLOCKSIZE audio. |
|
Lock that enforces a single writer to the QUEUE at a time. |
|
Event that (when set) signals the sound server should play some sound continuously rather than remain silent by default (eg. |
|
Queue that |
|
Event flag that is set when frames dropped into the CONTINUOUS_QUEUE should be looped (eg. |
Classes:
|
Client that dumps frames of audio directly into a running jackd client. |
- SERVER = None
After initializing, JackClient will register itself with this variable.
- Type
- BLOCKSIZE = 1024
Blocksize, or the amount of samples processed by jack per each
JackClient.process()
call.- Type
- QUEUE = None
Queue to be loaded with frames of BLOCKSIZE audio.
- PLAY = <multiprocessing.synchronize.Event object at 0x7f444c900a60>
Event used to trigger loading samples from QUEUE, ie. playing.
- STOP = <multiprocessing.synchronize.Event object at 0x7f441c841d60>
Event that is triggered on the end of buffered audio.
Note
NOT an event used to stop audio.
- Q_LOCK = None
Lock that enforces a single writer to the QUEUE at a time.
- Type
- CONTINUOUS = None
Event that (when set) signals the sound server should play some sound continuously rather than remain silent by default (eg. play a background sound).
- CONTINUOUS_QUEUE = None
Queue that
- CONTINUOUS_LOOP = None
Event flag that is set when frames dropped into the CONTINUOUS_QUEUE should be looped (eg. in the case of stationary background noise), otherwise they are played and then discarded (ie. the sound is continuously generating and submitting samples)
- class JackClient(name='jack_client', outchannels: Optional[list] = None, debug_timing: bool = False)[source]
Bases:
multiprocessing.context.Process
Client that dumps frames of audio directly into a running jackd client.
See the
process()
method to see how the client works in detail, but as a narrative overview:The client interacts with a running jackd daemon, typically launched with
external.start_jackd()
The jackd process is configured with theJACKDSTRING
pref, which by default is built from other parameters like theFS
sampling rate et al.multiprocessing.Event
objects are used to synchronize state within the client, eg. the play event signals that the client should begin to pull frames from the sound queuemultiprocessing.Queue
objects are used to send samples to the client, specifically chunks samples with lengthBLOCKSIZE
The general pattern of using both together is to load a queue with chunks of samples and then set the play event.
Jackd will call the
process
method repeatedly, within which this class will check the state of the event flags and pull from the appropriate queues to load the samples into jackd’s audio buffer
When first initialized, sets module level variables above, which are the public hooks to use the client. Within autopilot, the module-level variables are used, but if using the jackclient or sound system outside of a typical autopilot context, you can instantiate a JackClient and then pass it to sounds as
jack_client
.- Parameters
name (str) – name of client, default “jack_client”
outchannels (list) – Optionally manually pass outchannels rather than getting from prefs. A list of integers corresponding to output channels to initialize. if
None
(default), get'OUTCHANNELS'
from prefs
- Variables
q (
Queue
) – Queue that stores buffered frames of audioq_lock (
Lock
) – Lock that manages access to the Queueplay_evt (
multiprocessing.Event
) – Event used to trigger loading samples from QUEUE, ie. playing.stop_evt (
multiprocessing.Event
) – Event that is triggered on the end of buffered audio.quit_evt (
multiprocessing.Event
) – Event that causes the process to be terminated.client (
jack.Client
) – Client to interface with jackdblocksize (int) – The blocksize - ie. samples processed per
JackClient.process()
call.fs (int) – Sampling rate of client
zero_arr (
numpy.ndarray
) – cached array of zeroes used to fill jackd pipe when not processing audio.continuous_cycle (
itertools.cycle
) – cycle of frames used for continuous soundsmono_output (bool) –
True
orFalse
depending on if the number of output channels is 1 or >1, respectively. detected and set inJackClient.boot_server()
, initialized toTrue
(which is hopefully harmless)
- Parameters
name
Attributes:
set after the first frame of a sound is buffered, used to keep track internally when sounds are started and stopped.
Methods:
Called by
JackClient.run()
to boot the server upon starting the process.run
()Start the process, boot the server, start processing frames and wait for the end.
quit
()Set the
JackClient.quit_evt
process
(frames)Process a frame of audio.
write_to_outports
(data)Write the sound in data to the outport(s).
_pad_continuous
(data)When playing a sound in
process()
, if we're given a sound that is less than the blocksize, pad it with either silence or the continuous soundThread that waits for a time (returned by
jack.Client.frame_time
) passed asend_time
and then setsJackClient.stop_evt
- play_started
set after the first frame of a sound is buffered, used to keep track internally when sounds are started and stopped.
- boot_server()[source]
Called by
JackClient.run()
to boot the server upon starting the process.Activates the client and connects it to the physical speaker outputs as determined by prefs.get(‘OUTCHANNELS’).
This is the interpretation of OUTCHANNELS: * empty string
‘mono’ audio: the same sound is always played to all channels. Connect a single virtual outport to every physical channel. If multi-channel sound is provided, raise an error.
- a single int (example: J)
This is equivalent to [J]. The first virtual outport will be connected to physical channel J. Note this is NOT the same as ‘mono’, because only one speaker plays, instead of all speakers.
- a list (example: [I, J])
The first virtual outport will be connected to physical channel I. The second virtual outport will be connected to physical channel J. And so on. If 1-dimensional sound is provided, play the same to all speakers (like mono mode). If multi-channel sound is provided and the number of channels is different form the length of this list, raise an error.
jack.Client
s can’t be kept alive, so this must be called just before processing sample starts.
- process(frames)[source]
Process a frame of audio.
If the
JackClient.play_evt
is not set, fill port buffers with zeroes.Otherwise, pull frames of audio from the
JackClient.q
until it’s empty.When it’s empty, set the
JackClient.stop_evt
and clear theJackClient.play_evt
.- Parameters
frames – number of frames (samples) to be processed. unused. passed by jack client
- write_to_outports(data)[source]
Write the sound in data to the outport(s).
- If self.mono_output:
- If data is 1-dimensional:
Write that data to the single outport, which goes to all speakers.
Otherwise, raise an error.
- If not self.mono_output:
- If data is 1-dimensional:
Write that data to every outport
- If data is 2-dimensional:
Write one column to each outport, raising an error if there is a different number of columns than outports.
- _pad_continuous(data: numpy.ndarray) numpy.ndarray [source]
When playing a sound in
process()
, if we’re given a sound that is less than the blocksize, pad it with either silence or the continuous soundReturns:
- _wait_for_end()[source]
Thread that waits for a time (returned by
jack.Client.frame_time
) passed asend_time
and then setsJackClient.stop_evt
- Parameters
end_time (int) – the
frame_time
at which to set the event