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

« back to all changes in this revision

Viewing changes to clalsadrv.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) 2003-2006 Fons Adriaensen <fons.adriaensen@skynet.be>
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 <sys/time.h>
21
 
#include "clalsadrv.h"
22
 
 
23
 
 
24
 
// Public members ----------------------------------------------------------------------
25
 
 
26
 
 
27
 
Alsa_driver::~Alsa_driver (void)
28
 
{
29
 
    snd_pcm_sw_params_free (_capt_swpar);
30
 
    snd_pcm_hw_params_free (_capt_hwpar);
31
 
    snd_pcm_sw_params_free (_play_swpar);
32
 
    snd_pcm_hw_params_free (_play_hwpar);
33
 
 
34
 
    if (_play_handle) snd_pcm_close (_play_handle);
35
 
    if (_capt_handle) snd_pcm_close (_capt_handle);
36
 
    if (_ctrl_handle) snd_ctl_close (_ctrl_handle); 
37
 
}
38
 
 
39
 
 
40
 
Alsa_driver::Alsa_driver (const char        *name,
41
 
                          unsigned int       rate,
42
 
                          snd_pcm_uframes_t  frsize,
43
 
                          unsigned int       nfrags,
44
 
                          bool               play,
45
 
                          bool               capt,
46
 
                          bool               ctrl) :
47
 
    _rate (rate),
48
 
    _frsize (frsize),
49
 
    _nfrags (nfrags),   
50
 
    _play_handle (0),
51
 
    _capt_handle (0),
52
 
    _ctrl_handle (0),
53
 
    _play_hwpar (0),
54
 
    _play_swpar (0),
55
 
    _capt_hwpar (0),
56
 
    _capt_swpar (0),
57
 
    _play_nchan (0),
58
 
    _capt_nchan (0),
59
 
    _play_npfd (0),
60
 
    _capt_npfd (0),
61
 
    _synced (false),
62
 
    _stat (-1)
63
 
