diff options
author | falkTX <falktx@falktx.com> | 2022-05-04 11:19:06 +0100 |
---|---|---|
committer | falkTX <falktx@falktx.com> | 2022-05-04 11:19:06 +0100 |
commit | 564c710eefc760a5683b88b3ecb8a29100d5274e (patch) | |
tree | 31c6d8b5843eae1943eca80887bf5d68fdbebdf0 /tools/zalsa | |
parent | 3d5ace462f41e8330e8ffb3acd28ba6ddee54635 (diff) | |
download | jack2-564c710eefc760a5683b88b3ecb8a29100d5274e.tar.gz |
Remove example-clients and tools
Signed-off-by: falkTX <falktx@falktx.com>
Diffstat (limited to 'tools/zalsa')
-rw-r--r-- | tools/zalsa/alsathread.cc | 226 | ||||
-rw-r--r-- | tools/zalsa/alsathread.h | 68 | ||||
-rw-r--r-- | tools/zalsa/jackclient.cc | 549 | ||||
-rw-r--r-- | tools/zalsa/jackclient.h | 120 | ||||
-rw-r--r-- | tools/zalsa/lfqueue.cc | 89 | ||||
-rw-r--r-- | tools/zalsa/lfqueue.h | 182 | ||||
-rw-r--r-- | tools/zalsa/pxthread.cc | 87 | ||||
-rw-r--r-- | tools/zalsa/pxthread.h | 53 | ||||
-rw-r--r-- | tools/zalsa/timers.h | 53 | ||||
-rw-r--r-- | tools/zalsa/zita-a2j.cc | 409 | ||||
-rw-r--r-- | tools/zalsa/zita-j2a.cc | 408 |
11 files changed, 0 insertions, 2244 deletions
diff --git a/tools/zalsa/alsathread.cc b/tools/zalsa/alsathread.cc deleted file mode 100644 index bb5cf75b..00000000 --- a/tools/zalsa/alsathread.cc +++ /dev/null @@ -1,226 +0,0 @@ -// ---------------------------------------------------------------------------- -// -// Copyright (C) 2012-2018 Fons Adriaensen <fons@linuxaudio.org> -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <http://www.gnu.org/licenses/>. -// -// ---------------------------------------------------------------------------- - - -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <math.h> -#include "alsathread.h" -#include "timers.h" - - -Alsathread::Alsathread (Alsa_pcmi *alsadev, int mode) : - _alsadev (alsadev ), - _mode (mode), - _state (INIT), - _fsize (alsadev->fsize ()), - _audioq (0), - _commq (0), - _alsaq (0) -{ - // Compute DLL filter coefficients. - _dt = (double) _fsize / _alsadev->fsamp (); - _w1 = 2 * M_PI * 0.1 * _dt; - _w2 = _w1 * _w1; - _w1 *= 1.6; -} - - -Alsathread::~Alsathread (void) -{ - if (_state != INIT) - { - _state = TERM; - thr_wait (); - } - else - { - _alsadev->pcm_stop (); - } -} - - -int Alsathread::start (Lfq_audio *audioq, Lfq_int32 *commq, Lfq_adata *alsaq, int rtprio) -{ - // Start the ALSA thread. - _audioq = audioq; - _commq = commq; - _alsaq = alsaq; - _state = WAIT; - if (thr_start (SCHED_FIFO, rtprio, 0x10000)) return 1; - return 0; -} - - -void Alsathread::send (int k, double t) -{ - Adata *D; - - // Send (state, frame count, timestamp) to Jack thread. - if (_alsaq->wr_avail ()) - { - D = _alsaq->wr_datap (); - D->_state = _state; - D->_nsamp = k; - D->_timer = t; - _alsaq->wr_commit (); - } -} - - -// The following two functions transfer data between the audio queue -// and the ALSA device. Note that we do *not* check the queue's fill -// state, and it may overrun or underrun. It actually will in the first -// few iterations and in error conditions. This is entirely intentional. -// The queue keeps correct read and write counters even in that case, -// and the main control loop and error recovery depend on it working -// and being used in this way. - -int Alsathread::capture (void) -{ - int c, n, k; - float *p; - - // Start reading from ALSA device. - _alsadev->capt_init (_fsize); - if (_state == PROC) - { - // Input frames from the ALSA device to the audio queue. - // The outer loop takes care of wraparound. - for (n = _fsize; n; n -= k) - { - p = _audioq->wr_datap (); // Audio queue write pointer. - k = _audioq->wr_linav (); // Number of frames that can be - if (k > n) k = n; // written without wraparound. - for (c = 0; c < _audioq->nchan (); c++) - { - // Copy and interleave one channel. - _alsadev->capt_chan (c, p + c, k, _audioq->nchan ()); - } - _audioq->wr_commit (k); // Update audio queue state. - } - } - // Finish reading from ALSA device. - _alsadev->capt_done (_fsize); - return _fsize; -} - - -int Alsathread::playback (void) -{ - int c, n, k; - float *p; - - // Start writing to ALSA device. - _alsadev->play_init (_fsize); - c = 0; - if (_state == PROC) - { - // Output frames from the audio queue to the ALSA device. - // The outer loop takes care of wraparound. - for (n = _fsize; n; n -= k) - { - p = _audioq->rd_datap (); // Audio queue read pointer. - k = _audioq->rd_linav (); // Number of frames that can - if (k > n) k = n; // be read without wraparound. - for (c = 0; c < _audioq->nchan (); c++) - { - // De-interleave and copy one channel. - _alsadev->play_chan (c, p + c, k, _audioq->nchan ()); - } - _audioq->rd_commit (k); // Update audio queue state. - } - } - // Clear all or remaining channels. - while (c < _alsadev->nplay ()) _alsadev->clear_chan (c++, _fsize); - // Finish writing to ALSA device. - _alsadev->play_done (_fsize); - return _fsize; -} - - -void Alsathread::thr_main (void) -{ - int na, nu; - double tw, er; - - _alsadev->pcm_start (); - while (_state != TERM) - { - // Wait for next cycle, then take timestamp. - na = _alsadev->pcm_wait (); - - tw = tjack (jack_get_time ()); - // Check for errors - requires restart. - if (_alsadev->state () && (na == 0)) - { - _state = WAIT; - send (0, 0); - usleep (10000); - continue; - } - - // Check for commands from the Jack thread. - if (_commq->rd_avail ()) - { - _state = _commq->rd_int32 (); - if (_state == PROC) _first = true; - if (_state == TERM) send (0, 0); - } - - // We could have more than one period. - nu = 0; - while (na >= _fsize) - { - // Transfer frames. - if (_mode == PLAY) nu += playback (); - else nu += capture (); - // Update loop condition. - na -= _fsize; - // Run the DLL if in PROC state. - if (_state == PROC) - { - if (_first) - { - // Init DLL in first iteration. - _first = false; - _dt = (double) _fsize / _alsadev->fsamp (); - _t0 = tw; - _t1 = tw + _dt; - } - else - { - // Update the DLL. - // If we have more than one period, use - // the time error only for the last one. - if (na >= _fsize) er = 0; - else er = tjack_diff (tw, _t1); - _t0 = _t1; - _t1 = tjack_diff (_t1 + _dt + _w1 * er, 0.0); - _dt += _w2 * er; - } - } - } - - // Send number of frames used and timestamp to Jack thread. - if (_state == PROC) send (nu, _t1); - } - _alsadev->pcm_stop (); -} diff --git a/tools/zalsa/alsathread.h b/tools/zalsa/alsathread.h deleted file mode 100644 index f9cb761c..00000000 --- a/tools/zalsa/alsathread.h +++ /dev/null @@ -1,68 +0,0 @@ -// ---------------------------------------------------------------------------- -// -// Copyright (C) 2012-2018 Fons Adriaensen <fons@linuxaudio.org> -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <http://www.gnu.org/licenses/>. -// -// ---------------------------------------------------------------------------- - - -#ifndef __ALSATHREAD_H -#define __ALSATHREAD_H - - -#include <zita-alsa-pcmi.h> -#include "jack/jack.h" -#include "pxthread.h" -#include "lfqueue.h" - - -class Alsathread : public Pxthread -{ -public: - - enum { INIT, WAIT, PROC, TERM }; - enum { PLAY, CAPT }; - - Alsathread (Alsa_pcmi *alsadev, int mode); - virtual ~Alsathread (void); - virtual void thr_main (void); - - int start (Lfq_audio *audioq, Lfq_int32 *commq, Lfq_adata *alsaq, int rtprio); - -private: - - void send (int k, double t); - int capture (void); - int playback (void); - - Alsa_pcmi *_alsadev; - int _mode; - int _state; - int _nfail; - int _fsize; - Lfq_audio *_audioq; - Lfq_int32 *_commq; - Lfq_adata *_alsaq; - bool _first; -// double _jtmod; - double _t0; - double _t1; - double _dt; - double _w1; - double _w2; -}; - - -#endif diff --git a/tools/zalsa/jackclient.cc b/tools/zalsa/jackclient.cc deleted file mode 100644 index 095b2632..00000000 --- a/tools/zalsa/jackclient.cc +++ /dev/null @@ -1,549 +0,0 @@ -// ---------------------------------------------------------------------------- -// -// Copyright (C) 2012-2018 Fons Adriaensen <fons@linuxaudio.org> -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <http://www.gnu.org/licenses/>. -// -// ---------------------------------------------------------------------------- - - -#include <stdio.h> -#include <math.h> -#include "jackclient.h" -#include "alsathread.h" -#include "timers.h" - - -Jackclient::Jackclient (jack_client_t* cl, const char *jserv, int mode, int nchan, bool sync, void *arg) : - _client (cl), - _arg (arg), - _mode (mode), - _nchan (nchan), - _state (INIT), - _freew (false), - _resamp (0) -{ - init (jserv); - if (!sync) _resamp = new VResampler (); -} - - -Jackclient::~Jackclient (void) -{ - fini (); -} - - -bool Jackclient::init (const char *jserv) -{ - int i, spol, flags; - char s [64]; - struct sched_param spar; - - if (_client == 0) - { - fprintf (stderr, "Can't connect to Jack, is the server running ?\n"); - return false; - } - jack_set_process_callback (_client, jack_static_process, (void *) this); - jack_set_latency_callback (_client, jack_static_latency, (void *) this); - jack_set_freewheel_callback (_client, jack_static_freewheel, (void *) this); - jack_set_buffer_size_callback (_client, jack_static_buffsize, (void *) this); - jack_on_shutdown (_client, jack_static_shutdown, (void *) this); - - _bsize = 0; - _fsamp = 0; - if (jack_activate (_client)) - { - fprintf(stderr, "Can't activate Jack"); - return false; - } - _jname = jack_get_client_name (_client); - _bsize = jack_get_buffer_size (_client); - _fsamp = jack_get_sample_rate (_client); - - flags = JackPortIsTerminal | JackPortIsPhysical; - for (i = 0; i < _nchan; i++) - { - if (_mode == PLAY) - { - sprintf (s, "playback_%d", i + 1); - _ports [i] = jack_port_register (_client, s, JACK_DEFAULT_AUDIO_TYPE, - flags | JackPortIsInput, 0); - } - else - { - sprintf (s, "capture_%d", i + 1); - _ports [i] = jack_port_register (_client, s, JACK_DEFAULT_AUDIO_TYPE, - flags | JackPortIsOutput, 0); - } - } - pthread_getschedparam (jack_client_thread_id (_client), &spol, &spar); - _rprio = spar.sched_priority - sched_get_priority_max (spol); - _buff = new float [_bsize * _nchan]; - return true; -} - - -void Jackclient::fini (void) -{ - delete[] _buff; - delete _resamp; -} - - -void Jackclient::jack_static_shutdown (void *arg) -{ - ((Jackclient *) arg)->sendinfo (TERM, 0, 0); -} - - -int Jackclient::jack_static_buffsize (jack_nframes_t nframes, void *arg) -{ - Jackclient *J = (Jackclient *) arg; - - if (J->_bsize == 0) J->_bsize = nframes; - else if (J->_bsize != (int) nframes) J->_state = Jackclient::TERM; - return 0; -} - - -void Jackclient::jack_static_freewheel (int state, void *arg) -{ - ((Jackclient *) arg)->jack_freewheel (state); -} - - -void Jackclient::jack_static_latency (jack_latency_callback_mode_t jlcm, void *arg) -{ - ((Jackclient *) arg)->jack_latency (jlcm); -} - - -int Jackclient::jack_static_process (jack_nframes_t nframes, void *arg) -{ - return ((Jackclient *) arg)->jack_process (nframes); -} - - -void Jackclient::start (Lfq_audio *audioq, - Lfq_int32 *commq, - Lfq_adata *alsaq, - Lfq_jdata *infoq, - double ratio, - int delay, - int ltcor, - int rqual) -{ - double d; - - _audioq = audioq; - _commq = commq; - _alsaq = alsaq; - _infoq = infoq; - _ratio = ratio; - _delay = delay; - _rcorr = 1.0; - if (_resamp) - { - _resamp->setup (_ratio, _nchan, rqual); - _resamp->set_rrfilt (100); - d = _resamp->inpsize () / 2.0; - if (_mode == PLAY) d *= _ratio; - _delay += d; - } - _ltcor = ltcor; - _ppsec = (_fsamp + _bsize / 2) / _bsize; - initwait (_ppsec / 2); - jack_recompute_total_latencies (_client); -} - - -void Jackclient::initwait (int nwait) -{ - _count = -nwait; - _commq->wr_int32 (Alsathread::WAIT); - _state = WAIT; - if (nwait > _ppsec) sendinfo (WAIT, 0, 0); -} - - -void Jackclient::initsync (void) -{ - // Reset all lock-free queues. - _commq->reset (); - _alsaq->reset (); - _audioq->reset (); - if (_resamp) - { - // Reset and prefill the resampler. - _resamp->reset (); - _resamp->inp_count = _resamp->inpsize () / 2 - 1; - _resamp->out_count = 99999; - _resamp->process (); - } - // Initialise state variables. - _t_a0 = _t_a1 = 0; - _k_a0 = _k_a1 = 0; - // Initialise loop filter state. - _z1 = _z2 = _z3 = 0; - // Activate the ALSA thread, - _commq->wr_int32 (Alsathread::PROC); - _state = SYNC0; - sendinfo (SYNC0, 0, 0); -} - - -void Jackclient::setloop (double bw) -{ - double w; - - // Set the loop bandwidth to bw Hz. - w = 6.28 * bw * _bsize / _fsamp; - _w0 = 1.0 - exp (-20.0 * w); - _w1 = w * 2 / _bsize; - _w2 = w / 2; - if (_mode == PLAY) _w1 /= _ratio; - else _w1 *= _ratio; -} - - -void Jackclient::playback (int nframes) -{ - int i, j, n; - float *p, *q; - float *inp [MAXCHAN]; - - _bstat = _audioq->rd_avail (); - for (i = 0; i < _nchan; i++) - { - inp [i] = (float *)(jack_port_get_buffer (_ports [i], nframes)); - } - if (_resamp) - { - // Interleave inputs into _buff. - for (i = 0; i < _nchan; i++) - { - p = inp [i]; - q = _buff + i; - for (j = 0; j < _bsize; j++) q [j * _nchan] = p [j]; - } - // Resample _buff and write to audio queue. - // The while loop takes care of wraparound. - _resamp->inp_count = _bsize; - _resamp->inp_data = _buff; - while (_resamp->inp_count) - { - _resamp->out_count = _audioq->wr_linav (); - _resamp->out_data = _audioq->wr_datap (); - n = _resamp->out_count; - _resamp->process (); - n -= _resamp->out_count; - _audioq->wr_commit (n); - } - } - else - { - // Interleave inputs into audio queue. - // The while loop takes care of wraparound. - while (nframes) - { - q = _audioq->wr_datap (); - n = _audioq->wr_linav (); - if (n > nframes) n = nframes; - for (i = 0; i < _nchan; i++) - { - p = inp [i]; - for (j = 0; j < n; j++) q [j * _nchan] = p [j]; - inp [i] += n; - q += 1; - } - _audioq->wr_commit (n); - nframes -= n; - } - } -} - - -void Jackclient::capture (int nframes) -{ - int i, j, n; - float *p, *q; - float *out [MAXCHAN]; - - for (i = 0; i < _nchan; i++) - { - out [i] = (float *)(jack_port_get_buffer (_ports [i], nframes)); - } - if (_resamp) - { - // Read from audio queue and resample. - // The while loop takes care of wraparound. - _resamp->out_count = _bsize; - _resamp->out_data = _buff; - while (_resamp->out_count) - { - _resamp->inp_count = _audioq->rd_linav (); - _resamp->inp_data = _audioq->rd_datap (); - n = _resamp->inp_count; - _resamp->process (); - n -= _resamp->inp_count; - _audioq->rd_commit (n); - } - // Deinterleave _buff to outputs. - for (i = 0; i < _nchan; i++) - { - p = _buff + i; - q = out [i]; - for (j = 0; j < _bsize; j++) q [j] = p [j * _nchan]; - } - } - else - { - // Deinterleave audio queue to outputs. - // The while loop takes care of wraparound. - while (nframes) - { - p = _audioq->rd_datap (); - n = _audioq->rd_linav (); - if (n > nframes) n = nframes; - for (i = 0; i < _nchan; i++) - { - q = out [i]; - for (j = 0; j < n; j++) q [j] = p [j * _nchan]; - out [i] += n; - p += 1; - } - _audioq->rd_commit (n); - nframes -= n; - } - } - _bstat = _audioq->rd_avail (); -} - - -void Jackclient::silence (int nframes) -{ - int i; - float *q; - - // Write silence to all jack ports. - for (i = 0; i < _nchan; i++) - { - q = (float *)(jack_port_get_buffer (_ports [i], nframes)); - memset (q, 0, nframes * sizeof (float)); - } -} - - -void Jackclient::sendinfo (int state, double error, double ratio) -{ - Jdata *J; - - if (_infoq->wr_avail ()) - { - J = _infoq->wr_datap (); - J->_state = state; - J->_error = error; - J->_ratio = ratio; - J->_bstat = _bstat; - _infoq->wr_commit (); - } -} - - -void Jackclient::jack_freewheel (int state) -{ - _freew = state ? true : false; - if (_freew) initwait (_ppsec / 4); -} - - -void Jackclient::jack_latency (jack_latency_callback_mode_t jlcm) -{ - jack_latency_range_t R; - int i; - - if (_state < WAIT) return; - if (_mode == PLAY) - { - if (jlcm != JackPlaybackLatency) return; - R.min = R.max = (int)(_delay / _ratio) + _ltcor; - } - else - { - if (jlcm != JackCaptureLatency) return; - R.min = R.max = (int)(_delay * _ratio) + _ltcor; - } - for (i = 0; i < _nchan; i++) - { - jack_port_set_latency_range (_ports [i], jlcm, &R); - } -} - - -int Jackclient::jack_process (int nframes) -{ - int dk, n; - Adata *D; - jack_time_t t0, t1; - jack_nframes_t ft; - float us; - double tj, err, d1, d2, rd; - - // Buffer size change or other evil. - if (_state == TERM) - { - sendinfo (TERM, 0, 0); - return 0; - } - // Skip cylce if ports may not yet exist. - if (_state < WAIT) return 0; - - // Start synchronisation 1/2 second after entering - // the WAIT state. This delay allows the ALSA thread - // to restart cleanly if necessary. Disabled while - // freewheeling. - if (_state == WAIT) - { - if (_freew) return 0; - if (_mode == CAPT) silence (nframes); - if (++_count == 0) initsync (); - else return 0; - } - - // Get the start time of the current cycle. - jack_get_cycle_times (_client, &ft, &t0, &t1, &us); - tj = tjack (t0); - - // Check for any skipped cycles. - if (_state >= SYNC1) - { - dk = ft - _ft - _bsize; - if (_mode == PLAY) - { - dk = (int)(dk * _ratio + 0.5); - _audioq->wr_commit (dk); - } - else - { - dk = (int)(dk / _ratio + 0.5); - _audioq->rd_commit (dk); - } - } - _ft = ft; - - // Check if we have timing data from the ALSA thread. - n = _alsaq->rd_avail (); - // If the data queue is full restart synchronisation. - // This can happen e.g. on a jack engine timeout, or - // when too many cycles have been skipped. - if (n == _alsaq->size ()) - { - initwait (_ppsec / 2); - return 0; - } - if (n) - { - // Else move interval end to start, and update the - // interval end keeping only the most recent data. - if (_state < SYNC2) _state++; - _t_a0 = _t_a1; - _k_a0 = _k_a1; - while (_alsaq->rd_avail ()) - { - D = _alsaq->rd_datap (); - // Restart synchronisation in case of - // an error in the ALSA interface. - if (D->_state == Alsathread::WAIT) - { - initwait (_ppsec / 2); - return 0; - } - _t_a1 = D->_timer; - _k_a1 += D->_nsamp; - _alsaq->rd_commit (); - } - } - - err = 0; - if (_state >= SYNC2) - { - // Compute the delay error. - d1 = tjack_diff (tj, _t_a0); - d2 = tjack_diff (_t_a1, _t_a0); - rd = _resamp ? _resamp->inpdist () : 0.0; - - if (_mode == PLAY) - { - n = _audioq->nwr () - _k_a0; // Must be done as integer as both terms will overflow. - err = n - (_k_a1 - _k_a0) * d1 / d2 + rd * _ratio - _delay; - } - else - { - n = _k_a0 - _audioq->nrd (); // Must be done as integer as both terms will overflow. - err = n + (_k_a1 - _k_a0) * d1 / d2 + rd - _delay ; - } - n = (int)(floor (err + 0.5)); - if (_state == SYNC2) - { - // We have the first delay error value. Adjust the audio - // queue to obtain the actually wanted delay, and start - // tracking. - if (_mode == PLAY) _audioq->wr_commit (-n); - else _audioq->rd_commit (n); - err -= n; - setloop (1.0); - _state = PROC1; - } - } - - // Switch to lower bandwidth after 4 seconds. - if ((_state == PROC1) && (++_count == 4 * _ppsec)) - { - _state = PROC2; - setloop (0.05); - } - - if (_state >= PROC1) - { - _z1 += _w0 * (_w1 * err - _z1); - _z2 += _w0 * (_z1 - _z2); - _z3 += _w2 * _z2; - // Check error conditions. - if (fabs (_z3) > 0.05) - { - // Something is really wrong, wait 10 seconds then restart. - initwait (10 * _ppsec); - return 0; - } - // Run loop filter and set resample ratio. - if (_resamp) - { - _rcorr = 1 - (_z2 + _z3); - if (_rcorr > 1.05) _rcorr = 1.05; - if (_rcorr < 0.95) _rcorr = 0.95; - _resamp->set_rratio (_rcorr); - } - sendinfo (_state, err, _rcorr); - - // Resample and transfer between audio - // queue and jack ports. - if (_mode == PLAY) playback (nframes); - else capture (nframes); - } - else if (_mode == CAPT) silence (nframes); - - return 0; -} diff --git a/tools/zalsa/jackclient.h b/tools/zalsa/jackclient.h deleted file mode 100644 index 52f3ddfd..00000000 --- a/tools/zalsa/jackclient.h +++ /dev/null @@ -1,120 +0,0 @@ -// ---------------------------------------------------------------------------- -// -// Copyright (C) 2012-2018 Fons Adriaensen <fons@linuxaudio.org> -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <http://www.gnu.org/licenses/>. -// -// ---------------------------------------------------------------------------- - - -#ifndef __JACKCLIENT_H -#define __JACKCLIENT_H - - -#include <zita-resampler/vresampler.h> -#include "jack/jack.h" -#include "lfqueue.h" - - -class Jackclient -{ -public: - - Jackclient (jack_client_t*, const char *jserv, int mode, int nchan, bool sync, void *arg); - virtual ~Jackclient (void); - - enum { PLAY, CAPT, MAXCHAN = 64 }; - enum { INIT, TERM, WAIT, SYNC0, SYNC1, SYNC2, PROC1, PROC2 }; - - void start (Lfq_audio *audioq, - Lfq_int32 *commq, - Lfq_adata *alsaq, - Lfq_jdata *infoq, - double ratio, - int delay, - int ltcor, - int rqual); - - const char *jname (void) const { return _jname; } - int fsamp (void) const { return _fsamp; } - int bsize (void) const { return _bsize; } - int rprio (void) const { return _rprio; } - void *getarg(void) const { return _arg; } - -private: - - bool init (const char *jserv); - void fini (void); - void initwait (int nwait); - void initsync (void); - void setloop (double bw); - void silence (int nframes); - void playback (int nframes); - void capture (int nframes); - void sendinfo (int state, double error, double ratio); - - virtual void thr_main (void) {} - - void jack_freewheel (int state); - void jack_latency (jack_latency_callback_mode_t jlcm); - int jack_process (int nframes); - - jack_client_t *_client; - jack_port_t *_ports [MAXCHAN]; - void *_arg; - const char *_jname; - int _mode; - int _nchan; - int _state; - int _count; - int _fsamp; - int _bsize; - int _rprio; - bool _freew; - float *_buff; - - Lfq_audio *_audioq; - Lfq_int32 *_commq; - Lfq_adata *_alsaq; - Lfq_jdata *_infoq; - double _ratio; - int _ppsec; - int _bstat; - - jack_nframes_t _ft; - double _t_a0; - double _t_a1; - int _k_a0; - int _k_a1; - double _delay; - int _ltcor; - - double _w0; - double _w1; - double _w2; - double _z1; - double _z2; - double _z3; - double _rcorr; - VResampler *_resamp; - - static void jack_static_shutdown (void *arg); - static int jack_static_buffsize (jack_nframes_t nframes, void *arg); - static void jack_static_freewheel (int state, void *arg); - static void jack_static_latency (jack_latency_callback_mode_t jlcm, void *arg); - static int jack_static_process (jack_nframes_t nframes, void *arg); -}; - - -#endif diff --git a/tools/zalsa/lfqueue.cc b/tools/zalsa/lfqueue.cc deleted file mode 100644 index f66d07e3..00000000 --- a/tools/zalsa/lfqueue.cc +++ /dev/null @@ -1,89 +0,0 @@ -// ---------------------------------------------------------------------------- -// -// Copyright (C) 2012 Fons Adriaensen <fons@linuxaudio.org> -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <http://www.gnu.org/licenses/>. -// -// ---------------------------------------------------------------------------- - - -#include <assert.h> -#include "lfqueue.h" - - -Lfq_adata::Lfq_adata (int size) : - _size (size), - _mask (size - 1), - _nwr (0), - _nrd (0) -{ - assert (!(_size & _mask)); - _data = new Adata [_size]; -} - -Lfq_adata::~Lfq_adata (void) -{ - delete[] _data; -} - - -Lfq_jdata::Lfq_jdata (int size) : - _size (size), - _mask (size - 1), - _nwr (0), - _nrd (0) -{ - assert (!(_size & _mask)); - _data = new Jdata [_size]; -} - -Lfq_jdata::~Lfq_jdata (void) -{ - delete[] _data; -} - - -Lfq_int32::Lfq_int32 (int size) : - _size (size), - _mask (size - 1), - _nwr (0), - _nrd (0) -{ - assert (!(_size & _mask)); - _data = new int32_t [_size]; -} - -Lfq_int32::~Lfq_int32 (void) -{ - delete[] _data; -} - - -Lfq_audio::Lfq_audio (int nsamp, int nchan) : - _size (nsamp), - _mask (nsamp - 1), - _nch (nchan), - _nwr (0), - _nrd (0) -{ - assert (!(_size & _mask)); - _data = new float [_nch * _size]; -} - -Lfq_audio::~Lfq_audio (void) -{ - delete[] _data; -} - - diff --git a/tools/zalsa/lfqueue.h b/tools/zalsa/lfqueue.h deleted file mode 100644 index 3943d401..00000000 --- a/tools/zalsa/lfqueue.h +++ /dev/null @@ -1,182 +0,0 @@ -// ---------------------------------------------------------------------------- -// -// Copyright (C) 2012 Fons Adriaensen <fons@linuxaudio.org> -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <http://www.gnu.org/licenses/>. -// -// ---------------------------------------------------------------------------- - - -#ifndef __LFQUEUE_H -#define __LFQUEUE_H - - -#include <stdint.h> -#include <string.h> - - -class Adata -{ -public: - - int32_t _state; - int32_t _nsamp; - double _timer; -}; - - -class Lfq_adata -{ -public: - - Lfq_adata (int size); - ~Lfq_adata (void); - - void reset (void) { _nwr = _nrd = 0; } - int size (void) const { return _size; } - - int wr_avail (void) const { return _size - _nwr + _nrd; } - Adata *wr_datap (void) { return _data + (_nwr & _mask); } - void wr_commit (void) { _nwr++; } - - int rd_avail (void) const { return _nwr - _nrd; } - Adata *rd_datap (void) { return _data + (_nrd & _mask); } - void rd_commit (void) { _nrd++; } - -private: - - Adata *_data; - int _size; - int _mask; - int _nwr; - int _nrd; -}; - - -class Jdata -{ -public: - - int32_t _state; - double _error; - double _ratio; - int _bstat; -}; - - -class Lfq_jdata -{ -public: - - Lfq_jdata (int size); - ~Lfq_jdata (void); - - void reset (void) { _nwr = _nrd = 0; } - int size (void) const { return _size; } - - int wr_avail (void) const { return _size - _nwr + _nrd; } - Jdata *wr_datap (void) { return _data + (_nwr & _mask); } - void wr_commit (void) { _nwr++; } - - int rd_avail (void) const { return _nwr - _nrd; } - Jdata *rd_datap (void) { return _data + (_nrd & _mask); } - void rd_commit (void) { _nrd++; } - -private: - - Jdata *_data; - int _size; - int _mask; - int _nwr; - int _nrd; -}; - - -class Lfq_int32 -{ -public: - - Lfq_int32 (int size); - ~Lfq_int32 (void); - - int size (void) const { return _size; } - void reset (void) { _nwr = _nrd = 0; } - - int wr_avail (void) const { return _size - _nwr + _nrd; } - int32_t *wr_datap (void) { return _data + (_nwr & _mask); } - void wr_commit (void) { _nwr++; } - - int rd_avail (void) const { return _nwr - _nrd; } - int32_t *rd_datap (void) { return _data + (_nrd & _mask); } - void rd_commit (void) { _nrd++; } - - void wr_int32 (int32_t v) { _data [_nwr++ & _mask] = v; } - void wr_uint32 (uint32_t v) { _data [_nwr++ & _mask] = v; } - void wr_float (float v) { *(float *)(_data + (_nwr++ & _mask)) = v; } - - int32_t rd_int32 (void) { return _data [_nrd++ & _mask]; } - int32_t rd_uint32 (void) { return _data [_nrd++ & _mask]; } - float rd_float (void) { return *(float *)(_data + (_nrd++ & _mask)); } - -private: - - int32_t *_data; - int _size; - int _mask; - int _nwr; - int _nrd; -}; - - -class Lfq_audio -{ -public: - - Lfq_audio (int nsamp, int nchan); - ~Lfq_audio (void); - - int size (void) const { return _size; } - void reset (void) - { - _nwr = _nrd = 0; - memset (_data, 0, _size * _nch * sizeof (float)); - } - - int nchan (void) const { return _nch; } - int nwr (void) const { return _nwr; }; - int nrd (void) const { return _nrd; }; - - int wr_avail (void) const { return _size - _nwr + _nrd; } - int wr_linav (void) const { return _size - (_nwr & _mask); } - float *wr_datap (void) { return _data + _nch * (_nwr & _mask); } - void wr_commit (int k) { _nwr += k; } - - int rd_avail (void) const { return _nwr - _nrd; } - int rd_linav (void) const { return _size - (_nrd & _mask); } - float *rd_datap (void) { return _data + _nch * (_nrd & _mask); } - void rd_commit (int k) { _nrd += k; } - -private: - - float *_data; - int _size; - int _mask; - int _nch; - int _nwr; - int _nrd; -}; - - -#endif - diff --git a/tools/zalsa/pxthread.cc b/tools/zalsa/pxthread.cc deleted file mode 100644 index 522827d4..00000000 --- a/tools/zalsa/pxthread.cc +++ /dev/null @@ -1,87 +0,0 @@ -// ---------------------------------------------------------------------------- -// -// Copyright (C) 2012 Fons Adriaensen <fons@linuxaudio.org> -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <http://www.gnu.org/licenses/>. -// -// ---------------------------------------------------------------------------- - - -#include "pxthread.h" - - -Pxthread::Pxthread (void) : _thrid (0) -{ -} - - -Pxthread::~Pxthread (void) -{ -} - - -extern "C" void *Pxthread_entry_point (void *arg) -{ - Pxthread *T = (Pxthread *) arg; - T->thr_main (); - return NULL; -} - - -int Pxthread::thr_start (int policy, int priority, size_t stacksize) -{ - int min, max, rc; - pthread_attr_t attr; - struct sched_param parm; - - min = sched_get_priority_min (policy); - max = sched_get_priority_max (policy); - priority += max; - if (priority > max) priority = max; - if (priority < min) priority = min; - parm.sched_priority = priority; - - pthread_attr_init (&attr); - pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); - pthread_attr_setschedpolicy (&attr, policy); - pthread_attr_setschedparam (&attr, &parm); - pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM); - pthread_attr_setinheritsched (&attr, PTHREAD_EXPLICIT_SCHED); - pthread_attr_setstacksize (&attr, stacksize); - - _thrid = 0; - rc = pthread_create (&_thrid, - &attr, - Pxthread_entry_point, - this); - - pthread_attr_destroy (&attr); - - return rc; -} - - -void Pxthread::thr_main (void) -{ -} - - -void Pxthread::thr_wait (void) -{ - if (_thrid == 0) - return; - pthread_join (_thrid, NULL); - _thrid = 0; -} - diff --git a/tools/zalsa/pxthread.h b/tools/zalsa/pxthread.h deleted file mode 100644 index 542aa6ed..00000000 --- a/tools/zalsa/pxthread.h +++ /dev/null @@ -1,53 +0,0 @@ -// ---------------------------------------------------------------------------- -// -// Copyright (C) 2012 Fons Adriaensen <fons@linuxaudio.org> -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <http://www.gnu.org/licenses/>. -// -// ---------------------------------------------------------------------------- - - -#ifndef __PXTHREAD_H -#define __PXTHREAD_H - - -#include <sys/types.h> -#include <stdlib.h> -#include <stdio.h> -#include <stdarg.h> -#include <assert.h> -#include <errno.h> -#include <pthread.h> - - -class Pxthread -{ -public: - - Pxthread (void); - virtual ~Pxthread (void); - Pxthread (const Pxthread&); - Pxthread& operator=(const Pxthread&); - - virtual void thr_main (void) = 0; - virtual int thr_start (int policy, int priority, size_t stacksize = 0); - virtual void thr_wait (void); - -private: - - pthread_t _thrid; -}; - - -#endif diff --git a/tools/zalsa/timers.h b/tools/zalsa/timers.h deleted file mode 100644 index 267afa61..00000000 --- a/tools/zalsa/timers.h +++ /dev/null @@ -1,53 +0,0 @@ -// ---------------------------------------------------------------------------- -// -// Copyright (C) 2012-2018 Fons Adriaensen <fons@linuxaudio.org> -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <http://www.gnu.org/licenses/>. -// -// ---------------------------------------------------------------------------- - - -#ifndef __TIMERS_H -#define __TIMERS_H - - -#include <math.h> -#include <sys/time.h> -#include <jack/jack.h> - - -#define tjack_mod ldexp (1e-6f, 32) - - - -inline double tjack_diff (double a, double b) -{ - double d, m; - - d = a - b; - m = tjack_mod; - while (d < -m / 2) d += m; - while (d >= m / 2) d -= m; - return d; -} - - -inline double tjack (jack_time_t t, double dt = 0) -{ - int32_t u = (int32_t)(t & 0xFFFFFFFFLL); - return 1e-6 * u; -} - - -#endif diff --git a/tools/zalsa/zita-a2j.cc b/tools/zalsa/zita-a2j.cc deleted file mode 100644 index 1dbe1144..00000000 --- a/tools/zalsa/zita-a2j.cc +++ /dev/null @@ -1,409 +0,0 @@ -// ---------------------------------------------------------------------------- -// -// Copyright (C) 2012 Fons Adriaensen <fons@linuxaudio.org> -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <http://www.gnu.org/licenses/>. -// -// ---------------------------------------------------------------------------- - - -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <stdio.h> -#include <signal.h> -#include "alsathread.h" -#include "jackclient.h" -#include "lfqueue.h" -#include "jack/control.h" - -static const char *clopt = "hvLSwj:d:r:p:n:c:Q:I:"; - -static void help (void) -{ - jack_info ("%s-%s", APPNAME, VERSION); - jack_info ("(C) 2012-2018 Fons Adriaensen <fons@linuxaudio.org>"); - jack_info ("Use ALSA capture device as a Jack client."); - jack_info ("Options:"); - jack_info (" -h Display this text"); - jack_info (" -j <jackname> Name as Jack client [%s]", APPNAME); - jack_info (" -d <device> ALSA capture device [none]"); - jack_info (" -r <rate> Sample rate [48000]"); - jack_info (" -p <period> Period size [256]"); - jack_info (" -n <nfrags> Number of fragments [2]"); - jack_info (" -c <nchannels> Number of channels [2]"); - jack_info (" -S Word clock sync, no resampling"); - jack_info (" -Q <quality> Resampling quality, 16..96 [auto]"); - jack_info (" -I <samples> Latency adjustment [0]"); - jack_info (" -L Force 16-bit and 2 channels [off]"); - jack_info (" -w Wait until soundcard is available [off]"); - jack_info (" -v Print tracing information [off]"); -} - -class zita_a2j -{ - Lfq_int32 *commq; - Lfq_adata *alsaq; - Lfq_jdata *infoq; - Lfq_audio *audioq; - bool stop; - bool v_opt; - bool L_opt; - bool S_opt; - bool w_opt; - char *jname; - char *device; - int fsamp; - int bsize; - int nfrag; - int nchan; - int rqual; - int ltcor; - -public: - - zita_a2j() - { - commq = new Lfq_int32(16); - alsaq = new Lfq_adata(256); - infoq = new Lfq_jdata(256); - audioq = 0; - stop = false; - v_opt = false; - L_opt = false; - S_opt = false; - w_opt = false; - jname = strdup(APPNAME); - device = 0; - fsamp = 48000; - bsize = 128; - nfrag = 2; - nchan = 2; - rqual = 0; - ltcor = 0; - A = 0; - C = 0; - J = 0; - t = 0; - } - -private: - - int procoptions (int ac, const char *av []) - { - int k; - - optind = 1; - opterr = 0; - while ((k = getopt (ac, (char **) av, (char *) clopt)) != -1) - { - if (optarg && (*optarg == '-')) - { - jack_error (APPNAME ": Missing argument for '-%c' option.", k); - jack_error (APPNAME ": Use '-h' to see all options."); - return 1; - } - switch (k) - { - case 'h' : help (); return 1; - case 'v' : v_opt = true; break; - case 'L' : L_opt = true; break; - case 'S' : S_opt = true; break; - case 'w' : w_opt = true; break; - case 'j' : jname = optarg; break; - case 'd' : device = optarg; break; - case 'r' : fsamp = atoi (optarg); break; - case 'p' : bsize = atoi (optarg); break; - case 'n' : nfrag = atoi (optarg); break; - case 'c' : nchan = atoi (optarg); break; - case 'Q' : rqual = atoi (optarg); break; - case 'I' : ltcor = atoi (optarg); break; - case '?': - if (optopt != ':' && strchr (clopt, optopt)) - { - jack_error (APPNAME ": Missing argument for '-%c' option.", optopt); - } - else if (isprint (optopt)) - { - jack_error (APPNAME ": Unknown option '-%c'.", optopt); - } - else - { - jack_error (APPNAME ": Unknown option character '0x%02x'.", optopt & 255); - } - jack_error (APPNAME ": Use '-h' to see all options."); - return 1; - default: - return 1; - } - } - return 0; - } - - int parse_options (const char* load_init) - { - int argsz; - int argc = 0; - const char** argv; - char* args = strdup (load_init); - char* token; - char* ptr = args; - char* savep; - - if (!load_init) { - return 0; - } - - argsz = 8; /* random guess at "maxargs" */ - argv = (const char **) malloc (sizeof (char *) * argsz); - - argv[argc++] = APPNAME; - - while (1) { - - if ((token = strtok_r (ptr, " ", &savep)) == NULL) { - break; - } - - if (argc == argsz) { - argsz *= 2; - argv = (const char **) realloc (argv, sizeof (char *) * argsz); - } - - argv[argc++] = token; - ptr = NULL; - } - - return procoptions (argc, argv); - } - - void printinfo (void) - { - int n, k; - double e, r; - Jdata *J; - - n = 0; - k = 99999; - e = r = 0; - while (infoq->rd_avail ()) - { - J = infoq->rd_datap (); - if (J->_state == Jackclient::TERM) - { - jack_error (APPNAME ": Fatal error condition, terminating."); - stop = true; - return; - } - else if (J->_state == Jackclient::WAIT) - { - jack_info (APPNAME ": Detected excessive timing errors, waiting 10 seconds."); - n = 0; - } - else if (J->_state == Jackclient::SYNC0) - { - jack_info (APPNAME ": Starting synchronisation."); - } - else if (v_opt) - { - n++; - e += J->_error; - r += J->_ratio; - if (J->_bstat < k) k = J->_bstat; - } - infoq->rd_commit (); - } - if (n) jack_info (APPNAME ": %8.3lf %10.6lf %5d", e / n, r / n, k); - } - - - Alsa_pcmi *A; - Alsathread *C; - Jackclient *J; - - pthread_t t; - int topts; - - static void* _retry_alsa_pcmi (void *arg) - { - ((zita_a2j*)arg)->retry_alsa_pcmi (); - return NULL; - } - - void retry_alsa_pcmi () - { - Alsa_pcmi *a; - - while (! stop) - { - sleep(1); - - a = new Alsa_pcmi (0, device, 0, fsamp, bsize, nfrag, topts); - if (a->state ()) - { - delete a; - continue; - } - - A = a; - if (v_opt) A->printinfo (); - C = new Alsathread (A, Alsathread::CAPT); - usleep (100*1000); - jack_initialize_part2 (); - jack_info (APPNAME ": Device is now available and has been activated"); - break; - } - - t = 0; - } - -public: - - int - jack_initialize (jack_client_t* client, const char* load_init) - { - int opts; - - if (parse_options (load_init)) { - jack_error (APPNAME ": parse options failed"); - delete this; - return 1; - } - - if (device == 0) - { - help (); - delete this; - return 1; - } - if (rqual < 16) rqual = 16; - if (rqual > 96) rqual = 96; - if ((fsamp < 8000) || (bsize < 16) || (nfrag < 2) || (nchan < 1)) - { - jack_error (APPNAME ": Illegal parameter value(s)."); - delete this; - return 1; - } - - opts = 0; - if (v_opt) opts |= Alsa_pcmi::DEBUG_ALL; - if (L_opt) opts |= Alsa_pcmi::FORCE_16B | Alsa_pcmi::FORCE_2CH; - if (w_opt) - { - J = new Jackclient (client, 0, Jackclient::CAPT, nchan, S_opt, this); - A = new Alsa_pcmi (0, device, 0, fsamp, bsize, nfrag, opts); - - // if device is not available, spawn thread to keep trying - if (A->state ()) - { - delete A; - A = NULL; - topts = opts; - pthread_create (&t, NULL, _retry_alsa_pcmi, this); - jack_info (APPNAME ": Could not open device, will keep trying in new thread..."); - return 0; - } - - // otherwise continue as normal - if (v_opt) A->printinfo (); - C = new Alsathread (A, Alsathread::CAPT); - } - else - { - A = new Alsa_pcmi (0, device, 0, fsamp, bsize, nfrag, opts); - if (A->state ()) - { - jack_error (APPNAME ": Can't open ALSA capture device '%s'.", device); - delete this; - return 1; - } - if (v_opt) A->printinfo (); - if (nchan > A->ncapt ()) - { - nchan = A->ncapt (); - jack_error (APPNAME ": Warning: only %d channels are available.", nchan); - } - C = new Alsathread (A, Alsathread::CAPT); - J = new Jackclient (client, 0, Jackclient::CAPT, nchan, S_opt, this); - } - - usleep (100*1000); - jack_initialize_part2 (); - return 0; - } - - void jack_initialize_part2 () - { - int k, k_del; - double t_alsa; - double t_jack; - double t_del; - - t_alsa = (double) bsize / fsamp; - if (t_alsa < 1e-3) t_alsa = 1e-3; - t_jack = (double) J->bsize () / J->fsamp (); - t_del = t_alsa + t_jack; - k_del = (int)(t_del * fsamp); - for (k = 256; k < 2 * k_del; k *= 2); - audioq = new Lfq_audio (k, nchan); - - if (rqual == 0) - { - k = (fsamp < J->fsamp ()) ? fsamp : J->fsamp (); - if (k < 44100) k = 44100; - rqual = (int)((6.7 * k) / (k - 38000)); - } - if (rqual < 16) rqual = 16; - if (rqual > 96) rqual = 96; - - C->start (audioq, commq, alsaq, J->rprio () + 10); - J->start (audioq, commq, alsaq, infoq, J->fsamp () / (double) fsamp, k_del, ltcor, rqual); - } - - void jack_finish (void* arg) - { - if (t != 0) - { - stop = true; - pthread_join(t, NULL); - } - - commq->wr_int32 (Alsathread::TERM); - usleep (100000); - delete C; - delete A; - delete J; - delete audioq; - } -}; - -extern "C" { - -int -jack_initialize (jack_client_t* client, const char* load_init) -{ - zita_a2j *c = new zita_a2j(); - return c->jack_initialize(client, load_init); -} - -void jack_finish (void* arg) -{ - if (!arg) return; - Jackclient *J = (Jackclient *)arg; - zita_a2j *c = (zita_a2j *)J->getarg(); - c->jack_finish(arg); - delete c; -} - -} /* extern "C" */ diff --git a/tools/zalsa/zita-j2a.cc b/tools/zalsa/zita-j2a.cc deleted file mode 100644 index a341ab68..00000000 --- a/tools/zalsa/zita-j2a.cc +++ /dev/null @@ -1,408 +0,0 @@ -// ---------------------------------------------------------------------------- -// -// Copyright (C) 2012 Fons Adriaensen <fons@linuxaudio.org> -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <http://www.gnu.org/licenses/>. -// -// ---------------------------------------------------------------------------- - - -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <stdio.h> -#include <signal.h> -#include "alsathread.h" -#include "jackclient.h" -#include "lfqueue.h" -#include "jack/control.h" - -static const char *clopt = "hvLSwj:d:r:p:n:c:Q:O:"; - -static void help (void) -{ - jack_info ("%s-%s", APPNAME, VERSION); - jack_info ("(C) 2012-2018 Fons Adriaensen <fons@linuxaudio.org>"); - jack_info ("Use ALSA playback device as a Jack client."); - jack_info ("Options:"); - jack_info (" -h Display this text"); - jack_info (" -j <jackname> Name as Jack client [%s]", APPNAME); - jack_info (" -d <device> ALSA playback device [none]"); - jack_info (" -r <rate> Sample rate [48000]"); - jack_info (" -p <period> Period size [256]"); - jack_info (" -n <nfrags> Number of fragments [2]"); - jack_info (" -c <nchannels> Number of channels [2]"); - jack_info (" -S Word clock sync, no resampling"); - jack_info (" -Q <quality> Resampling quality, 16..96 [auto]"); - jack_info (" -O <samples> Latency adjustment [0]"); - jack_info (" -L Force 16-bit and 2 channels [off]"); - jack_info (" -w Wait until soundcard is available [off]"); - jack_info (" -v Print tracing information [off]"); -} - -class zita_j2a -{ - Lfq_int32 *commq; - Lfq_adata *alsaq; - Lfq_jdata *infoq; - Lfq_audio *audioq; - bool stop; - bool v_opt; - bool L_opt; - bool S_opt; - bool w_opt; - char *jname; - char *device; - int fsamp; - int bsize; - int nfrag; - int nchan; - int rqual; - int ltcor; - -public: - - zita_j2a() - { - commq = new Lfq_int32(16); - alsaq = new Lfq_adata(256); - infoq = new Lfq_jdata(256); - audioq = 0; - stop = false; - v_opt = false; - L_opt = false; - S_opt = false; - w_opt = false; - jname = strdup(APPNAME); - device = 0; - fsamp = 48000; - bsize = 128; - nfrag = 2; - nchan = 2; - rqual = 0; - ltcor = 0; - A = 0; - P = 0; - J = 0; - t = 0; - } - -private: - - int procoptions (int ac, const char *av []) - { - int k; - - optind = 1; - opterr = 0; - while ((k = getopt (ac, (char **) av, (char *) clopt)) != -1) - { - if (optarg && (*optarg == '-')) - { - jack_error (APPNAME ": Missing argument for '-%c' option.", k); - jack_error (APPNAME ": Use '-h' to see all options."); - return 1; - } - switch (k) - { - case 'h' : help (); return 1; - case 'v' : v_opt = true; break; - case 'L' : L_opt = true; break; - case 'S' : S_opt = true; break; - case 'w' : w_opt = true; break; - case 'j' : jname = optarg; break; - case 'd' : device = optarg; break; - case 'r' : fsamp = atoi (optarg); break; - case 'p' : bsize = atoi (optarg); break; - case 'n' : nfrag = atoi (optarg); break; - case 'c' : nchan = atoi (optarg); break; - case 'Q' : rqual = atoi (optarg); break; - case 'O' : ltcor = atoi (optarg); break; - case '?': - if (optopt != ':' && strchr (clopt, optopt)) - { - jack_error (APPNAME ": Missing argument for '-%c' option.", optopt); - } - else if (isprint (optopt)) - { - jack_error (APPNAME ": Unknown option '-%c'.", optopt); - } - else - { - jack_error (APPNAME ": Unknown option character '0x%02x'.", optopt & 255); - } - jack_error (APPNAME ": Use '-h' to see all options."); - return 1; - default: - return 1; - } - } - - return 0; - } - - int parse_options (const char* load_init) - { - int argsz; - int argc = 0; - const char** argv; - char* args = strdup (load_init); - char* token; - char* ptr = args; - char* savep; - - if (!load_init) { - return 0; - } - - argsz = 8; /* random guess at "maxargs" */ - argv = (const char **) malloc (sizeof (char *) * argsz); - - argv[argc++] = APPNAME; - - while (1) { - - if ((token = strtok_r (ptr, " ", &savep)) == NULL) { - break; - } - - if (argc == argsz) { - argsz *= 2; - argv = (const char **) realloc (argv, sizeof (char *) * argsz); - } - - argv[argc++] = token; - ptr = NULL; - } - - return procoptions (argc, argv); - } - - void printinfo (void) - { - int n, k; - double e, r; - Jdata *J; - - n = 0; - k = 99999; - e = r = 0; - while (infoq->rd_avail ()) - { - J = infoq->rd_datap (); - if (J->_state == Jackclient::TERM) - { - jack_info (APPNAME ": Fatal error condition, terminating."); - stop = true; - return; - } - else if (J->_state == Jackclient::WAIT) - { - jack_info (APPNAME ": Detected excessive timing errors, waiting 10 seconds."); - n = 0; - } - else if (J->_state == Jackclient::SYNC0) - { - jack_info (APPNAME ": Starting synchronisation."); - } - else if (v_opt) - { - n++; - e += J->_error; - r += J->_ratio; - if (J->_bstat < k) k = J->_bstat; - } - infoq->rd_commit (); - } - if (n) jack_info ("%8.3lf %10.6lf %5d", e / n, r / n, k); - } - - Alsa_pcmi *A; - Alsathread *P; - Jackclient *J; - - pthread_t t; - int topts; - - static void* _retry_alsa_pcmi (void *arg) - { - ((zita_j2a*)arg)->retry_alsa_pcmi (); - return NULL; - } - - void retry_alsa_pcmi () - { - Alsa_pcmi *a; - - while (! stop) - { - sleep(1); - - a = new Alsa_pcmi (device, 0, 0, fsamp, bsize, nfrag, topts); - if (a->state ()) - { - delete a; - continue; - } - - A = a; - if (v_opt) A->printinfo (); - P = new Alsathread (A, Alsathread::PLAY); - usleep (100*1000); - jack_initialize_part2 (); - jack_info (APPNAME ": Device is now available and has been activated"); - break; - } - - t = 0; - } - -public: - - int jack_initialize (jack_client_t* client, const char* load_init) - { - int opts; - - if (parse_options (load_init)) { - delete this; - return 1; - } - - if (device == 0) - { - help (); - delete this; - return 1; - } - if (rqual < 16) rqual = 16; - if (rqual > 96) rqual = 96; - if ((fsamp < 8000) || (bsize < 16) || (nfrag < 2) || (nchan < 1)) - { - jack_error (APPNAME ": Illegal parameter value(s)."); - delete this; - return 1; - } - - opts = 0; - if (v_opt) opts |= Alsa_pcmi::DEBUG_ALL; - if (L_opt) opts |= Alsa_pcmi::FORCE_16B | Alsa_pcmi::FORCE_2CH; - if (w_opt) - { - J = new Jackclient (client, 0, Jackclient::PLAY, nchan, S_opt, this); - - // if device is not available, spawn thread to keep trying - A = new Alsa_pcmi (device, 0, 0, fsamp, bsize, nfrag, opts); - if (A->state ()) - { - delete A; - A = NULL; - topts = opts; - pthread_create (&t, NULL, _retry_alsa_pcmi, this); - jack_info (APPNAME ": Could not open device, will keep trying in new thread..."); - return 0; - } - - // otherwise continue as normal - if (v_opt) A->printinfo (); - P = new Alsathread (A, Alsathread::PLAY); - } - else - { - A = new Alsa_pcmi (device, 0, 0, fsamp, bsize, nfrag, opts); - if (A->state ()) - { - jack_error (APPNAME ": Can't open ALSA playback device '%s'.", device); - delete this; - return 1; - } - if (v_opt) A->printinfo (); - if (nchan > A->nplay ()) - { - nchan = A->nplay (); - jack_error (APPNAME ": Warning: only %d channels are available.", nchan); - } - P = new Alsathread (A, Alsathread::PLAY); - J = new Jackclient (client, 0, Jackclient::PLAY, nchan, S_opt, this); - } - - usleep (100*1000); - jack_initialize_part2 (); - return 0; - } - - void jack_initialize_part2 () - { - int k, k_del; - double t_jack; - double t_alsa; - double t_del; - - t_alsa = (double) bsize / fsamp; - if (t_alsa < 1e-3) t_alsa = 1e-3; - t_jack = (double) J->bsize () / J->fsamp (); - t_del = t_alsa + t_jack; - k_del = (int)(t_del * fsamp); - for (k = 256; k < 2 * k_del; k *= 2); - audioq = new Lfq_audio (k, nchan); - - if (rqual == 0) - { - k = (fsamp < J->fsamp ()) ? fsamp : J->fsamp (); - if (k < 44100) k = 44100; - rqual = (int)((6.7 * k) / (k - 38000)); - } - if (rqual < 16) rqual = 16; - if (rqual > 96) rqual = 96; - - P->start (audioq, commq, alsaq, J->rprio () + 10); - J->start (audioq, commq, alsaq, infoq, (double) fsamp / J->fsamp (), k_del, ltcor, rqual); - } - - void jack_finish (void* arg) - { - if (t != 0) - { - stop = true; - pthread_join(t, NULL); - t = 0; - } - - commq->wr_int32 (Alsathread::TERM); - usleep (100*1000); - delete P; - delete A; - delete J; - delete audioq; - } -}; - -extern "C" { - -int -jack_initialize (jack_client_t* client, const char* load_init) -{ - zita_j2a *c = new zita_j2a(); - return c->jack_initialize(client, load_init); -} - -void jack_finish (void* arg) -{ - if (!arg) return; - Jackclient *J = (Jackclient *)arg; - zita_j2a *c = (zita_j2a *)J->getarg(); - c->jack_finish(arg); - delete c; -} - -} /* extern "C" */ |