~ubuntu-branches/ubuntu/wily/japa/wily

« back to all changes in this revision

Viewing changes to source/audio.cc

  • Committer: Package Import Robot
  • Author(s): Jaromír Mikeš
  • Date: 2013-08-07 02:19:42 UTC
  • mfrom: (1.1.2)
  • Revision ID: package-import@ubuntu.com-20130807021942-1rdfsndm8ga103f5
Tags: 0.8.4-1
* New upstream release.
* Fixed URL in watch file.
* Fixed URL and upstream email.
* Fixed homepage URL.
* Set dh/compat 9
* Tighten build-dep on libclthreads.
* Tighten build-dep on libclxclient.
* Bump standards.
* Fix VCS canonical URLs.
* Set Priority optional.
* Don't sign tags.
* Update copyright file.
* Added Keywords entry to desktop files.
* Tune gitignore file to handle rather dir.
* Update man pages.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// -------------------------------------------------------------------------
 
2
//
 
3
//  Copyright (C) 2004-2013 Fons Adriaensen <fons@linuxaudio.org>
 
4
//    
 
5
//  This program is free software; you can redistribute it and/or modify
 
6
//  it under the terms of the GNU General Public License as published by
 
7
//  the Free Software Foundation; either version 2 of the License, or
 
8
//  (at your option) any later version.
 
9
//
 
10
//  This program is distributed in the hope that it will be useful,
 
11
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
//  GNU General Public License for more details.
 
14
//
 
15
//  You should have received a copy of the GNU General Public License
 
16
//  along with this program; if not, write to the Free Software
 
17
//  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
18
//
 
19
// -------------------------------------------------------------------------
 
20
 
 
21
 
 
22
#include <math.h>
 
23
#include "audio.h"
 
24
#include "messages.h"
 
25
 
 
26
 
 
27
Audio::Audio (ITC_ctrl *cmain, const char *name) :
 
28
    A_thread ("Audio"), _jname (name), _cmain (cmain), _run_alsa (0), _run_jack (0),
 
29
    _active (false),
 
30
    _inputA (-1),
 
31
    _inputB (-1),
 
32
    _dataA (0),
 
33
    _dataB (0),
 
34
    _out1 (0),
 
35
    _out2 (0)
 
36
{
 
37
}
 
38
 
 
39
 
 
40
Audio::~Audio (void)
 
41
{
 
42
    if (_run_alsa) close_alsa ();
 
43
    if (_run_jack) close_jack ();
 
44
    delete[] _out1;
 
45
    delete[] _out2;
 
46
}
 
47
 
 
48
 
 
49
void Audio::init (void)
 
50
{
 
51
    _rngen.init (0);
 
52
    _b0 = _b1 = _b2 = _b3 = _b4 = _b5 = _b6 = 0.0f;
 
53
}
 
54
 
 
55
 
 
56
void Audio::init_alsa (const char *playdev, const char *captdev,
 
57
                       int fsamp, int fsize, int nfrags)
 
58
{
 
59
    _run_alsa = true;
 
60
    _alsa_handle = new Alsa_pcmi (playdev, captdev, 0, fsamp, fsize, nfrags);
 
61
    if (_alsa_handle->state () < 0)
 
62
    {
 
63
        fprintf (stderr, "Can't connect to ALSA\n");
 
64
        exit (1);
 
65
    } 
 
66
    _ncapt = _alsa_handle->ncapt ();
 
67
    _nplay = _alsa_handle->nplay ();
 
68
    _fsamp  = fsamp;
 
69
    _fsize = fsize;
 
70
 
 
71
    if (_nplay >= 2)
 
72
    {
 
73
        _out1 = new float [fsize];
 
74
        _out2 = new float [fsize];
 
75
    }
 
76
 
 
77
    init ();
 
78
   
 
79
    _cmain->put_event (EV_MESG, new M_audio (fsamp, _ncapt, _nplay, _jname));
 
80
    _alsa_handle->printinfo ();
 
81
    fprintf (stderr, "Connected to ALSA with %d inputs and %d outputs\n", _ncapt, _nplay); 
 
82
 
 
83
    if (thr_start (SCHED_FIFO, -10, 0x00010000))
 
84
    {
 
85
        fprintf (stderr, "Can't create ALSA thread with RT priority\n");
 
86
        if (thr_start (SCHED_OTHER, 0, 0x00010000))
 
87
        {
 
88
            fprintf (stderr, "Can't create ALSA thread\n");
 
89
            exit (1);
 
90
        }
 
91
    }
 
92
}
 
93
 
 
94
 
 
95
void Audio::close_alsa ()
 
96
{
 
97
//    fprintf (stderr, "Closing ALSA...\n");
 
98
    _run_alsa = false;
 
99
    get_event (1 << EV_EXIT);
 
100
    delete _alsa_handle;
 
101
}
 
102
 
 
103
 
 
104
void Audio::thr_main (void) 
 