{
64
 
    int                  err, dir;
65
 
    snd_ctl_card_info_t *card;
66
 
 
67
 
    if (play)
68
 
    {
69
 
        if (snd_pcm_open (&_play_handle, name, SND_PCM_STREAM_PLAYBACK, 0) < 0)
70
 
        {
71
 
            _play_handle = 0;
72
 
            fprintf (stderr, "Alsa_driver: Cannot open PCM device %s for playback.\n", name);
73
 
        }
74
 
    }
75
 
    
76
 
    if (capt)
77
 
    {
78
 
        if (snd_pcm_open (&_capt_handle, name, SND_PCM_STREAM_CAPTURE, 0) < 0)
79
 
        {
80
 
            _capt_handle = 0;
81
 
            fprintf (stderr, "Alsa_driver: Cannot open PCM device %s for capture.\n", name);
82
 
        }
83
 
    }
84
 
 
85
 
    if (! _play_handle && ! _capt_handle) return;
86
 
 
87
 
    if (ctrl)
88
 
    {
89
 
        snd_ctl_card_info_alloca (&card);
90
 
 
91
 
        if ((err = snd_ctl_open (&_ctrl_handle, name, 0)) < 0)
92
 
        {
93
 
            fprintf  (stderr, "Alse_driver: ctl_open(): %s\n", snd_strerror (err));
94
 
            return;
95
 
        }
96
 
        
97
 
        if ((err = snd_ctl_card_info (_ctrl_handle, card)) < 0)
98
 
        {
99
 
            fprintf  (stderr, "Alsa_driver: ctl_card_info(): %s\n", snd_strerror (err));
100
 
            return;
101
 
        }
102
 
    }
103
 
 
104
 
    // check capabilities here
105
 
 
106
 
    if (_play_handle)
107
 
    {
108
 
        if (snd_pcm_hw_params_malloc (&_play_hwpar) < 0)
109
 
        {
110
 
            fprintf (stderr, "Alsa_driver: can't allocate playback hw params\n");
111
 
            return;
112
 
        }
113
 
 
114
 
        if (snd_pcm_sw_params_malloc (&_play_swpar) < 0)
115
 
        {
116
 
            fprintf (stderr, "Alsa_driver: can't allocate playback sw params\n");
117
 
            return;
118
 
        }
119
 
 
120
 
        if (set_hwpar (_play_handle, _play_hwpar, "playback", &_play_nchan) < 0) return;
121
 
 
122
 
        if (_play_nchan > MAXPLAY)
123
 
        {
124
 
            fprintf (stderr, "Alsa_driver: detected %d playback channels, reset to %d.\n", _play_nchan, MAXPLAY);
125
 
            _play_nchan = MAXPLAY;     
126
 
        }
127
 
 
128
 
        if (set_swpar (_play_handle, _play_swpar, "playback") < 0) return;
129
 
    }
130
 
        
131
 
    if (_capt_handle)
132
 
    {
133
 
        if (snd_pcm_hw_params_malloc (&_capt_hwpar) < 0)
134
 
        {
135
 
            fprintf (stderr, "Alsa_driver: can't allocate capture hw params\n");
136
 
            return;
137
 
        }
138
 
 
139
 
        if (snd_pcm_sw_params_malloc (&_capt_swpar) < 0)
140
 
        {
141
 
            fprintf (stderr, "Alsa_driver: can't allocate capture sw params\n");
142
 
            return;
143
 
        }
144
 
 
145
 
        if (set_hwpar (_capt_handle, _capt_hwpar, "capture", &_capt_nchan) < 0) return;
146
 
 
147
 
        if (_capt_nchan > MAXCAPT)
148
 
        {
149
 
            fprintf (stderr, "Alsa_driver: detected %d capture channels, reset to %d\n", _capt_nchan, MAXCAPT);
150
 
            _capt_nchan = MAXCAPT;     
151
 
        }
152
 
 
153
 
        if (set_swpar (_capt_handle, _capt_swpar, "capture") < 0) return;
154
 
    }
155
 
 
156
 
    if (_play_handle)
157
 
    {
158
 
        if (snd_pcm_hw_params_get_rate (_play_hwpar, &rate, &dir) || (rate != rate) || dir)
159
 
        {
160
 
            fprintf (stderr, "Alsa_driver: can't get requested sample rate for playback.\n"); 
161
 
            return;
162
 
        }
163
 
 
164
 
        if (snd_pcm_hw_params_get_period_size (_play_hwpar, &frsize, &dir) || (frsize != _frsize) || dir)
165
 
        {
166
 
            fprintf (stderr, "Alsa_driver: can't get requested period size for playback.\n"); 
167
 
            return;
168
 
        }
169
 
 
170
 
        if (snd_pcm_hw_params_get_periods (_play_hwpar, &nfrags, &dir) || (nfrags != _nfrags) || dir)
171
 
        {
172
 
            fprintf (stderr, "Alsa_driver: can't get requested number of periods for playback.\n"); 
173
 
            return;
174
 
        }
175
 
 
176
 
        snd_pcm_hw_params_get_format (_play_hwpar, &_play_format);
177
 
        snd_pcm_hw_params_get_access (_play_hwpar, &_play_access);
178
 
 
179
 
        switch (_play_format)
180
 
        {
181
 
        case SND_PCM_FORMAT_S32_LE:
182
 
            _clear_func = clear_32le;     
183
 
            _play_func  = play_32le;     
184
 
            break;
185
 
 
186
 
        case SND_PCM_FORMAT_S24_3LE:
187
 
            _clear_func = clear_24le;     
188
 
            _play_func  = play_24le;     
189
 
            break;
190
 
 
191
 
        case SND_PCM_FORMAT_S16_LE:
192
 
            _clear_func = clear_16le;     
193
 
            _play_func  = play_16le;     
194
 
            break;
195
 
 
196
 
        default:
197
 
            fprintf (stderr, "Alsa_driver: can't handle playback sample format.\n"); 
198
 
            return;
199
 
        }
200
 
 
201
 
       _play_npfd = snd_pcm_poll_descriptors_count (_play_handle);
202
 
    }
203
 
 
204
 
    if (_capt_handle)
205
 
    {
206
 
        if (snd_pcm_hw_params_get_rate (_capt_hwpar, &rate, &dir) || (rate != _rate) || dir)
207
 
        {
208
 
            fprintf (stderr, "Alsa_driver: can't get requested sample rate for capture.\n"); 
209
 
            return;
210
 
        }
211
 
 
212
 
        if (snd_pcm_hw_params_get_period_size (_capt_hwpar, &frsize, &dir) || (frsize != _frsize) || dir)
213
 
        {
214
 
            fprintf (stderr, "Alsa_driver: can't get requested period size for capture.\n"); 
215
 
            return;
216
 
        }
217
 
 
218
 
        if (snd_pcm_hw_params_get_periods (_capt_hwpar, &nfrags, &dir) || (nfrags != _nfrags) || dir)
219
 
        {
220
 
            fprintf (stderr, "Alsa_driver: can't get requested number of periods for capture.\n"); 
221
 
            return;
222
 
        }
223
 
 
224
 
        if (_play_handle) _synced = ! snd_pcm_link (_play_handle, _capt_handle);
225
 
 
226
 
        snd_pcm_hw_params_get_format (_capt_hwpar, &_capt_format);
227
 
        snd_pcm_hw_params_get_access (_capt_hwpar, &_capt_access);
228
 
 
229
 
        switch (_capt_format)
230
 
        {
231
 
        case SND_PCM_FORMAT_S32_LE:
232
 
            _capt_func  = capt_32le;     
233
 
            break;
234
 
 
235
 
        case SND_PCM_FORMAT_S24_3LE:
236
 
            _capt_func  = capt_24le;     
237
 
            break;
238
 
 
239
 
        case SND_PCM_FORMAT_S16_LE:
240
 
            _capt_func  = capt_16le;     
241
 
            break;
242
 
 
243
 
        default:
244
 
            fprintf (stderr, "Alsa_driver: can't handle capture sample format.\n"); 
245
 
            return;
246
 
        }
247
 
 
248
 
        _capt_npfd = snd_pcm_poll_descriptors_count (_capt_handle);
249
 
    }
250
 
 
251
 
    if (_play_npfd + _capt_npfd > MAXPFD)
252
 
    {
253
 
        fprintf (stderr, "Alsa_driver: interface requires more than %d pollfd\n", MAXPFD);
254
 
        return;
255
 
    }      
256
 
 
257
 
    _stat = 0;
258
 
}       
259
 
 
260
 
 
261
 
