Merge branch 'master' of https://scm.cri.ensmp.fr/git/Faustine
[Faustine.git] / interpretor / faust-0.9.47mr3 / architecture / audio / alsa-dsp.h
1 /************************************************************************
2
3 IMPORTANT NOTE : this file contains two clearly delimited sections :
4 the ARCHITECTURE section (in two parts) and the USER section. Each section
5 is governed by its own copyright and license. Please check individually
6 each section for license and copyright information.
7 *************************************************************************/
8
9 /*******************BEGIN ARCHITECTURE SECTION (part 1/2)****************/
10
11 /************************************************************************
12 FAUST Architecture File
13 Copyright (C) 2003-2011 GRAME, Centre National de Creation Musicale
14 ---------------------------------------------------------------------
15 This Architecture section is free software; you can redistribute it
16 and/or modify it under the terms of the GNU General Public License
17 as published by the Free Software Foundation; either version 3 of
18 the License, or (at your option) any later version.
19
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; If not, see <http://www.gnu.org/licenses/>.
27
28 EXCEPTION : As a special exception, you may create a larger work
29 that contains this FAUST architecture section and distribute
30 that work under terms of your choice, so long as this FAUST
31 architecture section is not modified.
32
33
34 ************************************************************************
35 ************************************************************************/
36
37 #ifndef __alsa_dsp__
38 #define __alsa_dsp__
39
40 #include <stdio.h>
41 #include <pthread.h>
42 #include <sys/types.h>
43 #include <pwd.h>
44
45 #include <alsa/asoundlib.h>
46 #include "audio.h"
47 #include "dsp.h"
48
49 /**
50 DEFAULT ALSA PARAMETERS CONTROLLED BY ENVIRONMENT VARIABLES
51
52 Some default parameters of Faust's ALSA applications are controlled by the following environment variables :
53
54 FAUST2ALSA_DEVICE = "hw:0"
55 FAUST2ALSA_FREQUENCY= 44100
56 FAUST2ALSA_BUFFER = 1024
57 FAUST2ALSA_PERIODS = 2
58
59 */
60
61 using namespace std;
62
63 // handle 32/64 bits int size issues
64
65 #ifdef __x86_64__
66
67 #define uint32 unsigned int
68 #define uint64 unsigned long int
69
70 #define int32 int
71 #define int64 long int
72
73 #else
74
75 #define uint32 unsigned int
76 #define uint64 unsigned long long int
77
78 #define int32 int
79 #define int64 long long int
80 #endif
81
82 // check 32/64 bits issues are correctly handled
83
84 #define check_error(err) if (err) { printf("%s:%d, alsa error %d : %s\n", __FILE__, __LINE__, err, snd_strerror(err)); exit(1); }
85 #define check_error_msg(err,msg) if (err) { fprintf(stderr, "%s:%d, %s : %s(%d)\n", __FILE__, __LINE__, msg, snd_strerror(err), err); exit(1); }
86 #define display_error_msg(err,msg) if (err) { fprintf(stderr, "%s:%d, %s : %s(%d)\n", __FILE__, __LINE__, msg, snd_strerror(err), err); }
87
88 #define max(x,y) (((x)>(y)) ? (x) : (y))
89 #define min(x,y) (((x)<(y)) ? (x) : (y))
90
91 /**
92 * Used to set the priority and scheduling of the audi#include <sys/types.h>
93 #include <pwd.h>
94 o thread
95 */
96 static bool setRealtimePriority ()
97 {
98 struct passwd * pw;
99 int err;
100 uid_t uid;
101 struct sched_param param;
102
103 uid = getuid ();
104 pw = getpwnam ("root");
105 setuid (pw->pw_uid);
106 param.sched_priority = 50; /* 0 to 99 */
107 err = sched_setscheduler(0, SCHED_RR, &param);
108 setuid (uid);
109 return (err != -1);
110 }
111
112 /******************************************************************************
113 *******************************************************************************
114
115 AUDIO INTERFACE
116
117 *******************************************************************************
118 *******************************************************************************/
119
120 enum { kRead = 1, kWrite = 2, kReadWrite = 3 };
121
122 /**
123 * A convenient class to pass parameters to AudioInterface
124 */
125 class AudioParam
126 {
127 public:
128
129 const char* fCardName;
130 unsigned int fFrequency;
131 unsigned int fBuffering;
132 unsigned int fPeriods;
133
134 unsigned int fSoftInputs;
135 unsigned int fSoftOutputs;
136
137 public :
138 AudioParam() :
139 fCardName("hw:0"),
140 fFrequency(44100),
141 fBuffering(512),
142 fPeriods(2),
143 fSoftInputs(2),
144 fSoftOutputs(2)
145 {}
146
147 AudioParam& cardName(const char* n) { fCardName = n; return *this; }
148 AudioParam& frequency(int f) { fFrequency = f; return *this; }
149 AudioParam& buffering(int fpb) { fBuffering = fpb; return *this; }
150 AudioParam& periods(int p) { fPeriods = p; return *this; }
151 AudioParam& inputs(int n) { fSoftInputs = n; return *this; }
152 AudioParam& outputs(int n) { fSoftOutputs = n; return *this; }
153 };
154
155 /**
156 * An ALSA audio interface
157 */
158 class AudioInterface : public AudioParam
159 {
160 public :
161 snd_pcm_t* fOutputDevice ;
162 snd_pcm_t* fInputDevice ;
163 snd_pcm_hw_params_t* fInputParams;
164 snd_pcm_hw_params_t* fOutputParams;
165
166 snd_pcm_format_t fSampleFormat;
167 snd_pcm_access_t fSampleAccess;
168
169 unsigned int fCardInputs;
170 unsigned int fCardOutputs;
171
172 unsigned int fChanInputs;
173 unsigned int fChanOutputs;
174
175 // interleaved mode audiocard buffers
176 void* fInputCardBuffer;
177 void* fOutputCardBuffer;
178
179 // non interleaved mode audiocard buffers
180 void* fInputCardChannels[256];
181 void* fOutputCardChannels[256];
182
183 // non interleaved mod, floating point software buffers
184 float* fInputSoftChannels[256];
185 float* fOutputSoftChannels[256];
186
187 public :
188
189 const char* cardName() { return fCardName; }
190 int frequency() { return fFrequency; }
191 int buffering() { return fBuffering; }
192 int periods() { return fPeriods; }
193
194 float** inputSoftChannels() { return fInputSoftChannels; }
195 float** outputSoftChannels() { return fOutputSoftChannels; }
196
197
198 AudioInterface(const AudioParam& ap = AudioParam()) : AudioParam(ap)
199 {
200
201 fInputDevice = 0;
202 fOutputDevice = 0;
203 fInputParams = 0;
204 fOutputParams = 0;
205 }
206
207 /**
208 * Open the audio interface
209 */
210 void open()
211 {
212 int err;
213
214 // allocation d'un stream d'entree et d'un stream de sortie
215 err = snd_pcm_open( &fInputDevice, fCardName, SND_PCM_STREAM_CAPTURE, 0 ); check_error(err)
216 err = snd_pcm_open( &fOutputDevice, fCardName, SND_PCM_STREAM_PLAYBACK, 0 ); check_error(err)
217
218 // recherche des parametres d'entree
219 err = snd_pcm_hw_params_malloc ( &fInputParams ); check_error(err);
220 setAudioParams(fInputDevice, fInputParams);
221
222 // recherche des parametres de sortie
223 err = snd_pcm_hw_params_malloc ( &fOutputParams ); check_error(err)
224 setAudioParams(fOutputDevice, fOutputParams);
225
226 // set the number of physical input and output channels close to what we need
227 fCardInputs = fSoftInputs;
228 fCardOutputs = fSoftOutputs;
229
230 snd_pcm_hw_params_set_channels_near(fInputDevice, fInputParams, &fCardInputs);
231 snd_pcm_hw_params_set_channels_near(fOutputDevice, fOutputParams, &fCardOutputs);
232
233 printf("inputs : %u, outputs : %u\n", fCardInputs, fCardOutputs);
234
235 // enregistrement des parametres d'entree-sortie
236
237 err = snd_pcm_hw_params (fInputDevice, fInputParams ); check_error (err);
238 err = snd_pcm_hw_params (fOutputDevice, fOutputParams ); check_error (err);
239
240 //assert(snd_pcm_hw_params_get_period_size(fInputParams,NULL) == snd_pcm_hw_params_get_period_size(fOutputParams,NULL));
241
242 // allocation of alsa buffers
243 if (fSampleAccess == SND_PCM_ACCESS_RW_INTERLEAVED) {
244 fInputCardBuffer = calloc(interleavedBufferSize(fInputParams), 1);
245 fOutputCardBuffer = calloc(interleavedBufferSize(fOutputParams), 1);
246
247 } else {
248 for (unsigned int i = 0; i < fCardInputs; i++) {
249 fInputCardChannels[i] = calloc(noninterleavedBufferSize(fInputParams), 1);
250 }
251 for (unsigned int i = 0; i < fCardOutputs; i++) {
252 fOutputCardChannels[i] = calloc(noninterleavedBufferSize(fOutputParams), 1);
253 }
254
255 }
256
257 // allocation of floating point buffers needed by the dsp code
258
259 fChanInputs = max(fSoftInputs, fCardInputs); assert (fChanInputs < 256);
260 fChanOutputs = max(fSoftOutputs, fCardOutputs); assert (fChanOutputs < 256);
261
262 for (unsigned int i = 0; i < fChanInputs; i++) {
263 fInputSoftChannels[i] = (float*) calloc (fBuffering, sizeof(float));
264 for (unsigned int j = 0; j < fBuffering; j++) {
265 fInputSoftChannels[i][j] = 0.0;
266 }
267 }
268
269 for (unsigned int i = 0; i < fChanOutputs; i++) {
270 fOutputSoftChannels[i] = (float*) calloc (fBuffering, sizeof(float));
271 for (unsigned int j = 0; j < fBuffering; j++) {
272 fOutputSoftChannels[i][j] = 0.0;
273 }
274 }
275 }
276
277 void setAudioParams(snd_pcm_t* stream, snd_pcm_hw_params_t* params)
278 {
279 int err;
280
281 // set params record with initial values
282 err = snd_pcm_hw_params_any ( stream, params );
283 check_error_msg(err, "unable to init parameters")
284
285 // set alsa access mode (and fSampleAccess field) either to non interleaved or interleaved
286
287 err = snd_pcm_hw_params_set_access (stream, params, SND_PCM_ACCESS_RW_NONINTERLEAVED );
288 if (err) {
289 err = snd_pcm_hw_params_set_access (stream, params, SND_PCM_ACCESS_RW_INTERLEAVED );
290 check_error_msg(err, "unable to set access mode neither to non-interleaved or to interleaved");
291 }
292 snd_pcm_hw_params_get_access(params, &fSampleAccess);
293
294
295 // search for 32-bits or 16-bits format
296 err = snd_pcm_hw_params_set_format (stream, params, SND_PCM_FORMAT_S32);
297 if (err) {
298 err = snd_pcm_hw_params_set_format (stream, params, SND_PCM_FORMAT_S16);
299 check_error_msg(err, "unable to set format to either 32-bits or 16-bits");
300 }
301 snd_pcm_hw_params_get_format(params, &fSampleFormat);
302 // set sample frequency
303 snd_pcm_hw_params_set_rate_near (stream, params, &fFrequency, 0);
304
305 // set period and period size (buffering)
306 err = snd_pcm_hw_params_set_period_size (stream, params, fBuffering, 0);
307 check_error_msg(err, "period size not available");
308
309 err = snd_pcm_hw_params_set_periods (stream, params, fPeriods, 0);
310 check_error_msg(err, "number of periods not available");
311 }
312
313 ssize_t interleavedBufferSize (snd_pcm_hw_params_t* params)
314 {
315 _snd_pcm_format format; snd_pcm_hw_params_get_format(params, &format);
316 snd_pcm_uframes_t psize; snd_pcm_hw_params_get_period_size(params, &psize, NULL);
317 unsigned int channels; snd_pcm_hw_params_get_channels(params, &channels);
318 ssize_t bsize = snd_pcm_format_size (format, psize * channels);
319 return bsize;
320 }
321
322 ssize_t noninterleavedBufferSize (snd_pcm_hw_params_t* params)
323 {
324 _snd_pcm_format format; snd_pcm_hw_params_get_format(params, &format);
325 snd_pcm_uframes_t psize; snd_pcm_hw_params_get_period_size(params, &psize, NULL);
326 ssize_t bsize = snd_pcm_format_size (format, psize);
327 return bsize;
328 }
329
330 void close()
331 {}
332
333 /**
334 * Read audio samples from the audio card. Convert samples to floats and take
335 * care of interleaved buffers
336 */
337 void read()
338 {
339 if (fSampleAccess == SND_PCM_ACCESS_RW_INTERLEAVED) {
340
341 int count = snd_pcm_readi(fInputDevice, fInputCardBuffer, fBuffering);
342 if (count<0) {
343 display_error_msg(count, "reading samples");
344 int err = snd_pcm_prepare(fInputDevice);
345 check_error_msg(err, "preparing input stream");
346 }
347
348 if (fSampleFormat == SND_PCM_FORMAT_S16) {
349
350 short* buffer16b = (short*) fInputCardBuffer;
351 for (unsigned int s = 0; s < fBuffering; s++) {
352 for (unsigned int c = 0; c < fCardInputs; c++) {
353 fInputSoftChannels[c][s] = float(buffer16b[c + s*fCardInputs])*(1.0/float(SHRT_MAX));
354 }
355 }
356
357 } else if (fSampleFormat == SND_PCM_FORMAT_S32) {
358
359 int32* buffer32b = (int32*) fInputCardBuffer;
360 for (unsigned int s = 0; s < fBuffering; s++) {
361 for (unsigned int c = 0; c < fCardInputs; c++) {
362 fInputSoftChannels[c][s] = float(buffer32b[c + s*fCardInputs])*(1.0/float(INT_MAX));
363 }
364 }
365 } else {
366
367 printf("unrecognized input sample format : %u\n", fSampleFormat);
368 exit(1);
369 }
370
371 } else if (fSampleAccess == SND_PCM_ACCESS_RW_NONINTERLEAVED) {
372
373 int count = snd_pcm_readn(fInputDevice, fInputCardChannels, fBuffering);
374 if (count<0) {
375 display_error_msg(count, "reading samples");
376 int err = snd_pcm_prepare(fInputDevice);
377 check_error_msg(err, "preparing input stream");
378 }
379
380 if (fSampleFormat == SND_PCM_FORMAT_S16) {
381
382 for (unsigned int c = 0; c < fCardInputs; c++) {
383 short* chan16b = (short*) fInputCardChannels[c];
384 for (unsigned int s = 0; s < fBuffering; s++) {
385 fInputSoftChannels[c][s] = float(chan16b[s])*(1.0/float(SHRT_MAX));
386 }
387 }
388
389 } else if (fSampleFormat == SND_PCM_FORMAT_S32) {
390
391 for (unsigned int c = 0; c < fCardInputs; c++) {
392 int32* chan32b = (int32*) fInputCardChannels[c];
393 for (unsigned int s = 0; s < fBuffering; s++) {
394 fInputSoftChannels[c][s] = float(chan32b[s])*(1.0/float(INT_MAX));
395 }
396 }
397 } else {
398
399 printf("unrecognized input sample format : %u\n", fSampleFormat);
400 exit(1);
401 }
402
403 } else {
404 check_error_msg(-10000, "unknow access mode");
405 }
406 }
407
408 /**
409 * write the output soft channels to the audio card. Convert sample
410 * format and interleaves buffers when needed
411 */
412 void write()
413 {
414 recovery :
415
416 if (fSampleAccess == SND_PCM_ACCESS_RW_INTERLEAVED) {
417
418 if (fSampleFormat == SND_PCM_FORMAT_S16) {
419
420 short* buffer16b = (short*) fOutputCardBuffer;
421 for (unsigned int f = 0; f < fBuffering; f++) {
422 for (unsigned int c = 0; c < fCardOutputs; c++) {
423 float x = fOutputSoftChannels[c][f];
424 buffer16b[c + f*fCardOutputs] = short( max(min(x,1.0),-1.0) * float(SHRT_MAX) ) ;
425 }
426 }
427
428 } else if (fSampleFormat == SND_PCM_FORMAT_S32) {
429
430 int32* buffer32b = (int32*) fOutputCardBuffer;
431 for (unsigned int f = 0; f < fBuffering; f++) {
432 for (unsigned int c = 0; c < fCardOutputs; c++) {
433 float x = fOutputSoftChannels[c][f];
434 buffer32b[c + f*fCardOutputs] = int( max(min(x,1.0),-1.0) * float(INT_MAX) ) ;
435 }
436 }
437 } else {
438
439 printf("unrecognized output sample format : %u\n", fSampleFormat);
440 exit(1);
441 }
442
443 int count = snd_pcm_writei(fOutputDevice, fOutputCardBuffer, fBuffering);
444 if (count<0) {
445 display_error_msg(count, "w3");
446 int err = snd_pcm_prepare(fOutputDevice);
447 check_error_msg(err, "preparing output stream");
448 goto recovery;
449 }
450
451
452 } else if (fSampleAccess == SND_PCM_ACCESS_RW_NONINTERLEAVED) {
453
454 if (fSampleFormat == SND_PCM_FORMAT_S16) {
455
456 for (unsigned int c = 0; c < fCardOutputs; c++) {
457 short* chan16b = (short*) fOutputCardChannels[c];
458 for (unsigned int f = 0; f < fBuffering; f++) {
459 float x = fOutputSoftChannels[c][f];
460 chan16b[f] = short( max(min(x,1.0),-1.0) * float(SHRT_MAX) ) ;
461 }
462 }
463
464 } else if (fSampleFormat == SND_PCM_FORMAT_S32) {
465
466 for (unsigned int c = 0; c < fCardOutputs; c++) {
467 int32* chan32b = (int32*) fOutputCardChannels[c];
468 for (unsigned int f = 0; f < fBuffering; f++) {
469 float x = fOutputSoftChannels[c][f];
470 chan32b[f] = int( max(min(x,1.0),-1.0) * float(INT_MAX) ) ;
471 }
472 }
473
474 } else {
475
476 printf("unrecognized output sample format : %u\n", fSampleFormat);
477 exit(1);
478 }
479
480 int count = snd_pcm_writen(fOutputDevice, fOutputCardChannels, fBuffering);
481 if (count<0) {
482 display_error_msg(count, "w3");
483 int err = snd_pcm_prepare(fOutputDevice);
484 check_error_msg(err, "preparing output stream");
485 goto recovery;
486 }
487
488 } else {
489 check_error_msg(-10000, "unknow access mode");
490 }
491 }
492
493 /**
494 * print short information on the audio device
495 */
496 void shortinfo()
497 {
498 int err;
499 snd_ctl_card_info_t* card_info;
500 snd_ctl_t* ctl_handle;
501 err = snd_ctl_open (&ctl_handle, fCardName, 0); check_error(err);
502 snd_ctl_card_info_alloca (&card_info);
503 err = snd_ctl_card_info(ctl_handle, card_info); check_error(err);
504 printf("%s|%d|%d|%d|%d|%s\n",
505 snd_ctl_card_info_get_driver(card_info),
506 fCardInputs, fCardOutputs,
507 fFrequency, fBuffering,
508 snd_pcm_format_name((_snd_pcm_format)fSampleFormat));
509 }
510
511 /**
512 * print more detailled information on the audio device
513 */
514 void longinfo()
515 {
516 int err;
517 snd_ctl_card_info_t* card_info;
518 snd_ctl_t* ctl_handle;
519
520 printf("Audio Interface Description :\n");
521 printf("Sampling Frequency : %d, Sample Format : %s, buffering : %d\n",
522 fFrequency, snd_pcm_format_name((_snd_pcm_format)fSampleFormat), fBuffering);
523 printf("Software inputs : %2d, Software outputs : %2d\n", fSoftInputs, fSoftOutputs);
524 printf("Hardware inputs : %2d, Hardware outputs : %2d\n", fCardInputs, fCardOutputs);
525 printf("Channel inputs : %2d, Channel outputs : %2d\n", fChanInputs, fChanOutputs);
526
527 // affichage des infos de la carte
528 err = snd_ctl_open (&ctl_handle, fCardName, 0); check_error(err);
529 snd_ctl_card_info_alloca (&card_info);
530 err = snd_ctl_card_info(ctl_handle, card_info); check_error(err);
531 printCardInfo(card_info);
532
533 // affichage des infos liees aux streams d'entree-sortie
534 if (fSoftInputs > 0) printHWParams(fInputParams);
535 if (fSoftOutputs > 0) printHWParams(fOutputParams);
536 }
537
538 void printCardInfo(snd_ctl_card_info_t* ci)
539 {
540 printf("Card info (address : %p)\n", ci);
541 printf("\tID = %s\n", snd_ctl_card_info_get_id(ci));
542 printf("\tDriver = %s\n", snd_ctl_card_info_get_driver(ci));
543 printf("\tName = %s\n", snd_ctl_card_info_get_name(ci));
544 printf("\tLongName = %s\n", snd_ctl_card_info_get_longname(ci));
545 printf("\tMixerName = %s\n", snd_ctl_card_info_get_mixername(ci));
546 printf("\tComponents = %s\n", snd_ctl_card_info_get_components(ci));
547 printf("--------------\n");
548 }
549
550 void printHWParams( snd_pcm_hw_params_t* params )
551 {
552 printf("HW Params info (address : %p)\n", params);
553 #if 0
554 printf("\tChannels = %d\n", snd_pcm_hw_params_get_channels(params));
555 printf("\tFormat = %s\n", snd_pcm_format_name((_snd_pcm_format)snd_pcm_hw_params_get_format(params)));
556 printf("\tAccess = %s\n", snd_pcm_access_name((_snd_pcm_access)snd_pcm_hw_params_get_access(params)));
557 printf("\tRate = %d\n", snd_pcm_hw_params_get_rate(params, NULL));
558 printf("\tPeriods = %d\n", snd_pcm_hw_params_get_periods(params, NULL));
559 printf("\tPeriod size = %d\n", (int)snd_pcm_hw_params_get_period_size(params, NULL));
560 printf("\tPeriod time = %d\n", snd_pcm_hw_params_get_period_time(params, NULL));
561 printf("\tBuffer size = %d\n", (int)snd_pcm_hw_params_get_buffer_size(params));
562 printf("\tBuffer time = %d\n", snd_pcm_hw_params_get_buffer_time(params, NULL));
563 #endif
564 printf("--------------\n");
565 }
566
567 };
568
569 // lopt : Scan Command Line long int Arguments
570 long lopt(int argc, char *argv[], const char* longname, const char* shortname, long def)
571 {
572 for (int i=2; i<argc; i++)
573 if ( strcmp(argv[i-1], shortname) == 0 || strcmp(argv[i-1], longname) == 0 )
574 return atoi(argv[i]);
575 return def;
576 }
577
578 // sopt : Scan Command Line string Arguments
579 const char* sopt(int argc, char *argv[], const char* longname, const char* shortname, const char* def)
580 {
581 for (int i=2; i<argc; i++)
582 if ( strcmp(argv[i-1], shortname) == 0 || strcmp(argv[i-1], longname) == 0 )
583 return argv[i];
584 return def;
585 }
586
587 // fopt : Scan Command Line flag option (without argument), return true if the flag
588 bool fopt(int argc, char *argv[], const char* longname, const char* shortname)
589 {
590 for (int i=1; i<argc; i++)
591 if ( strcmp(argv[i], shortname) == 0 || strcmp(argv[i], longname) == 0 )
592 return true;
593 return false;
594 }
595
596 /**
597 * Return the value of an environment variable or defval if undefined.
598 */
599 static int getDefaultEnv(const char* name, int defval)
600 {
601 const char* str = getenv(name);
602 if (str) {
603 return atoi(str);
604 } else {
605 return defval;
606 }
607 }
608
609 /**
610 * Return the value of an environment variable or defval if undefined.
611 */
612 static const char* getDefaultEnv(const char* name, const char* defval)
613 {
614 const char* str = getenv(name);
615 if (str) {
616 return str;
617 } else {
618 return defval;
619 }
620 }
621
622 /******************************************************************************
623 *******************************************************************************
624
625 ALSA audio interface
626
627 *******************************************************************************
628 *******************************************************************************/
629 void* __run(void* ptr);
630
631 class alsaaudio : public audio {
632 AudioInterface* fAudio;
633 dsp* fDSP;
634 pthread_t fAudioThread;
635 bool fRunning;
636
637 public:
638 alsaaudio(int argc, char *argv[], dsp* DSP) : fAudio(0), fDSP(DSP), fRunning(false) {
639 fAudio = new AudioInterface (
640 AudioParam().cardName( sopt(argc, argv, "--device", "-d", getDefaultEnv("FAUST2ALSA_DEVICE", "hw:0") ) )
641 .frequency( lopt(argc, argv, "--frequency", "-f", getDefaultEnv("FAUST2ALSA_FREQUENCY",44100) ) )
642 .buffering( lopt(argc, argv, "--buffer", "-b", getDefaultEnv("FAUST2ALSA_BUFFER",1024) ) )
643 .periods( lopt(argc, argv, "--periods", "-p", getDefaultEnv("FAUST2ALSA_PERIODS",2) ) )
644 .inputs(DSP->getNumInputs())
645 .outputs(DSP->getNumOutputs()));
646 }
647 virtual ~alsaaudio() { stop(); delete fAudio; }
648
649 virtual bool init(const char */*name*/, dsp* DSP) {
650 AVOIDDENORMALS;
651 fAudio->open();
652 DSP->init(fAudio->frequency());
653 return true;
654 }
655
656 virtual bool start() {
657 fRunning = true;
658 if (pthread_create( &fAudioThread, 0, __run, this))
659 fRunning = false;
660 return fRunning;
661 }
662
663 virtual void stop() {
664 if (fRunning) {
665 fRunning = false;
666 pthread_join (fAudioThread, 0);
667 }
668 }
669
670 virtual void run() {
671 bool rt = setRealtimePriority();
672 printf(rt ? "RT : ":"NRT: "); fAudio->shortinfo();
673 fAudio->write();
674 fAudio->write();
675 while(fRunning) {
676 fAudio->read();
677 fDSP->compute(fAudio->buffering(), fAudio->inputSoftChannels(), fAudio->outputSoftChannels());
678 fAudio->write();
679 }
680 }
681 };
682
683 void* __run (void* ptr)
684 {
685 alsaaudio * alsa = (alsaaudio*)ptr;
686 alsa->run();
687 return 0;
688 }
689
690 #endif
691
692 /********************END ARCHITECTURE SECTION (part 2/2)****************/
693