105
{
 
106
    unsigned long k, m, n;
 
107
 
 
108
    _alsa_handle->pcm_start ();
 
109
 
 
110
    while (_run_alsa)
 
111
    {
 
112
        k = _alsa_handle->pcm_wait ();  
 
113
        while (k >= _fsize)
 
114
        {
 
115
            if (_ncapt)
 
116
            { 
 
117
                _alsa_handle->capt_init (_fsize);
 
118
 
 
119
                if (_dataA)
 
120
                {
 
121
                    m = _fsize;
 
122
                    n = _size - _dind;
 
123
                    if (m >= n)
 
124
                    {
 
125
                        if (_inputA < 0) memset (_dataA + _dind, 0, n * sizeof (float));
 
126
                        else _alsa_handle->capt_chan (_inputA, _dataA + _dind, n);
 
127
                        if (_inputB < 0) memset (_dataB + _dind, 0, n * sizeof (float));
 
128
                        else 
 
129
                        {
 
130
                            if (_inputB == _inputA) memcpy (_dataB + _dind, _dataA + _dind, n * sizeof (float));
 
131
                            else _alsa_handle->capt_chan (_inputB, _dataB + _dind, n);
 
132
                        }
 
133
                        _dind = 0;
 
134
                        m -= n;
 
135
                    }
 
136
                    if (m)
 
137
                    {
 
138
                        if (_inputA < 0) memset (_dataA + _dind, 0, m * sizeof (float));
 
139
                        else _alsa_handle->capt_chan (_inputA, _dataA + _dind, m);
 
140
                        if (_inputB < 0) memset (_dataB + _dind, 0, m * sizeof (float));
 
141
                        else
 
142
                        {
 
143
                            if (_inputB == _inputA) memcpy (_dataB + _dind, _dataA + _dind, m * sizeof (float));
 
144
                            else _alsa_handle->capt_chan (_inputB, _dataB + _dind, m);
 
145
                        }
 
146
                        _dind += m;
 
147
                    }
 
148
                }
 
149
 
 
150
                _alsa_handle->capt_done (_fsize);
 
151
            }
 
152
 
 
153
            if (_nplay)
 
154
            {
 
155
                _alsa_handle->play_init (_fsize);
 
156
 
 
157
                if (_nplay >= 2)
 
158
                {
 
159
                    gen_noise (_fsize, _out1, _out2);
 
160
                    _alsa_handle->play_chan (0, _out1, _fsize);
 
161
                    _alsa_handle->play_chan (1, _out2, _fsize);
 
162
                }
 
163
 
 
164
                _alsa_handle->play_done (_fsize);
 
165
            }
 
166
 
 
167
            k -= _fsize;
 
168
            _scnt += _fsize;
 
169
        }
 
170
        get_messages ();
 
171
    }
 
172
 
 
173
    _alsa_handle->pcm_stop ();
 
174
    put_event (EV_EXIT);
 
175
}
 
176
 
 
177
 
 
178
void Audio::init_jack (const char *server)
 