int Alsa_driver::pcm_start (void)
262
 
{
263
 
    unsigned int i, j, n;
264
 
    int          err;
265
 
 
266
 
    if (_play_handle)
267
 
    {
268
 
        n = snd_pcm_avail_update (_play_handle);
269
 
        if (n != _frsize * _nfrags)
270
 
        {
271
 
            fprintf  (stderr, "Alsa_driver: full buffer not available at start.\n");
272
 
            return -1;
273
 
        }
274
 
 
275
 
        for (i = 0; i < _nfrags; i++)
276
 
        {     
277
 
            play_init (_frsize);
278
 
            for (j = 0; j < _play_nchan; j++) clear_chan (j, _frsize);
279
 
            play_done (_frsize);
280
 
        }
281
 
                
282
 
        if ((err = snd_pcm_start (_play_handle)) < 0)
283
 
        {
284
 
            fprintf (stderr, "Alsa_driver: pcm_start(play): %s.\n", snd_strerror (err));
285
 
            return -1;
286
 
        }
287
 
    }
288
 
 
289
 
    if (_capt_handle && !_synced && ((err = snd_pcm_start (_capt_handle)) < 0))
290
 
    {
291
 
        fprintf (stderr, "Alsa_driver: pcm_start(capt): %s.\n", snd_strerror (err));
292
 
        return -1;
293
 
    }
294
 
 
295
 
    return 0;
296
 
}
297
 
 
298
 
 
299
 
int Alsa_driver::pcm_stop (void)
300
 
{
301
 
    int err;
302
 
 
303
 
    if (_play_handle && ((err = snd_pcm_drop (_play_handle)) < 0))
304
 
    {
305
 
        fprintf (stderr, "Alsa_driver: pcm_drop(play): %s.\n", snd_strerror (err));
306
 
        return -1;
307
 
    }
308
 
 
309
 
    if (_capt_handle && !_synced && ((err = snd_pcm_drop (_capt_handle)) < 0))
310
 
    {
311
 
        fprintf (stderr, "Alsa_driver: pcm_drop(capt): %s.\n", snd_strerror (err));
312
 
        return -1;
313
 
    }
314
 
 
315
 
    return 0;
316
 
}
317
 
 
318
 
 
319
 
