Switch to unified view

a/sc2src/alsadirect.cpp b/sc2src/alsadirect.cpp
...
...
31
#define BSWAP16(X) (X)
31
#define BSWAP16(X) (X)
32
#endif
32
#endif
33
33
34
#include <iostream>
34
#include <iostream>
35
#include <queue>
35
#include <queue>
36
#include <mutex>
36
#include <alsa/asoundlib.h>
37
#include <alsa/asoundlib.h>
37
38
38
#include <samplerate.h>
39
#include <samplerate.h>
39
40
40
#include "log.h"
41
#include "log.h"
...
...
60
61
61
/* This is used to disable sample rate conversion until playing is actually 
62
/* This is used to disable sample rate conversion until playing is actually 
62
   started */
63
   started */
63
static bool qinit = false;
64
static bool qinit = false;
64
65
66
/* Alsa. Locked while we work with it */
67
static std::mutex alsa_mutex;
65
static snd_pcm_t *pcm = nullptr;
68
static snd_pcm_t *pcm;
66
static string alsadevice("default");
69
static string alsadevice("default");
70
static snd_pcm_sframes_t alsa_delay;
67
71
68
static bool alsa_init(const string& dev, AudioMessage *tsk);
69
static void alsa_close();
70
71
// From MPD recovery code
72
// From MPD recovery code.
73
// Note: no locking: we're called from alsawriter holding the lock.
72
static int alsa_recover(snd_pcm_t *pcm, int err)
74
static int alsa_recover(snd_pcm_t *pcm, int err)
73
{
75
{
74
    if (err == -EPIPE) {
76
    if (err == -EPIPE) {
75
        LOGDEB("Underrun on ALSA device\n");
77
        LOGDEB("Underrun on ALSA device\n");
76
    } else if (err == -ESTRPIPE) {
78
    } else if (err == -ESTRPIPE) {
...
...
122
static unsigned int period_time = 50000;
124
static unsigned int period_time = 50000;
123
// Set after initializing the driver
125
// Set after initializing the driver
124
static snd_pcm_uframes_t periodframes;
126
static snd_pcm_uframes_t periodframes;
125
static snd_pcm_uframes_t bufferframes;
127
static snd_pcm_uframes_t bufferframes;
126
128
129
static bool alsa_init(const string& dev, AudioMessage *tsk);
130
127
static void *alsawriter(void *p)
131
static void *alsawriter(void *p)
128
{
132
{
129
    while (true) {
133
    while (true) {
130
        if (!qinit) {
134
        if (!qinit) {
131
            if (!alsaqueue.waitminsz(qstarg)) {
135
            if (!alsaqueue.waitminsz(qstarg)) {
...
...
140
            // TBD: reset alsa?
144
            // TBD: reset alsa?
141
            alsaqueue.workerExit();
145
            alsaqueue.workerExit();
142
            return (void*)1;
146
            return (void*)1;
143
        }
147
        }
144
148
149
        std::unique_lock<std::mutex> lock(alsa_mutex);
145
        if (pcm == nullptr) {
150
        if (pcm == nullptr) {
146
            if (!alsa_init(alsadevice, tsk)) {
151
            if (!alsa_init(alsadevice, tsk)) {
147
                LOGERR("alsawriter: error alsa init\n");
148
                alsaqueue.workerExit();
152
                alsaqueue.workerExit();
149
                return (void*)1;
153
                return (void*)1;
150
            }
154
            }
151
        }
155
        }
152
156
...
...
154
        char *buf = tsk->m_buf;
158
        char *buf = tsk->m_buf;
155
        // This loop is copied from the alsa sample, but it should not
159
        // This loop is copied from the alsa sample, but it should not
156
        // be necessary, in synchronous mode, alsa is supposed to
160
        // be necessary, in synchronous mode, alsa is supposed to
157
        // perform complete writes except for errors or interrupts
161
        // perform complete writes except for errors or interrupts
158
        while (frames > 0) {
162
        while (frames > 0) {
163
            if (g_quitrequest) {
164
                break;
165
            }
166
            if (snd_pcm_delay(pcm, &alsa_delay) < 0) {
167
                alsa_delay = 0;
168
            }
159
//            LOGDEB("alsawriter: avail frames " << snd_pcm_avail(pcm) <<
169
//            LOGDEB("alsawriter: avail frames " << snd_pcm_avail(pcm) <<
160
//                   " writing " << frames << endl);
170
//                   " writing " << frames << endl);
161
            snd_pcm_sframes_t ret =  snd_pcm_writei(pcm, tsk->m_buf, frames);
171
            snd_pcm_sframes_t ret =  snd_pcm_writei(pcm, tsk->m_buf, frames);
162
            if (ret != int(frames)) {
172
            if (ret != int(frames)) {
163
                LOGERR("snd_pcm_writei(" << frames <<" frames) failed: ret: " <<
173
                LOGERR("snd_pcm_writei(" << frames <<" frames) failed: ret: " <<
...
...
311
321
312
    return true;
322
    return true;
313
323
314
error:
324
error:
315
    LOGERR("alsa_init: " << cmd << " error:" << snd_strerror(err) << endl);
325
    LOGERR("alsa_init: " << cmd << " error:" << snd_strerror(err) << endl);
326
    alsa_close();
316
    return false;
327
    return false;
317
}
328
}
318
329
319
static void alsa_close()
330
void alsa_close()
320
{
331
{
321
    LOGDEB("alsawriter: alsa close\n");
332
    LOGDEB("alsawriter: alsa close\n");
333
    std::unique_lock<std::mutex> lock(alsa_mutex);
334
    alsa_delay = 0;
322
    if (pcm != nullptr) {
335
    if (pcm != nullptr) {
323
        snd_pcm_close(pcm);
336
        snd_pcm_close(pcm);
324
        pcm = nullptr;
337
        pcm = nullptr;
325
    }
338
    }
326
}
327
328
// Current in-driver delay in samples
329
static int alsadelay()
330
{
331
    snd_pcm_sframes_t delay;
332
    if (pcm != nullptr) {
333
        if (snd_pcm_delay(pcm, &delay) >= 0) {
334
            return delay;
335
        }
336
    }
337
    return 0;
338
}
339
}
339
340
340
class Filter {
341
class Filter {
341
public:
342
public:
342
#define FNS 128
343
#define FNS 128
...
...
413
414
414
    double qs = 0.0;
415
    double qs = 0.0;
415
    
416
    
416
    if (qinit) {
417
    if (qinit) {
417
        // Qsize in frames. This is the variable to control
418
        // Qsize in frames. This is the variable to control
418
        qs = alsaqueue.qsize() * bufframes + alsadelay();
419
        qs = alsaqueue.qsize() * bufframes + alsa_delay;
419
        // Error term
420
        // Error term
420
        double qstargframes = qstarg * bufframes;
421
        double qstargframes = qstarg * bufframes;
421
        double et =  ((qstargframes - qs) / qstargframes);
422
        double et =  ((qstargframes - qs) / qstargframes);
422
423
423
        // Integral. Not used, made it worse each time I tried.
424
        // Integral. Not used, made it worse each time I tried.
...
...
721
    size_t src_input_bytes = 0;
722
    size_t src_input_bytes = 0;
722
    
723
    
723
    alsaqueue.start(1, alsawriter, 0);
724
    alsaqueue.start(1, alsawriter, 0);
724
725
725
    while (true) {
726
    while (true) {
727
        if (g_quitrequest) {
728
            goto done;
729
        }
726
        AudioMessage *tsk = 0;
730
        AudioMessage *tsk = 0;
727
        // Get new data
731
        // Get new data
728
        if (!queue->take(&tsk)) {
732
        if (!queue->take(&tsk)) {
729
            LOGDEB("audioEater: alsadirect: queue take failed\n");
733
            LOGDEB("audioEater: alsadirect: queue take failed\n");
730
            goto done;
734
            goto done;
731
        }
735
        }
736
        alsaAudioEater.pktcounter++;
737
        
732
        if (tsk->m_bytes == 0 || tsk->m_chans == 0 || tsk->m_bits == 0) {
738
        if (tsk->m_bytes == 0 || tsk->m_chans == 0 || tsk->m_bits == 0) {
733
            LOGDEB("Zero buf\n");
739
            LOGDEB("Zero buf\n");
734
            continue;
740
            continue;
735
        }
741
        }
736
742