Switch to unified view

a/src/alsadirect.cpp b/src/alsadirect.cpp
...
...
185
    } else {
185
    } else {
186
        return 0;
186
        return 0;
187
    }
187
    }
188
}
188
}
189
189
190
class Filter {
191
public:
192
#define FNS 128
193
    Filter() : old(0.0), sum(0.0), idx(0) {
194
        for (int i = 0; i < FNS; i++) {
195
            buf[i] = 1.0;
196
            sum += buf[i];
197
        }
198
    }
199
    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;
210
        sum += ns;
211
        if (idx == FNS)
212
            idx = 0;
213
        sum -= buf[idx];
214
        return sum/FNS;
215
#endif
216
    }
217
    float old;
218
    float buf[FNS];
219
    float sum;
220
    int idx;
221
};
222
190
static void *audioEater(void *cls)
223
static void *audioEater(void *cls)
191
{
224
{
192
    LOGDEB("audioEater: alsadirect\n");
225
    LOGDEB("audioEater: alsadirect\n");
193
    AudioEater::Context *ctxt = (AudioEater::Context*)cls;
226
    AudioEater::Context *ctxt = (AudioEater::Context*)cls;
194
227
...
...
199
    ctxt = 0;
232
    ctxt = 0;
200
233
201
    qinit = false;
234
    qinit = false;
202
235
203
    float samplerate_ratio = 1.0;
236
    float samplerate_ratio = 1.0;
237
    Filter filter;
204
238
205
    int src_error = 0;
239
    int src_error = 0;
206
    SRC_STATE *src_state = 0;
240
    SRC_STATE *src_state = 0;
207
    SRC_DATA src_data;
241
    SRC_DATA src_data;
208
    memset(&src_data, 0, sizeof(src_data));
242
    memset(&src_data, 0, sizeof(src_data));
...
...
231
                queue->workerExit();
265
                queue->workerExit();
232
                return (void *)1;
266
                return (void *)1;
233
            }
267
            }
234
            // BEST_QUALITY yields approx 25% cpu on a core i7
268
            // BEST_QUALITY yields approx 25% cpu on a core i7
235
            // 4770T. Obviously too much, actually might not be
269
            // 4770T. Obviously too much, actually might not be
236
            // sustainable (it's quite 100% of 1 cpu)
270
            // sustainable (it's almost 100% of 1 cpu)
237
            // MEDIUM_QUALITY is around 10%
271
            // MEDIUM_QUALITY is around 10%
238
            // FASTEST is 4-5%. Given that this is process-wide, probably
272
            // FASTEST is 4-5%. Given that this measured for the full
239
            // a couple % in fact.
273
            // process, probably a couple % for the conversion in fact.
240
            // To be re-evaluated on the pi... FASTEST is 30% CPU on a Pi2
274
            // Rpi: FASTEST is 30% CPU on a Pi2 with USB
241
            // with USB audio. Curiously it's 25-30% on a Pi1 with i2s audio.
275
            // audio. Curiously it's 25-30% on a Pi1 with i2s audio.
242
            src_state = src_new(SRC_SINC_FASTEST, tsk->m_chans, &src_error);
276
            src_state = src_new(SRC_SINC_FASTEST, tsk->m_chans, &src_error);
243
277
244
            // Number of frames per buffer. This is constant for a
278
            // Number of frames per buffer. This is constant for a
245
            // given stream (depends on fe, Songcast buffers are 10mS)
279
            // given stream (depends on fe, Songcast buffers are 10mS)
246
            bufframes = tsk->m_bytes / (tsk->m_chans * (tsk->m_bits/8));
280
            bufframes = tsk->m_bytes / (tsk->m_chans * (tsk->m_bits/8));
...
...
249
        // Computing the samplerate conversion factor. We want to keep
283
        // Computing the samplerate conversion factor. We want to keep
250
        // the queue at its target size to control the delay. The
284
        // the queue at its target size to control the delay. The
251
        // present hack sort of works but has a tendancy to keep
285
        // present hack sort of works but has a tendancy to keep
252
        // oscillating (with a very small amplitude). It should be
286
        // oscillating (with a very small amplitude). It should be
253
        // replaced by a proper filter
287
        // replaced by a proper filter
254
        float qs = alsaqueue.qsize();
288
        float qs;
255
        if (qinit) {
289
        if (qinit) {
256
            qs = alsaqueue.qsize() + alsadelay() / bufframes;
290
            qs = alsaqueue.qsize() + alsadelay() / bufframes;
257
            float t = ((qstarg - qs) / qstarg);
291
            float t = ((qstarg - qs) / qstarg);
258
            float adj = t * t;
292
            float adj = t * t;
259
            if (qs < qstarg) {
293
            if (qs < qstarg) {
...
...
264
                samplerate_ratio = 1.0 - adj;
298
                samplerate_ratio = 1.0 - adj;
265
                if (samplerate_ratio < 0.9) 
299
                if (samplerate_ratio < 0.9) 
266
                    samplerate_ratio = 0.9;
300
                    samplerate_ratio = 0.9;
267
            }
301
            }
268
        } else {
302
        } else {
303
            qs = alsaqueue.qsize();
269
            samplerate_ratio = 1.0;
304
            samplerate_ratio = 1.0;
270
        }
305
        }
306
        samplerate_ratio = filter(samplerate_ratio);
271
307
272
        unsigned int tot_samples = tsk->m_bytes / (tsk->m_bits/8);
308
        unsigned int tot_samples = tsk->m_bytes / (tsk->m_bits/8);