snd_pcm_sframes_t Alsa_driver::pcm_wait (void)
320
 
{
321
 
    bool              need_capt;
322
 
    bool              need_play;
323
 
    snd_pcm_sframes_t capt_av;
324
 
    snd_pcm_sframes_t play_av;
325
 
    unsigned short    rev;
326
 
    int               i, r, n1, n2;
327
 
 
328
 
    _stat = 0;
329
 
    need_capt = _capt_handle ? true : false;
330
 
    need_play = _play_handle ? true : false;
331
 
 
332
 
    while (need_play || need_capt)
333
 
    {
334
 
        n1 = 0;
335
 
        if (need_play)
336
 
        {
337
 
            snd_pcm_poll_descriptors (_play_handle, _pfd, _play_npfd);
338
 
            n1 += _play_npfd;
339
 
        }
340
 
        n2 = n1;
341
 
        if (need_capt)
342
 
        {
343
 
            snd_pcm_poll_descriptors (_capt_handle, _pfd + n1, _capt_npfd);
344
 
            n2 += _capt_npfd;
345
 
        }
346
 
 
347
 
        for (i = 0; i < n2; i++) _pfd [i].events |= POLLERR;
348
 
 
349
 
        r = poll (_pfd, n2, 1000);
350
 
        if (r < 0)
351
 
        {
352
 
            if (errno == EINTR)
353
 
            {
354
 
                _stat = -1;
355
 
                return 0;
356
 
            }
357
 
            fprintf (stderr, "Alsa_driver: poll(): %s\n.", strerror (errno));
358
 
            _stat = -2;
359
 
            return 0;
360
 
        }
361
 
        if (r == 0)
362
 
        { 
363
 
            fprintf (stderr, "Alsa_driver: poll timed out\n.");
364
 
            _stat = -3;
365
 
            return 0;
366
 
        }               
367
 
 
368
 
        if (need_play)
369
 
        {
370
 
            snd_pcm_poll_descriptors_revents (_play_handle, _pfd, n1, &rev);
371
 
            if (rev & POLLERR)
372
 
            {
373
 
                fprintf (stderr, "Alsa_driver: error on playback pollfd.\n");
374
 
                _stat = -4;
375
 
                recover ();
376
 
                return 0;
377
 
            }
378
 
            if (rev & POLLOUT) need_play = false;
379
 
        }
380
 
        if (need_capt)
381
 
        {
382
 
            snd_pcm_poll_descriptors_revents (_capt_handle, _pfd + n1, n2 - n1, &rev);
383
 
            if (rev & POLLERR)
384
 
            {
385
 
                fprintf (stderr, "Alsa_driver: error on capture pollfd.\n");
386
 
                _stat = -4;
387
 
                recover ();
388
 
                return 0;
389
 
            }
390
 
            if (rev & POLLIN) need_capt = false;
391
 
        }
392
 
    }
393
 
 
394
 
    play_av = 999999;
395
 
    if (_play_handle && (play_av = snd_pcm_avail_update (_play_handle)) < 0)
396
 
    {
397
 
        _stat = -5;
398
 
        recover ();
399
 
        return 0;
400
 
    }
401
 
 
402
 
    capt_av = 999999;
403
 
    if (_capt_handle && (capt_av = snd_pcm_avail_update (_capt_handle)) < 0)
404
 
    {
405
 
        _stat = -6;
406
 
        recover ();
407
 
        return 0;
408
 
    }
409
 
 
410
 
    return (capt_av < play_av) ? capt_av : play_av;
411
 
}
412
 
 
413
 
 
414
 
int Alsa_driver::pcm_idle (snd_pcm_uframes_t len)
415
 
