~ubuntu-branches/debian/stretch/clalsadrv/stretch

« back to all changes in this revision

Viewing changes to apps/latency.cc

  • Committer: Bazaar Package Importer
  • Author(s): Alessio Treglia
  • Date: 2010-04-17 12:25:13 UTC
  • mfrom: (1.1.4 upstream) (2.1.4 experimental)
  • Revision ID: james.westby@ubuntu.com-20100417122513-vsy32s4vwo8vgzvs
Tags: 2.0.0-2
Upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    Copyright (C) 2010 Fons Adriaensen <fons@kokkinizita.net>
 
3
    
 
4
    This program is free software; you can redistribute it and/or modify
 
5
    it under the terms of the GNU General Public License as published by
 
6
    the Free Software Foundation; either version 2 of the License, or
 
7
    (at your option) any later version.
 
8
 
 
9
    This program is distributed in the hope that it will be useful,
 
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
    GNU General Public License for more details.
 
13
 
 
14
    You should have received a copy of the GNU General Public License
 
15
    along with this program; if not, write to the Free Software
 
16
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
17
*/
 
18
 
 
19
 
 
20
#include <unistd.h>
 
21
#include <stdlib.h>
 
22
#include <string.h>
 
23
#include <stdio.h>
 
24
#include <math.h>
 
25
#include <clthreads.h>
 
26
#include <clalsadrv.h>
 
27
 
 
28
 
 
29
// --------------------------------------------------------------------------------
 
30
 
 
31
 
 
32
class Freq
 
33
{
 
34
public:
 
35
 
 
36
    int   p;
 
37
    int   f;
 
38
    float a;
 
39
    float xa;
 
40
    float ya;
 
41
    float xf;
 
42
    float yf;
 
43
};
 
44
 
 
45
 
 
46
class MTDM
 
47
{
 
48
public:
 
49
 
 
50
    MTDM (void);
 
51
    int process (size_t len, float *inp, float *out);
 
52
    int resolve (void);
 
53
    void invert (void) { _inv ^= 1; }
 
54
    int    inv (void) { return _inv; }
 
55
    double del (void) { return _del; }
 
56
    double err (void) { return _err; }
 
57
 
 
58
private:
 
59
 
 
60
    double  _del;
 
61
    double  _err;
 
62
    int     _cnt;
 
63
    int     _inv;
 
64
    Freq    _freq [5];
 
65
};
 
66
 
 
67
 
 
68
MTDM::MTDM (void) : _cnt (0), _inv (0)
 
69
{
 
70
    int   i;
 
71
    Freq  *F;
 
72
 
 
73
    _freq [0].f = 4096;
 
74
    _freq [1].f =  512;
 
75
    _freq [2].f = 1088;
 
76
    _freq [3].f = 1544;
 
77
    _freq [4].f = 2049;
 
78
 
 
79
    _freq [0].a = 0.2f;
 
80
    _freq [1].a = 0.1f;
 
81
    _freq [2].a = 0.1f;
 
82
    _freq [3].a = 0.1f;
 
83
    _freq [4].a = 0.1f;
 
84
 
 
85
    for (i = 0, F = _freq; i < 5; i++, F++)
 
86
    {
 
87
        F->p = 128;
 
88
        F->xa = F->ya = 0.0f;
 
89
        F->xf = F->yf = 0.0f;
 
90
    }
 
91
}
 
92
 
 
93
 
 
94
int MTDM::process (size_t len, float *ip, float *op)
 
95
{
 
96
    int    i;
 
97
    float  vip, vop, a, c, s;
 
98
    Freq   *F;
 
99
 
 
100
    while (len--)
 
101
    {
 
102
        vop = 0.0f;
 
103
        vip = *ip++;
 
104
        for (i = 0, F = _freq; i < 5; i++, F++)
 
105
        {
 
106
            a = 2 * (float) M_PI * (F->p & 65535) / 65536.0; 
 
107
            F->p += F->f;
 
108
            c =  cosf (a); 
 
109
            s = -sinf (a); 
 
110
            vop += F->a * s;
 
111
            F->xa += s * vip;
 
112
            F->ya += c * vip;
 
113
        } 
 
114
        *op++ = vop;
 
115
        if (++_cnt == 16)
 
116
        {
 
117
            for (i = 0, F = _freq; i < 5; i++, F++)
 
118
            {
 
119
                F->xf += 1e-3f * (F->xa - F->xf + 1e-20);
 
120
                F->yf += 1e-3f * (F->ya - F->yf + 1e-20);
 
121
                F->xa = F->ya = 0.0f;
 
122
            }
 
123
            _cnt = 0;
 
124
        }
 
125
    }
 
126
 
 
127
    return 0;
 
128
}
 
129
 
 
130
 
 
131
int MTDM::resolve (void)
 
