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 // ----------------------------------------------------------------------------
25 #include "alsathread.h"
29 Alsathread::Alsathread (Alsa_pcmi
*alsadev
, int mode
) :
33 _fsize (alsadev
->fsize ()),
38 // Compute DLL filter coefficients.
39 _dt
= (double) _fsize
/ _alsadev
->fsamp ();
40 _w1
= 2 * M_PI
* 0.1 * _dt
;
46 Alsathread::~Alsathread (void)
55 _alsadev
->pcm_stop ();
60 int Alsathread::start (Lfq_audio
*audioq
, Lfq_int32
*commq
, Lfq_adata
*alsaq
, int rtprio
)
62 // Start the ALSA thread.
67 if (thr_start (SCHED_FIFO
, rtprio
, 0x10000)) return 1;
72 void Alsathread::send (int k
, double t
)
76 // Send (state, frame count, timestamp) to Jack thread.
77 if (_alsaq
->wr_avail ())
79 D
= _alsaq
->wr_datap ();
88 // The following two functions transfer data between the audio queue
89 // and the ALSA device. Note that we do *not* check the queue's fill
90 // state, and it may overrun or underrun. It actually will in the first
91 // few iterations and in error conditions. This is entirely intentional.
92 // The queue keeps correct read and write counters even in that case,
93 // and the main control loop and error recovery depend on it working
94 // and being used in this way.
96 int Alsathread::capture (void)
101 // Start reading from ALSA device.
102 _alsadev
->capt_init (_fsize
);
105 // Input frames from the ALSA device to the audio queue.
106 // The outer loop takes care of wraparound.
107 for (n
= _fsize
; n
; n
-= k
)
109 p
= _audioq
->wr_datap (); // Audio queue write pointer.
110 k
= _audioq
->wr_linav (); // Number of frames that can be
111 if (k
> n
) k
= n
; // written without wraparound.
112 for (c
= 0; c
< _audioq
->nchan (); c
++)
114 // Copy and interleave one channel.
115 _alsadev
->capt_chan (c
, p
+ c
, k
, _audioq
->nchan ());
117 _audioq
->wr_commit (k
); // Update audio queue state.
120 // Finish reading from ALSA device.
121 _alsadev
->capt_done (_fsize
);
126 int Alsathread::playback (void)
131 // Start writing to ALSA device.
132 _alsadev
->play_init (_fsize
);
136 // Output frames from the audio queue to the ALSA device.
137 // The outer loop takes care of wraparound.
138 for (n
= _fsize
; n
; n
-= k
)
140 p
= _audioq
->rd_datap (); // Audio queue read pointer.
141 k
= _audioq
->rd_linav (); // Number of frames that can
142 if (k
> n
) k
= n
; // be read without wraparound.
143 for (c
= 0; c
< _audioq
->nchan (); c
++)
145 // De-interleave and copy one channel.
146 _alsadev
->play_chan (c
, p
+ c
, k
, _audioq
->nchan ());
148 _audioq
->rd_commit (k
); // Update audio queue state.
151 // Clear all or remaining channels.
152 while (c
< _alsadev
->nplay ()) _alsadev
->clear_chan (c
++, _fsize
);
153 // Finish writing to ALSA device.
154 _alsadev
->play_done (_fsize
);
159 void Alsathread::thr_main (void)
164 _alsadev
->pcm_start ();
165 while (_state
!= TERM
)
167 // Wait for next cycle, then take timestamp.
168 na
= _alsadev
->pcm_wait ();
170 tw
= tjack (jack_get_time ());
171 // Check for errors - requires restart.
172 if (_alsadev
->state () && (na
== 0))
180 // Check for commands from the Jack thread.
181 if (_commq
->rd_avail ())
183 _state
= _commq
->rd_int32 ();
184 if (_state
== PROC
) _first
= true;
185 if (_state
== TERM
) send (0, 0);
188 // We could have more than one period.
193 if (_mode
== PLAY
) nu
+= playback ();
194 else nu
+= capture ();
195 // Update loop condition.
197 // Run the DLL if in PROC state.
202 // Init DLL in first iteration.
204 _dt
= (double) _fsize
/ _alsadev
->fsamp ();
211 // If we have more than one period, use
212 // the time error only for the last one.
213 if (na
>= _fsize
) er
= 0;
214 else er
= tjack_diff (tw
, _t1
);
216 _t1
= tjack_diff (_t1
+ _dt
+ _w1
* er
, 0.0);
222 // Send number of frames used and timestamp to Jack thread.
223 if (_state
== PROC
) send (nu
, _t1
);
225 _alsadev
->pcm_stop ();