{
416
 
    unsigned int       i;
417
 
    snd_pcm_uframes_t  n, k;
418
 
 
419
 
    if (_capt_handle)
420
 
    {
421
 
        n = len;
422
 
        while (n)  
423
 
        {
424
 
            k = capt_init (n);
425
 
            capt_done (k);
426
 
            n -= k;
427
 
        }
428
 
    }
429
 
 
430
 
    if (_play_handle)
431
 
    {
432
 
        n = len;
433
 
        while (n)
434
 
        {
435
 
            k = play_init (n);
436
 
            for (i = 0; i < _play_nchan; i++) clear_chan (i, k);
437
 
            play_done (k);
438
 
            n -= k;
439
 
        }
440
 
    }
441
 
 
442
 
    return 0;
443
 
}
444
 
 
445
 
 
446
 
int Alsa_driver::play_init (snd_pcm_uframes_t len)
447
 
{
448
 
    unsigned int                   i;
449
 
    const snd_pcm_channel_area_t   *a;
450
 
    int                            err;
451
 
 
452
 
    if ((err = snd_pcm_mmap_begin (_play_handle, &a, &_play_offs, &len)) < 0)
453
 
    {
454
 
        fprintf (stderr, "Alsa_driver: snd_pcm_mmap_begin(play): %s.\n", snd_strerror (err)); 
455
 
        return -1;
456
 
    }
457
 
 
458
 
    _play_step = (a->step) >> 3;
459
 
    for (i = 0; i < _play_nchan; i++, a++)
460
 
    {
461
 
        _play_ptr [i] = (char *) a->addr + ((a->first + a->step * _play_offs) >> 3);
462
 
    } 
463
 
   
464
 
    return len;
465
 
}
466
 
 
467
 
 
468
 
int Alsa_driver::capt_init (snd_pcm_uframes_t len)
469
 
{
470
 
    unsigned int                  i;
471
 
    const snd_pcm_channel_area_t  *a;
472
 
    int                           err;
473
 
 
474
 
    if ((err = snd_pcm_mmap_begin (_capt_handle, &a, &_capt_offs, &len)) < 0)
475
 
    {
476
 
        fprintf (stderr, "Alsa_driver: snd_pcm_mmap_begin(capt): %s.\n", snd_strerror (err)); 
477
 
        return -1;
478
 
    }
479
 
 
480
 
    _capt_step = (a->step) >> 3;
481
 
    for (i = 0; i < _capt_nchan; i++, a++)
482
 
    {
483
 
        _capt_ptr [i] = (char *) a->addr + ((a->first + a->step * _capt_offs) >> 3);
484
 
    } 
485
 
   
486
 
    return len;
487
 
}
488
 
 
489
 
 
490
 
void Alsa_driver::printinfo (void)
491
 
{
492
 
    fprintf (stderr, "playback :");
493
 
    if (_play_handle)
494
 
    {
495
 
        fprintf (stderr, "\n  nchan  : %d\n", _play_nchan);
496
 
        fprintf (stderr, "  rate   : %d\n", _rate);
497
 
        fprintf (stderr, "  frsize : %ld\n", _frsize);
498
 
        fprintf (stderr, "  nfrags : %d\n", _nfrags);
499
 
        fprintf (stderr, "  format : %s\n", snd_pcm_format_name (_play_format));
500
 
    }
501
 
    else fprintf (stderr, " not enabled\n");
502
 
    fprintf (stderr, "capture  :");
503
 
    if (_capt_handle)
504
 
    {
505
 
        fprintf (stderr, "\n  nchan  : %d\n", _capt_nchan);
506
 
        fprintf (stderr, "  rate   : %d\n", _rate);
507
 
        fprintf (stderr, "  frsize : %ld\n", _frsize);
508
 
        fprintf (stderr, "  nfrags : %d\n", _nfrags);
509
 
        fprintf (stderr, "  format : %s\n", snd_pcm_format_name (_capt_format));
510
 
        if (_play_handle) fprintf (stderr, "%s\n", _synced ? "synced" : "not synced");
511
 
    }
512
 
    else fprintf (stderr, " not enabled\n");
513
 
}
514
 
 
515
 
 
516
 
// Private members ---------------------------------------------------------------------
517
 
 
518
 
 
519
 