179
{
 
180
    char            s [16];
 
181
    int             opts;
 
182
    jack_status_t   stat;
 
183
 
 
184
    opts = JackNoStartServer;
 
185
    if (server) opts |= JackServerName;
 
186
    _jack_handle = jack_client_open (_jname, (jack_options_t)opts, &stat, server);
 
187
    if (!_jack_handle)
 
188
    {
 
189
        fprintf (stderr, "Can't connect to JACK\n");
 
190
        exit (1);
 
191
    }
 
192
 
 
193
    jack_set_process_callback (_jack_handle, jack_static_callback, (void *)this);
 
194
    jack_on_shutdown (_jack_handle, jack_static_shutdown, (void *)this);
 
195
 
 
196
    if (jack_activate (_jack_handle))
 
197
    {
 
198
        fprintf(stderr, "Can't activate JACK");
 
199
        exit (1);
 
200
    }
 
201
    _run_jack = true;
 
202
 
 
203
    _ncapt = 4;
 
204
    for (int i = 0; i < _ncapt; i++)
 
205
    {
 
206
        sprintf(s, "in_%d", i + 1);
 
207
        _jack_in [i] = jack_port_register (_jack_handle, s, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
 
208
    }
 
209
 
 
210
    _nplay = 2;
 
211
    _jack_out [0] = jack_port_register (_jack_handle, "white", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
 
212
    _jack_out [1] = jack_port_register (_jack_handle, "pink",  JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
 
213
 
 
214
    init ();
 
215
    
 
216
    _fsamp = jack_get_sample_rate (_jack_handle);
 
217
    _fsize = jack_get_buffer_size (_jack_handle);
 
218
    _jname = jack_get_client_name (_jack_handle);
 
219
    _cmain->put_event (EV_MESG, new M_audio (_fsamp, _ncapt, _nplay, _jname));
 
220
    _active = true;
 
221
}
 
222
 
 
223
 
 
224
void Audio::close_jack ()
 
225
{
 
226
    jack_deactivate (_jack_handle);
 
227
    jack_client_close (_jack_handle);
 
228
}
 
229
 
 
230
 
 
231
void Audio::jack_static_shutdown (void *arg)
 
232
{
 
233
    return ((Audio *) arg)->jack_shutdown ();
 
234
}
 
235
 
 
236
 
 
237
void Audio::jack_shutdown (void)
 
238
{
 
239
    _cmain->put_event (EV_JACK);
 
240
}
 
241
 
 
242
 
 
243
int Audio::jack_static_callback (jack_nframes_t nframes, void *arg)
 
244
{
 
245
    return ((Audio *) arg)->jack_callback (nframes);
 
246
}
 
247
 
 
248
 
 
249
int Audio::jack_callback (jack_nframes_t nframes)
 
250
{
 
251
    unsigned long  m, n;
 
252
    float  *pA, *pB;
 
253
 
 
254
    if (!_active) return 0;
 
255
    if (_dataA)
 
256
    {
 
257
        pA = (_inputA >= 0) ? (float *)(jack_port_get_buffer (_jack_in [_inputA], nframes)) : 0;
 
258
        pB = (_inputB >= 0) ? (float *)(jack_port_get_buffer (_jack_in [_inputB], nframes)) : 0;
 
259
        m = nframes;
 
260
        n = _size - _dind;
 
261
        while (m >= n)
 
262
        {
 
263
            if (pA)
 
264
            {
 
265
                memcpy (_dataA + _dind, pA, sizeof(float) * n);
 
266
                pA += n;
 
267
            }
 
268
            else  memset (_dataA + _dind, 0,  sizeof(float) * n);
 
269
            if (pB)
 
270
            {
 
271
                memcpy (_dataB + _dind, pB, sizeof(float) * n);
 
272
                pB += n;
 
273
            }
 
274
            else memset (_dataB + _dind, 0,  sizeof(float) * n);
 
275
            m -= n;
 
276
            n = _size;
 
277
            _dind = 0;
 
278
        }
 
279
        if (m)
 
280
        {
 
281
            if (pA) memcpy (_dataA + _dind, pA, sizeof(float) * m);
 
282
            else    memset (_dataA + _dind, 0,  sizeof(float) * m);
 
283
            if (pB) memcpy (_dataB + _dind, pB, sizeof(float) * m);
 
284
            else    memset (_dataB + _dind, 0,  sizeof(float) * m);
 
285
            _dind += m;
 
286
        }
 
287
        _scnt += nframes;
 
288
    }
 
289
 
 
290
    gen_noise (nframes, 
 
291
               (float *)(jack_port_get_buffer (_jack_out [0], nframes)),
 
292
               (float *)(jack_port_get_buffer (_jack_out [1], nframes)));
 
293
 
 
294
    get_messages ();
 
295
 
 
296
    return 0;
 
297
}
 
298
 
 
299
 
 
300
void Audio::gen_noise (int n, float *op1, float *op2 ) 
 
301
{
 
302
    float x;
 
303
 
 
304
    while (n--)
 
305
    {
 
306
        x = _rngen.grandf ();
 
307
        *op1++ = 0.07071f * x;             
 
308
        x *= 0.023f;
 
309
        _b0 = 0.99886f * _b0 + 0.0555179f * x;
 
310
        _b1 = 0.99332f * _b1 + 0.0750759f * x;
 
311
        _b2 = 0.96900f * _b2 + 0.1538520f * x;
 
312
        _b3 = 0.86650f * _b3 + 0.3104856f * x;
 
313
        _b4 = 0.55000f * _b4 + 0.5329522f * x;
 
314
        _b5 = -0.7616f * _b5 - 0.0168980f * x;
 
315
        *op2++ = _b0 + _b1 + _b2 + _b3 + _b4 + _b5 + _b6 + x * 0.5362f;
 
316
        _b6 = x * 0.115926f;
 
317
    }
 
318
}
 
319
 
 
320
 
 
321
void Audio::get_messages (void) 
 
322
{
 
323
    int       k;
 
324
    ITC_mesg *M;
 
325
 
 
326
    if (_dataA)
 
327
    {
 
328
        k = _scnt / _step;
 
329
        if (k && _cmain->put_event_try (EV_TRIG, k) == ITC_ctrl::NO_ERROR) _scnt -= k * _step;
 
330
    }
 
331
   
 
332
    if (get_event_nowait (1 << EV_MESG) == EV_MESG)
 
333
    {
 
334
        M = get_message ();
 
335
        if (M->type () == MT_BUFFP)
 
336
        {
 
337
            M_buffp *Z = (M_buffp *) M; 
 
338
            _dataA = Z->_dataA;
 
339
            _dataB = Z->_dataB;
 
340
            _size  = Z->_size;
 
341
            _step  = Z->_step; 
 
342
            _dind  = 0;
 
343
            _scnt  = 0;
 
344
        }
 
345
        else if (M->type () == MT_INPUT)
 
346
        {
 
347
            M_input *Z = (M_input *) M; 
 
348
            _inputA = Z->_inputA;
 
349
            _inputB = Z->_inputB;
 
350
            if (_inputA >= _ncapt) _inputA = -1; 
 
351
            if (_inputB >= _ncapt) _inputB = -1; 
 
352
        }
 
353
        M->recover ();
 
354
    }
 
355
}
 
356
 
 
357