273
        if ((unsigned int)src_data.input_frames < tot_samples / tsk->m_chans) {
309
        if ((unsigned int)src_data.input_frames < tot_samples / tsk->m_chans) {
274
            int bytes = tot_samples * sizeof(float);
310
            int bytes = tot_samples * sizeof(float);
275
            src_data.data_in = (float *)realloc(src_data.data_in, bytes);
311
            src_data.data_in = (float *)realloc(src_data.data_in, bytes);
...
...
279
            src_data.output_frames = 2 * src_data.input_frames;
315
            src_data.output_frames = 2 * src_data.input_frames;
280
        }
316
        }
281
        src_data.src_ratio = samplerate_ratio;
317
        src_data.src_ratio = samplerate_ratio;
282
        src_data.end_of_input = 0;
318
        src_data.end_of_input = 0;
283
        
319
        
320
        // Data always comes in host order, because this is what we
321
        // request from upstream. 24 and 32 bits are untested.
284
        switch (tsk->m_bits) {
322
        switch (tsk->m_bits) {
285
        case 16: {
323
        case 16: 
324
        {
286
            const short *sp = (const short *)tsk->m_buf;
325
            const short *sp = (const short *)tsk->m_buf;
287
            for (unsigned int i = 0; i < tot_samples; i++) {
326
            for (unsigned int i = 0; i < tot_samples; i++) {
288
                src_data.data_in[i] = *sp++;
327
                src_data.data_in[i] = *sp++;
289
            }
328
            }
329
        }
290
            break;
330
        break;
291
        }
292
        case 24:
331
        case 24: 
332
        {
333
            const unsigned char *icp = (const unsigned char *)tsk->m_buf;
334
            unsigned int o;
335
            unsigned char *ocp = (unsigned char *)&o;
336
            ocp[3] = 0;
337
            for (unsigned int i = 0; i < tot_samples; i++) {
338
                ocp[0] = *icp++;
339
                ocp[1] = *icp++;
340
                ocp[2] = *icp++;
341
                src_data.data_in[i] = o;
342
            }
343
        }
344
        break;
293
        case 32:
345
        case 32: 
346
        {
347
            const int *ip = (const int *)tsk->m_buf;
348
            for (unsigned int i = 0; i < tot_samples; i++) {
349
                src_data.data_in[i] = *ip++;
350
            }
351
        }
352
        break;
294
        default:
353
        default:
295
            abort();
354
            LOGERR("audioEater:alsa: bad m_bits: " << tsk->m_bits << endl);
355
            alsaqueue.setTerminateAndWait();
356
            queue->workerExit();
357
            return (void *)1;
296
        }
358
        }
359
297
        int ret = src_process(src_state, &src_data);
360
        int ret = src_process(src_state, &src_data);
298
        if (ret) {
361
        if (ret) {
299
            LOGERR("src_process: " << src_strerror(ret) << endl);
362
            LOGERR("src_process: " << src_strerror(ret) << endl);
300
            continue;
363
            continue;
301
        }
364
        }
365
302
        {
366
        {
303
            static int cnt;
367
            static int cnt;
304
            if (cnt++ == 100) {
368
            if (cnt++ == 103) {
305
                LOGDEB("samplerate: " 
369
                LOGDEB("audioEater:alsa: " 
306
                       " qstarg " << qstarg <<
370
                       " qstarg " << qstarg <<
307
                       " iqsz " << alsaqueue.qsize() <<
371
                       " iqsz " << alsaqueue.qsize() <<
308
                       " qsize " << int(qs) << 
372
                       " qsize " << int(qs) << 
309
                       " ratio " << samplerate_ratio <<
373
                       " ratio " << samplerate_ratio <<
310
                       " in " << src_data.input_frames << 
374
                       " in " << src_data.input_frames << 
311
                       " consumed " << src_data.input_frames_used << 
375
                       " consumed " << src_data.input_frames_used << 
312
                       " out " << src_data.output_frames_gen << endl);
376
                       " out " << src_data.output_frames_gen << endl);
313
                cnt = 0;
377
                cnt = 0;
314
            }
378
            }
315
        }
379
        }
380
316
        tot_samples =  src_data.output_frames_gen * tsk->m_chans;
381
        tot_samples =  src_data.output_frames_gen * tsk->m_chans;
317
        if (src_data.output_frames_gen > src_data.input_frames) {
382
        if (src_data.output_frames_gen > src_data.input_frames) {
318
            tsk->m_bytes = tot_samples * (tsk->m_bits / 8);
383
            tsk->m_bytes = tot_samples * (tsk->m_bits / 8);
319
            tsk->m_buf = (char *)realloc(tsk->m_buf, tsk->m_bytes);
384
            tsk->m_buf = (char *)realloc(tsk->m_buf, tsk->m_bytes);
320
            if (!tsk->m_buf) 
385
            if (!tsk->m_buf) {
321
                abort();
386
                LOGERR("audioEater:alsa: out of memory\n");
387
                alsaqueue.setTerminateAndWait();
388
                queue->workerExit();
389
                return (void *)1;
322
        }
390
            }
391
        }
323
392
324
        // Output is always 16 bits lsb first for now. We should
393
        // Convert floats buffer into output which is always 16LE for
325
        // probably dither the lsb ?
394
        // now. We should probably dither the lsb ?
326
        tsk->m_bits = 16;
395
        tsk->m_bits = 16;
327
        {
396
        {
328
#ifdef WORDS_BIGENDIAN
397
#ifdef WORDS_BIGENDIAN
329
            unsigned char *ocp = (unsigned char *)tsk->m_buf;
398
            unsigned char *ocp = (unsigned char *)tsk->m_buf;
330
            short val;
399
            short val;