int Alsa_driver::set_hwpar (snd_pcm_t *handle,  snd_pcm_hw_params_t *hwpar, const char *sname, unsigned int *nchan)
520
 
{
521
 
    int           err;
522
 
    unsigned int  n;
523
 
 
524
 
    if ((err = snd_pcm_hw_params_any (handle, hwpar)) < 0)
525
 
    {
526
 
        fprintf (stderr, "Alsa_driver: no %s hw configurations available: %s.\n", sname, snd_strerror (err));
527
 
        return -1;
528
 
    }
529
 
 
530
 
    if ((err = snd_pcm_hw_params_set_periods_integer (handle, hwpar)) < 0)
531
 
    {
532
 
        fprintf (stderr, "Alsa_driver: can't set %s period size to integral value.\n", sname);
533
 
        return -1;
534
 
    }
535
 
 
536
 
    if (   ((err = snd_pcm_hw_params_set_access (handle, hwpar, SND_PCM_ACCESS_MMAP_NONINTERLEAVED)) < 0)
537
 
        && ((err = snd_pcm_hw_params_set_access (handle, hwpar, SND_PCM_ACCESS_MMAP_INTERLEAVED)) < 0))
538
 
    {
539
 
        fprintf (stderr, "Alsa_driver: the %s interface doesn't support mmap-based access.\n", sname);
540
 
        return -1;
541
 
    }
542
 
 
543
 
    if (   ((err = snd_pcm_hw_params_set_format (handle, hwpar, SND_PCM_FORMAT_S32)) < 0)
544
 
        && ((err = snd_pcm_hw_params_set_format (handle, hwpar, SND_PCM_FORMAT_S24_3LE)) < 0)
545
 
        && ((err = snd_pcm_hw_params_set_format (handle, hwpar, SND_PCM_FORMAT_S16)) < 0))
546
 
    {
547
 
        fprintf (stderr, "Alsa_driver: the %s interface doesn't support 32, 24 or 16 bit access.\n.", sname);
548
 
        return -1;
549
 
    }
550
 
 
551
 
    if ((err = snd_pcm_hw_params_set_rate (handle, hwpar, _rate, 0)) < 0)
552
 
    {
553
 
        fprintf (stderr, "Alsa_driver: can't set %s sample rate to %u.\n", sname, _rate);
554
 
        return -1;
555
 
    }
556
 
 
557
 
    snd_pcm_hw_params_get_channels_max (hwpar, nchan);
558
 
 
559
 
    if (*nchan > 1024)
560
 
    { 
561
 
       fprintf (stderr, "Alsa_driver: detected more than 1024 %s channnels, reset to 2.\n", sname);
562
 
       *nchan = 2;     
563
 
    }                           
564
 
 
565
 
    if ((err = snd_pcm_hw_params_set_channels (handle, hwpar, *nchan)) < 0)
566
 
    {
567
 
        fprintf (stderr, "Alsa_driver: can't set %s channel count to %u.\n", sname, *nchan);
568
 
        return -1;
569
 
    }
570
 
 
571
 
 
572
 
    if ((err = snd_pcm_hw_params_set_period_size (handle, hwpar, _frsize, 0)) < 0)
573
 
    {
574
 
        fprintf (stderr, "Alsa_driver: can't set %s period size to %lu.\n", sname, _frsize);
575
 
        return -1;
576
 
    }
577
 
 
578
 
    // This is to handle recent ALSA releases creating a default device with
579
 
    // a large number of periods...
580
 
    n = _nfrags; 
581
 
    snd_pcm_hw_params_set_periods_min (handle, hwpar, &n, NULL);
582
 
    if (_nfrags < n) _nfrags = n; 
583
 
 
584
 
    if ((err = snd_pcm_hw_params_set_periods_near (handle, hwpar, &_nfrags, 0)) < 0)
585
 
    {
586
 
        fprintf (stderr, "Alsa_driver: can't set %s periods to %u.\n", sname, _nfrags);
587
 
        return -1;
588
 
    }
589
 
        
590
 
    if ((err = snd_pcm_hw_params_set_buffer_size (handle, hwpar, _frsize * _nfrags)) < 0)
591
 
    {
592
 
        fprintf (stderr, "Alsa_driver: can't set %s buffer length to %lu.\n", sname, _frsize * _nfrags);
593
 
        return -1;
594
 
    }
595
 
 
596
 
    if ((err = snd_pcm_hw_params (handle, hwpar)) < 0)
597
 
    {
598
 
        fprintf (stderr, "Alsa_driver: can't set %s hardware parameters.\n", sname);
599
 
        return -1;
600
 
    }
601
 
 
602
 
    return 0;
603
 
}
604
 
 
605
 
 
606
 
