1 // ----------------------------------------------------------------------------
3 // Copyright (C) 2012-2018 Fons Adriaensen <fons@linuxaudio.org>
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program. If not, see <http://www.gnu.org/licenses/>.
18 // ----------------------------------------------------------------------------
23 #include "jackclient.h"
24 #include "alsathread.h"
28 Jackclient::Jackclient (jack_client_t
* cl
, const char *jserv
, int mode
, int nchan
, bool sync
, void *arg
) :
38 if (!sync
) _resamp
= new VResampler ();
42 Jackclient::~Jackclient (void)
48 bool Jackclient::init (const char *jserv
)
52 struct sched_param spar
;
56 fprintf (stderr
, "Can't connect to Jack, is the server running ?\n");
59 jack_set_process_callback (_client
, jack_static_process
, (void *) this);
60 jack_set_latency_callback (_client
, jack_static_latency
, (void *) this);
61 jack_set_freewheel_callback (_client
, jack_static_freewheel
, (void *) this);
62 jack_set_buffer_size_callback (_client
, jack_static_buffsize
, (void *) this);
63 jack_on_shutdown (_client
, jack_static_shutdown
, (void *) this);
67 if (jack_activate (_client
))
69 fprintf(stderr
, "Can't activate Jack");
72 _jname
= jack_get_client_name (_client
);
73 _bsize
= jack_get_buffer_size (_client
);
74 _fsamp
= jack_get_sample_rate (_client
);
76 flags
= JackPortIsTerminal
| JackPortIsPhysical
;
77 for (i
= 0; i
< _nchan
; i
++)
81 sprintf (s
, "playback_%d", i
+ 1);
82 _ports
[i
] = jack_port_register (_client
, s
, JACK_DEFAULT_AUDIO_TYPE
,
83 flags
| JackPortIsInput
, 0);
87 sprintf (s
, "capture_%d", i
+ 1);
88 _ports
[i
] = jack_port_register (_client
, s
, JACK_DEFAULT_AUDIO_TYPE
,
89 flags
| JackPortIsOutput
, 0);
92 pthread_getschedparam (jack_client_thread_id (_client
), &spol
, &spar
);
93 _rprio
= spar
.sched_priority
- sched_get_priority_max (spol
);
94 _buff
= new float [_bsize
* _nchan
];
99 void Jackclient::fini (void)
106 void Jackclient::jack_static_shutdown (void *arg
)
108 ((Jackclient
*) arg
)->sendinfo (TERM
, 0, 0);
112 int Jackclient::jack_static_buffsize (jack_nframes_t nframes
, void *arg
)
114 Jackclient
*J
= (Jackclient
*) arg
;
116 if (J
->_bsize
== 0) J
->_bsize
= nframes
;
117 else if (J
->_bsize
!= (int) nframes
) J
->_state
= Jackclient::TERM
;
122 void Jackclient::jack_static_freewheel (int state
, void *arg
)
124 ((Jackclient
*) arg
)->jack_freewheel (state
);
128 void Jackclient::jack_static_latency (jack_latency_callback_mode_t jlcm
, void *arg
)
130 ((Jackclient
*) arg
)->jack_latency (jlcm
);
134 int Jackclient::jack_static_process (jack_nframes_t nframes
, void *arg
)
136 return ((Jackclient
*) arg
)->jack_process (nframes
);
140 void Jackclient::start (Lfq_audio
*audioq
,
160 _resamp
->setup (_ratio
, _nchan
, rqual
);
161 _resamp
->set_rrfilt (100);
162 d
= _resamp
->inpsize () / 2.0;
163 if (_mode
== PLAY
) d
*= _ratio
;
167 _ppsec
= (_fsamp
+ _bsize
/ 2) / _bsize
;
168 initwait (_ppsec
/ 2);
169 jack_recompute_total_latencies (_client
);
173 void Jackclient::initwait (int nwait
)
176 _commq
->wr_int32 (Alsathread::WAIT
);
178 if (nwait
> _ppsec
) sendinfo (WAIT
, 0, 0);
182 void Jackclient::initsync (void)
184 // Reset all lock-free queues.
190 // Reset and prefill the resampler.
192 _resamp
->inp_count
= _resamp
->inpsize () / 2 - 1;
193 _resamp
->out_count
= 99999;
196 // Initialise state variables.
199 // Initialise loop filter state.
201 // Activate the ALSA thread,
202 _commq
->wr_int32 (Alsathread::PROC
);
204 sendinfo (SYNC0
, 0, 0);
208 void Jackclient::setloop (double bw
)
212 // Set the loop bandwidth to bw Hz.
213 w
= 6.28 * bw
* _bsize
/ _fsamp
;
214 _w0
= 1.0 - exp (-20.0 * w
);
215 _w1
= w
* 2 / _bsize
;
217 if (_mode
== PLAY
) _w1
/= _ratio
;
222 void Jackclient::playback (int nframes
)
226 float *inp
[MAXCHAN
];
228 _bstat
= _audioq
->rd_avail ();
229 for (i
= 0; i
< _nchan
; i
++)
231 inp
[i
] = (float *)(jack_port_get_buffer (_ports
[i
], nframes
));
235 // Interleave inputs into _buff.
236 for (i
= 0; i
< _nchan
; i
++)
240 for (j
= 0; j
< _bsize
; j
++) q
[j
* _nchan
] = p
[j
];
242 // Resample _buff and write to audio queue.
243 // The while loop takes care of wraparound.
244 _resamp
->inp_count
= _bsize
;
245 _resamp
->inp_data
= _buff
;
246 while (_resamp
->inp_count
)
248 _resamp
->out_count
= _audioq
->wr_linav ();
249 _resamp
->out_data
= _audioq
->wr_datap ();
250 n
= _resamp
->out_count
;
252 n
-= _resamp
->out_count
;
253 _audioq
->wr_commit (n
);
258 // Interleave inputs into audio queue.
259 // The while loop takes care of wraparound.
262 q
= _audioq
->wr_datap ();
263 n
= _audioq
->wr_linav ();
264 if (n
> nframes
) n
= nframes
;
265 for (i
= 0; i
< _nchan
; i
++)
268 for (j
= 0; j
< n
; j
++) q
[j
* _nchan
] = p
[j
];
272 _audioq
->wr_commit (n
);
279 void Jackclient::capture (int nframes
)
283 float *out
[MAXCHAN
];
285 for (i
= 0; i
< _nchan
; i
++)
287 out
[i
] = (float *)(jack_port_get_buffer (_ports
[i
], nframes
));
291 // Read from audio queue and resample.
292 // The while loop takes care of wraparound.
293 _resamp
->out_count
= _bsize
;
294 _resamp
->out_data
= _buff
;
295 while (_resamp
->out_count
)
297 _resamp
->inp_count
= _audioq
->rd_linav ();
298 _resamp
->inp_data
= _audioq
->rd_datap ();
299 n
= _resamp
->inp_count
;
301 n
-= _resamp
->inp_count
;
302 _audioq
->rd_commit (n
);
304 // Deinterleave _buff to outputs.
305 for (i
= 0; i
< _nchan
; i
++)
309 for (j
= 0; j
< _bsize
; j
++) q
[j
] = p
[j
* _nchan
];
314 // Deinterleave audio queue to outputs.
315 // The while loop takes care of wraparound.
318 p
= _audioq
->rd_datap ();
319 n
= _audioq
->rd_linav ();
320 if (n
> nframes
) n
= nframes
;
321 for (i
= 0; i
< _nchan
; i
++)
324 for (j
= 0; j
< n
; j
++) q
[j
] = p
[j
* _nchan
];
328 _audioq
->rd_commit (n
);
332 _bstat
= _audioq
->rd_avail ();
336 void Jackclient::silence (int nframes
)
341 // Write silence to all jack ports.
342 for (i
= 0; i
< _nchan
; i
++)
344 q
= (float *)(jack_port_get_buffer (_ports
[i
], nframes
));
345 memset (q
, 0, nframes
* sizeof (float));
350 void Jackclient::sendinfo (int state
, double error
, double ratio
)
354 if (_infoq
->wr_avail ())
356 J
= _infoq
->wr_datap ();
361 _infoq
->wr_commit ();
366 void Jackclient::jack_freewheel (int state
)
368 _freew
= state
? true : false;
369 if (_freew
) initwait (_ppsec
/ 4);
373 void Jackclient::jack_latency (jack_latency_callback_mode_t jlcm
)
375 jack_latency_range_t R
;
378 if (_state
< WAIT
) return;
381 if (jlcm
!= JackPlaybackLatency
) return;
382 R
.min
= R
.max
= (int)(_delay
/ _ratio
) + _ltcor
;
386 if (jlcm
!= JackCaptureLatency
) return;
387 R
.min
= R
.max
= (int)(_delay
* _ratio
) + _ltcor
;
389 for (i
= 0; i
< _nchan
; i
++)
391 jack_port_set_latency_range (_ports
[i
], jlcm
, &R
);
396 int Jackclient::jack_process (int nframes
)
403 double tj
, err
, d1
, d2
, rd
;
405 // Buffer size change or other evil.
408 sendinfo (TERM
, 0, 0);
411 // Skip cylce if ports may not yet exist.
412 if (_state
< WAIT
) return 0;
414 // Start synchronisation 1/2 second after entering
415 // the WAIT state. This delay allows the ALSA thread
416 // to restart cleanly if necessary. Disabled while
420 if (_freew
) return 0;
421 if (_mode
== CAPT
) silence (nframes
);
422 if (++_count
== 0) initsync ();
426 // Get the start time of the current cycle.
427 jack_get_cycle_times (_client
, &ft
, &t0
, &t1
, &us
);
430 // Check for any skipped cycles.
433 dk
= ft
- _ft
- _bsize
;
436 dk
= (int)(dk
* _ratio
+ 0.5);
437 _audioq
->wr_commit (dk
);
441 dk
= (int)(dk
/ _ratio
+ 0.5);
442 _audioq
->rd_commit (dk
);
447 // Check if we have timing data from the ALSA thread.
448 n
= _alsaq
->rd_avail ();
449 // If the data queue is full restart synchronisation.
450 // This can happen e.g. on a jack engine timeout, or
451 // when too many cycles have been skipped.
452 if (n
== _alsaq
->size ())
454 initwait (_ppsec
/ 2);
459 // Else move interval end to start, and update the
460 // interval end keeping only the most recent data.
461 if (_state
< SYNC2
) _state
++;
464 while (_alsaq
->rd_avail ())
466 D
= _alsaq
->rd_datap ();
467 // Restart synchronisation in case of
468 // an error in the ALSA interface.
469 if (D
->_state
== Alsathread::WAIT
)
471 initwait (_ppsec
/ 2);
476 _alsaq
->rd_commit ();
483 // Compute the delay error.
484 d1
= tjack_diff (tj
, _t_a0
);
485 d2
= tjack_diff (_t_a1
, _t_a0
);
486 rd
= _resamp
? _resamp
->inpdist () : 0.0;
490 n
= _audioq
->nwr () - _k_a0
; // Must be done as integer as both terms will overflow.
491 err
= n
- (_k_a1
- _k_a0
) * d1
/ d2
+ rd
* _ratio
- _delay
;
495 n
= _k_a0
- _audioq
->nrd (); // Must be done as integer as both terms will overflow.
496 err
= n
+ (_k_a1
- _k_a0
) * d1
/ d2
+ rd
- _delay
;
498 n
= (int)(floor (err
+ 0.5));
501 // We have the first delay error value. Adjust the audio
502 // queue to obtain the actually wanted delay, and start
504 if (_mode
== PLAY
) _audioq
->wr_commit (-n
);
505 else _audioq
->rd_commit (n
);
512 // Switch to lower bandwidth after 4 seconds.
513 if ((_state
== PROC1
) && (++_count
== 4 * _ppsec
))
521 _z1
+= _w0
* (_w1
* err
- _z1
);
522 _z2
+= _w0
* (_z1
- _z2
);
524 // Check error conditions.
525 if (fabs (_z3
) > 0.05)
527 // Something is really wrong, wait 10 seconds then restart.
528 initwait (10 * _ppsec
);
531 // Run loop filter and set resample ratio.
534 _rcorr
= 1 - (_z2
+ _z3
);
535 if (_rcorr
> 1.05) _rcorr
= 1.05;
536 if (_rcorr
< 0.95) _rcorr
= 0.95;
537 _resamp
->set_rratio (_rcorr
);
539 sendinfo (_state
, err
, _rcorr
);
541 // Resample and transfer between audio
542 // queue and jack ports.
543 if (_mode
== PLAY
) playback (nframes
);
544 else capture (nframes
);
546 else if (_mode
== CAPT
) silence (nframes
);