|
a/src/alsadirect.cpp |
|
b/src/alsadirect.cpp |
|
... |
|
... |
16 |
*/
|
16 |
*/
|
17 |
#include "config.h"
|
17 |
#include "config.h"
|
18 |
|
18 |
|
19 |
#include <string.h>
|
19 |
#include <string.h>
|
20 |
#include <sys/types.h>
|
20 |
#include <sys/types.h>
|
|
|
21 |
#include <math.h>
|
21 |
|
22 |
|
22 |
#include <iostream>
|
23 |
#include <iostream>
|
23 |
#include <queue>
|
24 |
#include <queue>
|
24 |
#include <alsa/asoundlib.h>
|
25 |
#include <alsa/asoundlib.h>
|
25 |
|
26 |
|
|
... |
|
... |
79 |
snd_pcm_prepare(pcm);
|
80 |
snd_pcm_prepare(pcm);
|
80 |
}
|
81 |
}
|
81 |
} else {
|
82 |
} else {
|
82 |
qinit = true;
|
83 |
qinit = true;
|
83 |
}
|
84 |
}
|
|
|
85 |
delete tsk;
|
84 |
}
|
86 |
}
|
85 |
}
|
87 |
}
|
86 |
|
88 |
|
87 |
static bool alsa_init(const string& dev, AudioMessage *tsk)
|
89 |
static bool alsa_init(const string& dev, AudioMessage *tsk)
|
88 |
{
|
90 |
{
|
|
... |
|
... |
195 |
buf[i] = 1.0;
|
197 |
buf[i] = 1.0;
|
196 |
sum += buf[i];
|
198 |
sum += buf[i];
|
197 |
}
|
199 |
}
|
198 |
}
|
200 |
}
|
199 |
float operator()(float ns) {
|
201 |
float operator()(float ns) {
|
200 |
#if 0
|
|
|
201 |
if (old == 0.0) {
|
|
|
202 |
old = ns;
|
|
|
203 |
} else {
|
|
|
204 |
old = (old + ns) / 2;
|
|
|
205 |
}
|
|
|
206 |
return old;
|
|
|
207 |
#endif
|
|
|
208 |
#if 1
|
|
|
209 |
buf[idx++] = ns;
|
202 |
buf[idx++] = ns;
|
210 |
sum += ns;
|
203 |
sum += ns;
|
211 |
if (idx == FNS)
|
204 |
if (idx == FNS)
|
212 |
idx = 0;
|
205 |
idx = 0;
|
213 |
sum -= buf[idx];
|
206 |
sum -= buf[idx];
|
214 |
return sum/FNS;
|
207 |
return sum/FNS;
|
215 |
#endif
|
|
|
216 |
}
|
208 |
}
|
217 |
float old;
|
209 |
float old;
|
218 |
float buf[FNS];
|
210 |
float buf[FNS];
|
219 |
float sum;
|
211 |
float sum;
|
220 |
int idx;
|
212 |
int idx;
|
|
... |
|
... |
240 |
SRC_STATE *src_state = 0;
|
232 |
SRC_STATE *src_state = 0;
|
241 |
SRC_DATA src_data;
|
233 |
SRC_DATA src_data;
|
242 |
memset(&src_data, 0, sizeof(src_data));
|
234 |
memset(&src_data, 0, sizeof(src_data));
|
243 |
|
235 |
|
244 |
alsaqueue.start(1, alsawriter, 0);
|
236 |
alsaqueue.start(1, alsawriter, 0);
|
|
|
237 |
|
|
|
238 |
// Integral term. We do not use it at the moment
|
|
|
239 |
// double it = 0;
|
245 |
|
240 |
|
246 |
while (true) {
|
241 |
while (true) {
|
247 |
AudioMessage *tsk = 0;
|
242 |
AudioMessage *tsk = 0;
|
248 |
size_t qsz;
|
243 |
size_t qsz;
|
249 |
if (!queue->take(&tsk, &qsz)) {
|
244 |
if (!queue->take(&tsk, &qsz)) {
|
|
... |
|
... |
280 |
bufframes = tsk->m_bytes / (tsk->m_chans * (tsk->m_bits/8));
|
275 |
bufframes = tsk->m_bytes / (tsk->m_chans * (tsk->m_bits/8));
|
281 |
}
|
276 |
}
|
282 |
|
277 |
|
283 |
// Computing the samplerate conversion factor. We want to keep
|
278 |
// Computing the samplerate conversion factor. We want to keep
|
284 |
// the queue at its target size to control the delay. The
|
279 |
// the queue at its target size to control the delay. The
|
285 |
// present hack sort of works but has a tendancy to keep
|
280 |
// present hack sort of works but could probably benefit from
|
286 |
// oscillating (with a very small amplitude). It should be
|
281 |
// a more scientific approach
|
287 |
// replaced by a proper filter
|
282 |
|
|
|
283 |
// Qsize in songcast buffers. This is the variable to control
|
288 |
float qs;
|
284 |
double qs;
|
|
|
285 |
|
289 |
if (qinit) {
|
286 |
if (qinit) {
|
290 |
qs = alsaqueue.qsize() + alsadelay() / bufframes;
|
287 |
qs = alsaqueue.qsize() + alsadelay() / bufframes;
|
|
|
288 |
// Error term
|
291 |
float t = ((qstarg - qs) / qstarg);
|
289 |
double et = ((qstarg - qs) / qstarg);
|
292 |
float adj = t * t;
|
290 |
|
293 |
if (qs < qstarg) {
|
291 |
// Integral. Not used, made it worse each time I tried
|
|
|
292 |
// it += et;
|
|
|
293 |
|
|
|
294 |
// Error correction coef
|
|
|
295 |
double ce = 0.1;
|
|
|
296 |
|
|
|
297 |
// Integral coef
|
|
|
298 |
//double ci = 0.0001;
|
|
|
299 |
|
|
|
300 |
// Compute command
|
|
|
301 |
double adj = ce * et /* + ci * it*/;
|
|
|
302 |
|
|
|
303 |
// Also tried a quadratic correction, worse.
|
|
|
304 |
// double adj = et * ((et < 0) ? -et : et);
|
|
|
305 |
|
|
|
306 |
// Computed ratio
|
294 |
samplerate_ratio = 1.0 + adj;
|
307 |
samplerate_ratio = 1.0 + adj;
|
295 |
if (samplerate_ratio > 1.1)
|
308 |
|
296 |
samplerate_ratio = 1.1;
|
309 |
// Limit extension
|
297 |
} else {
|
|
|
298 |
samplerate_ratio = 1.0 - adj;
|
|
|
299 |
if (samplerate_ratio < 0.9)
|
310 |
if (samplerate_ratio < 0.9)
|
300 |
samplerate_ratio = 0.9;
|
311 |
samplerate_ratio = 0.9;
|
301 |
}
|
312 |
if (samplerate_ratio > 1.1)
|
|
|
313 |
samplerate_ratio = 1.1;
|
|
|
314 |
|
302 |
} else {
|
315 |
} else {
|
|
|
316 |
// Starting up, wait for more info
|
303 |
qs = alsaqueue.qsize();
|
317 |
qs = alsaqueue.qsize();
|
304 |
samplerate_ratio = 1.0;
|
318 |
samplerate_ratio = 1.0;
|
|
|
319 |
// it = 0;
|
305 |
}
|
320 |
}
|
|
|
321 |
|
|
|
322 |
// Average the rate value to eliminate fast oscillations
|
306 |
samplerate_ratio = filter(samplerate_ratio);
|
323 |
samplerate_ratio = filter(samplerate_ratio);
|
307 |
|
324 |
|
308 |
unsigned int tot_samples = tsk->m_bytes / (tsk->m_bits/8);
|
325 |
unsigned int tot_samples = tsk->m_bytes / (tsk->m_bits/8);
|
309 |
if ((unsigned int)src_data.input_frames < tot_samples / tsk->m_chans) {
|
326 |
if ((unsigned int)src_data.input_frames < tot_samples / tsk->m_chans) {
|
310 |
int bytes = tot_samples * sizeof(float);
|
327 |
int bytes = tot_samples * sizeof(float);
|