int Alsa_driver::set_swpar (snd_pcm_t *handle, snd_pcm_sw_params_t *swpar, const char *sname) 
607
 
{
608
 
    int err;
609
 
 
610
 
    snd_pcm_sw_params_current (handle, swpar);
611
 
 
612
 
    if ((err = snd_pcm_sw_params_set_tstamp_mode (handle, swpar, SND_PCM_TSTAMP_MMAP)) < 0)
613
 
    {
614
 
        fprintf (stderr, "Alsa_driver: can't set %s timestamp mode to %u.\n", sname, SND_PCM_TSTAMP_MMAP);
615
 
        return -1;
616
 
    }
617
 
 
618
 
    if ((err = snd_pcm_sw_params_set_avail_min (handle, swpar, _frsize)) < 0)
619
 
    {
620
 
        fprintf (stderr, "Alsa_driver: can't set %s availmin to %lu.\n", sname, _frsize);
621
 
        return -1;
622
 
    }
623
 
 
624
 
    if ((err = snd_pcm_sw_params (handle, swpar)) < 0)
625
 
    {
626
 
        fprintf (stderr, "Alsa_driver: can't set %s software parameters.\n", sname);
627
 
        return -1;
628
 
    }
629
 
 
630
 
    return 0;
631
 
}
632
 
 
633
 
 
634
 
int Alsa_driver::recover (void)
635
 
{
636
 
    int                err; 
637
 
    snd_pcm_status_t  *stat;
638
 
 
639
 
    snd_pcm_status_alloca (&stat);
640
 
 
641
 
    if ((err = snd_pcm_status (_play_handle ? _play_handle : _capt_handle, stat)) < 0)
642
 
    {
643
 
        fprintf (stderr, "Alsa_driver: pcm_status(): %s\n",  snd_strerror (err));
644
 
    }
645
 
    else if (snd_pcm_status_get_state (stat) == SND_PCM_STATE_XRUN)
646
 
    {
647
 
        struct timeval tnow, trig;
648
 
 
649
 
        gettimeofday (&tnow, 0);
650
 
        snd_pcm_status_get_trigger_tstamp (stat, &trig);
651
 
        fprintf (stderr, "Alsa_driver: stat = %02x, xrun of at least %8.3lf ms\n", _stat,
652
 
                 1e3 * tnow.tv_sec - 1e3 * trig.tv_sec + 1e-3 * tnow.tv_usec - 1e-3 * trig.tv_usec);
653
 
    }
654
 
 
655
 
    if (pcm_stop ()) return -1;
656
 
 
657
 
    if (_play_handle && ((err = snd_pcm_prepare (_play_handle)) < 0))
658
 
    {
659
 
        fprintf (stderr, "Alsa_driver: pcm_prepare(play): %s\n", snd_strerror (err));
660
 
        return -1;
661
 
    }
662
 
 
663
 
    if (_capt_handle && !_synced && ((err = snd_pcm_prepare (_capt_handle)) < 0))
664
 
    {
665
 
        fprintf (stderr, "Alsa_driver: pcm_prepare(capt): %s\n", snd_strerror (err));
666
 
        return -1;
667
 
    }
668
 
 
669
 
    if (pcm_start ()) return -1;
670
 
 
671
 
    return 0;
672
 
}       
673
 
 
674
 
 
675
 
// Static members ----------------------------------------------------------------------
676
 
 
677
 
 
678
 
char *Alsa_driver::clear_16le (char *dst, int step, int nfrm)
679
 
{
680
 
    while (nfrm--)
681
 
    {
682
 
        *((short int *) dst) = 0;
683
 
        dst += step;
684
 
    }  
685
 
    return dst;
686
 
}
687
 
 
688
 