132
{
 
133
    int     i, k, m;
 
134
    double  d, e, f0, p;
 
135
    Freq    *F = _freq;
 
136
 
 
137
    if (hypot (F->xf, F->yf) < 0.01) return -1;
 
138
    d = atan2 (F->yf, F->xf) / (2 * M_PI);
 
139
    if (_inv) d += 0.5f;
 
140
    if (d > 0.5f) d -= 1.0f;
 
141
    f0 = _freq [0].f;
 
142
    m = 1;
 
143
    _err = 0.0;
 
144
    for (i = 0; i < 4; i++)
 
145
    {
 
146
        F++;
 
147
        p = atan2 (F->yf, F->xf) / (2 * M_PI) - d * F->f / f0;
 
148
        if (_inv) p += 0.5f;
 
149
        p -= floor (p);
 
150
        p *= 8;
 
151
        k = (int)(floor (p + 0.5));
 
152
        e = fabs (p - k);
 
153
        if (e > _err) _err = e;
 
154
        if (e > 0.4) return 1; 
 
155
        d += m * (k & 7);
 
156
        m *= 8;
 
157
    }  
 
158
    _del = 16 * d;
 
159
 
 
160
    return 0;
 
161
}
 
162
 
 
163
 
 
164
// --------------------------------------------------------------------------------
 
165
 
 
166
 
 
167
static char          playdev [256];
 
168
static char          captdev [256];
 
169
static unsigned long fsamp;
 
170
static unsigned long frsize;
 
171
static unsigned long nfrags;
 
172
static MTDM          mtdm;
 
173
 
 
174
 
 
175
class Audiothr : public P_thread
 
176
{
 
177
public:
 
178
 
 
179
    virtual void thr_main (void);
 
180
 
 
181
private:
 
182
 
 
183
    float *ipbuf;
 
184
    float *opbuf;
 
185
};
 
186
 
 
187
 
 
188
void Audiothr::thr_main (void)
 
189
{
 
190
    Alsa_driver *D;
 
191
    unsigned long k;
 
192
 
 
193
    ipbuf = new float [frsize];
 
194
    opbuf = new float [frsize];
 
195
 
 
196
    D = new Alsa_driver (playdev, captdev, 0, fsamp, frsize, nfrags);
 
197
    if (D->stat ()) 
 
198
    {
 
199
        fprintf (stderr, "Can't open ALSA device\n");
 
200
        delete D;
 
201
        return;
 
202
    }
 
203
    D->printinfo ();
 
204
 
 
205
    D->pcm_start ();
 
206
    while (1)
 
207
    {
 
208
        k = D->pcm_wait ();  
 
209
        while (k >= frsize)
 
210
        {
 
211
            D->capt_init (frsize);
 
212
            D->capt_chan (0, ipbuf, frsize);
 
213
            D->capt_done (frsize);
 
214
 
 
215
            mtdm.process (frsize, ipbuf, opbuf);
 
216
 
 
217
            D->play_init (frsize);
 
218
            D->play_chan (0, opbuf, frsize);              
 
219
            D->play_done (frsize);
 
220
 
 
221
            k -= frsize;
 
222
        }
 
223
    }
 
224
    D->pcm_stop ();
 
225
 
 
226
    delete D;
 
227
}
 
228
 
 
229
 
 
230
// --------------------------------------------------------------------------------
 
231
 
 
232
 
 
233
int main (int ac, char *av [])
 
234
{
 
235
    Audiothr  A;
 
236
    float     t;
 
237
 
 
238
    if (ac < 6)
 
239
    {
 
240
        fprintf (stderr, "alsa-latency <playdev><captdev><fsamp><frsize><nfrags>\n");
 
241
        return 1;
 
242
    }
 
243
 
 
244
    strcpy (playdev, av [1]);
 
245
    strcpy (captdev, av [2]);
 
246
    fsamp  = atoi (av [3]);
 
247
    frsize = atoi (av [4]);
 
248
    nfrags = atoi (av [5]);
 
249
 
 
250
    if (A.thr_start (SCHED_FIFO, -50, 0x20000))
 
251
    {
 
252
        fprintf (stderr, "Can't run in RT mode, trying normal scheduling.\n");
 
253
        if (A.thr_start (SCHED_OTHER, 0, 0x20000))
 
254
        {
 
255
            fprintf (stderr, "Can't start audio thread.\n");
 
256
            return 1;
 
257
        }
 
258
    }
 
259
 
 
260
    t = 1000.0f / fsamp;
 
261
    while (1)
 
262
    {
 
263
        usleep (250000);
 
264
 
 
265
        if (mtdm.resolve () < 0) printf ("Signal below threshold...\n");
 
266
        else 
 
267
        {
 
268
            if (mtdm.err () > 0.3) 
 
269
            {
 
270
                mtdm.invert ();
 
271
                mtdm.resolve ();
 
272
            }
 
273
            printf ("%10.3lf frames %10.3lf ms", mtdm.del (), mtdm.del () * t);
 
274
            if (mtdm.err () > 0.2) printf (" ??");
 
275
            if (mtdm.inv ()) printf (" Inv");
 
276
            printf ("\n");
 
277
        }
 
278
    }
 
279
 
 
280
    return 0;
 
281
}
 
282
 
 
283
 
 
284
// --------------------------------------------------------------------------------
 
285