char *Alsa_driver::play_16le (const float *src, char *dst, int step, int nfrm)
689
 
{
690
 
    float     s;
691
 
    short int d;
692
 
 
693
 
    while (nfrm--)
694
 
    {
695
 
        s = *src++;
696
 
        if      (s >  1) d = 0x7fff;
697
 
        else if (s < -1) d = 0x8001;
698
 
        else d = (short int)(0x7fff * s); 
699
 
        *((short int *) dst) = d;
700
 
        dst += step;
701
 
    } 
702
 
    return dst; 
703
 
}
704
 
 
705
 
const char *Alsa_driver::capt_16le (const char *src, float *dst, int step, int nfrm )
706
 
{
707
 
    float     d;
708
 
    short int s;
709
 
 
710
 
    while (nfrm--)
711
 
    {
712
 
        s = *((short int *) src);
713
 
        d = (float) s / 0x7fff;  
714
 
        *dst++ = d;  
715
 
        src += step;
716
 
    }  
717
 
    return src;
718
 
}
719
 
 
720
 
char *Alsa_driver::clear_24le (char *dst, int step, int nfrm)
721
 
{
722
 
    while (nfrm--)
723
 
    {
724
 
        dst [0] = 0;
725
 
        dst [1] = 0;
726
 
        dst [2] = 0;
727
 
        dst += step;
728
 
    }
729
 
    return dst;  
730
 
}
731
 
 
732
 
char *Alsa_driver::play_24le (const float *src, char *dst, int step, int nfrm)
733
 
{
734
 
    float   s;
735
 
    int     d;
736
 
 
737
 
    while (nfrm--)
738
 
    {
739
 
        s = *src++;
740
 
        if      (s >  1) d = 0x007fffff;
741
 
        else if (s < -1) d = 0x00800001;  
742
 
        else d = (int)(0x007fffff * s); 
743
 
        dst [0] = d;
744
 
        dst [1] = d >> 8;
745
 
        dst [2] = d >> 16;
746
 
        dst += step;
747
 
    }  
748
 
    return dst;
749
 
}
750
 
 
751
 
const char *Alsa_driver::capt_24le (const char *src, float *dst, int step, int nfrm)
752
 
{
753
 
    float   d;
754
 
    int     s;
755
 
 
756
 
    while (nfrm--)
757
 
    {
758
 
        s  =  src [0] & 0xFF;
759
 
        s += (src [1] & 0xFF) << 8;  
760
 
        s += (src [2] & 0xFF) << 16;
761
 
        if (s & 0x00800000) s-= 0x01000000;  
762
 
        d = (float) s / 0x007fffff;  
763
 
        *dst++ = d;  
764
 
        src += step;
765
 
    } 
766
 
    return src;
767
 
}
768
 
 
769
 
 
770
 
char *Alsa_driver::clear_32le (char *dst, int step, int nfrm)
771
 
{
772
 
    while (nfrm--)
773
 
    {
774
 
        *((int *) dst) = 0;
775
 
        dst += step;
776
 
    }
777
 
    return dst;  
778
 
}
779
 
 
780
 
char *Alsa_driver::play_32le (const float *src, char *dst, int step, int nfrm)
781
 
{
782
 
    float   s;
783
 
    int     d;
784
 
 
785
 
    while (nfrm--)
786
 
    {
787
 
        s = *src++;
788
 
        if      (s >  1) d = 0x007fffff;
789
 
        else if (s < -1) d = 0x00800001;  
790
 
        else d = (int)(0x007fffff * s); 
791
 
        *((int *) dst) = d << 8;
792
 
        dst += step;
793
 
    }  
794
 
    return dst;
795
 
}
796
 
 
797
 
const char *Alsa_driver::capt_32le (const char *src, float *dst, int step, int nfrm)
798
 
{
799
 
    float   d;
800
 
    int     s;
801
 
 
802
 
    while (nfrm--)
803
 
    {
804
 
        s = *((int *) src);
805
 
        d = (float) s / 0x7fffff00;  
806
 
        *dst++ = d;  
807
 
        src += step;
808
 
    }  
809
 
    return src;
810
 
}
811
 
 
812