summaryrefslogtreecommitdiff
path: root/apps/plugins/pdbox/PDa/src/s_audio_pa.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/pdbox/PDa/src/s_audio_pa.c')
-rw-r--r--apps/plugins/pdbox/PDa/src/s_audio_pa.c584
1 files changed, 584 insertions, 0 deletions
diff --git a/apps/plugins/pdbox/PDa/src/s_audio_pa.c b/apps/plugins/pdbox/PDa/src/s_audio_pa.c
new file mode 100644
index 0000000000..ebae9679dc
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/src/s_audio_pa.c
@@ -0,0 +1,584 @@
1/* Copyright (c) 2001 Miller Puckette and others.
2* For information on usage and redistribution, and for a DISCLAIMER OF ALL
3* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
4
5/* this file calls Ross Bencina's and Phil Burk's Portaudio package. It's
6 the main way in for Mac OS and, with Michael Casey's help, also into
7 ASIO in Windows. */
8
9
10#include "m_pd.h"
11#include "s_stuff.h"
12#include <stdio.h>
13#include <stdlib.h>
14#include "portaudio.h"
15#include "pablio_pd.h"
16
17 /* LATER try to figure out how to handle default devices in portaudio;
18 the way s_audio.c handles them isn't going to work here. */
19
20#if defined(MACOSX) || defined(MSW)
21#define Pa_GetDefaultInputDevice Pa_GetDefaultInputDeviceID
22#define Pa_GetDefaultOutputDevice Pa_GetDefaultOutputDeviceID
23#endif
24
25 /* public interface declared in m_imp.h */
26
27 /* implementation */
28static PABLIO_Stream *pa_stream;
29static int pa_inchans, pa_outchans;
30static float *pa_soundin, *pa_soundout;
31
32#define MAX_PA_CHANS 32
33#define MAX_SAMPLES_PER_FRAME MAX_PA_CHANS * DEFDACBLKSIZE
34
35int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin,
36 t_sample *soundout, int framesperbuf, int nbuffers,
37 int indeviceno, int outdeviceno)
38{
39 PaError err;
40 static int initialized;
41 int j, devno, pa_indev = 0, pa_outdev = 0;
42
43 if (!initialized)
44 {
45 /* Initialize PortAudio */
46 int err = Pa_Initialize();
47 if ( err != paNoError )
48 {
49 fprintf( stderr,
50 "Error number %d occured initializing portaudio\n",
51 err);
52 fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
53 return (1);
54 }
55 initialized = 1;
56 }
57 /* post("in %d out %d rate %d device %d", inchans, outchans, rate, deviceno); */
58 if (inchans != 0 && outchans != 0 && inchans != outchans)
59 error("portaudio: number of input and output channels must match");
60 if (inchans > MAX_PA_CHANS)
61 {
62 post("input channels reduced to maximum %d", MAX_PA_CHANS);
63 inchans = MAX_PA_CHANS;
64 }
65 if (outchans > MAX_PA_CHANS)
66 {
67 post("output channels reduced to maximum %d", MAX_PA_CHANS);
68 outchans = MAX_PA_CHANS;
69 }
70
71 if (inchans > 0)
72 {
73 for (j = 0, devno = 0; j < Pa_CountDevices(); j++)
74 {
75 const PaDeviceInfo *info = Pa_GetDeviceInfo(j);
76 if (info->maxInputChannels > 0)
77 {
78 if (devno == indeviceno)
79 {
80 pa_indev = j;
81 break;
82 }
83 devno++;
84 }
85 }
86 }
87
88 if (outchans > 0)
89 {
90 for (j = 0, devno = 0; j < Pa_CountDevices(); j++)
91 {
92 const PaDeviceInfo *info = Pa_GetDeviceInfo(j);
93 if (info->maxOutputChannels > 0)
94 {
95 if (devno == outdeviceno)
96 {
97 pa_outdev = j;
98 break;
99 }
100 devno++;
101 }
102 }
103 }
104
105 if (sys_verbose)
106 {
107 post("input device %d, channels %d", pa_indev, inchans);
108 post("output device %d, channels %d", pa_outdev, outchans);
109 post("framesperbuf %d, nbufs %d", framesperbuf, nbuffers);
110 }
111 if (inchans && outchans)
112 err = OpenAudioStream( &pa_stream, rate, paFloat32,
113 PABLIO_READ_WRITE, inchans, framesperbuf, nbuffers,
114 pa_indev, pa_outdev);
115 else if (inchans)
116 err = OpenAudioStream( &pa_stream, rate, paFloat32,
117 PABLIO_READ, inchans, framesperbuf, nbuffers,
118 pa_indev, pa_outdev);
119 else if (outchans)
120 err = OpenAudioStream( &pa_stream, rate, paFloat32,
121 PABLIO_WRITE, outchans, framesperbuf, nbuffers,
122 pa_indev, pa_outdev);
123 else err = 0;
124 if ( err != paNoError )
125 {
126 fprintf( stderr, "Error number %d occured opening portaudio stream\n",
127 err);
128 fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
129 Pa_Terminate();
130 sys_inchannels = sys_outchannels = 0;
131 return (1);
132 }
133 else if (sys_verbose)
134 post("... opened OK.");
135 pa_inchans = inchans;
136 pa_outchans = outchans;
137 pa_soundin = soundin;
138 pa_soundout = soundout;
139 return (0);
140}
141
142void pa_close_audio( void)
143{
144 if (pa_inchans || pa_outchans)
145 CloseAudioStream( pa_stream );
146 pa_inchans = pa_outchans = 0;
147}
148
149int pa_send_dacs(void)
150{
151 float samples[MAX_SAMPLES_PER_FRAME], *fp1, *fp2;
152 int i, j;
153 double timebefore;
154
155 timebefore = sys_getrealtime();
156 if ((pa_inchans && GetAudioStreamReadable(pa_stream) < DEFDACBLKSIZE) ||
157 (pa_outchans && GetAudioStreamWriteable(pa_stream) < DEFDACBLKSIZE))
158 {
159 if (pa_inchans && pa_outchans)
160 {
161 int synced = 0;
162 while (GetAudioStreamWriteable(pa_stream) > 2*DEFDACBLKSIZE)
163 {
164 for (j = 0; j < pa_outchans; j++)
165 for (i = 0, fp2 = samples + j; i < DEFDACBLKSIZE; i++,
166 fp2 += pa_outchans)
167 {
168 *fp2 = 0;
169 }
170 synced = 1;
171 WriteAudioStream(pa_stream, samples, DEFDACBLKSIZE);
172 }
173 while (GetAudioStreamReadable(pa_stream) > 2*DEFDACBLKSIZE)
174 {
175 synced = 1;
176 ReadAudioStream(pa_stream, samples, DEFDACBLKSIZE);
177 }
178 /* if (synced)
179 post("sync"); */
180 }
181 return (SENDDACS_NO);
182 }
183 if (pa_inchans)
184 {
185 ReadAudioStream(pa_stream, samples, DEFDACBLKSIZE);
186 for (j = 0, fp1 = pa_soundin; j < pa_inchans; j++, fp1 += DEFDACBLKSIZE)
187 for (i = 0, fp2 = samples + j; i < DEFDACBLKSIZE; i++,
188 fp2 += pa_inchans)
189 {
190 fp1[i] = *fp2;
191 }
192 }
193#if 0
194 {
195 static int nread;
196 if (nread == 0)
197 {
198 post("it's %f %f %f %f",
199 pa_soundin[0], pa_soundin[1], pa_soundin[2], pa_soundin[3]);
200 nread = 1000;
201 }
202 nread--;
203 }
204#endif
205 if (pa_outchans)
206 {
207 for (j = 0, fp1 = pa_soundout; j < pa_outchans; j++,
208 fp1 += DEFDACBLKSIZE)
209 for (i = 0, fp2 = samples + j; i < DEFDACBLKSIZE; i++,
210 fp2 += pa_outchans)
211 {
212 *fp2 = fp1[i];
213 fp1[i] = 0;
214 }
215 WriteAudioStream(pa_stream, samples, DEFDACBLKSIZE);
216 }
217
218 if (sys_getrealtime() > timebefore + 0.002)
219 {
220 /* post("slept"); */
221 return (SENDDACS_SLEPT);
222 }
223 else return (SENDDACS_YES);
224}
225
226
227void pa_listdevs(void) /* lifted from pa_devs.c in portaudio */
228{
229 int i,j;
230 int numDevices;
231 const PaDeviceInfo *pdi;
232 PaError err;
233 Pa_Initialize();
234 numDevices = Pa_CountDevices();
235 if( numDevices < 0 )
236 {
237 fprintf(stderr, "ERROR: Pa_CountDevices returned 0x%x\n", numDevices );
238 err = numDevices;
239 goto error;
240 }
241 fprintf(stderr, "Audio Devices:\n");
242 for( i=0; i<numDevices; i++ )
243 {
244 pdi = Pa_GetDeviceInfo( i );
245 fprintf(stderr, "device %d:", i+1 );
246 fprintf(stderr, " %s;", pdi->name );
247 fprintf(stderr, "%d inputs, ", pdi->maxInputChannels );
248 fprintf(stderr, "%d outputs", pdi->maxOutputChannels );
249 if ( i == Pa_GetDefaultInputDevice() )
250 fprintf(stderr, " (Default Input)");
251 if ( i == Pa_GetDefaultOutputDevice() )
252 fprintf(stderr, " (Default Output)");
253 fprintf(stderr, "\n");
254 }
255
256 fprintf(stderr, "\n");
257 return;
258
259error:
260 fprintf( stderr, "An error occured while using the portaudio stream\n" );
261 fprintf( stderr, "Error number: %d\n", err );
262 fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
263
264}
265
266 /* scanning for devices */
267void pa_getdevs(char *indevlist, int *nindevs,
268 char *outdevlist, int *noutdevs, int *canmulti,
269 int maxndev, int devdescsize)
270{
271 int i, nin = 0, nout = 0, ndev;
272 *canmulti = 1; /* one dev each for input and output */
273
274 Pa_Initialize();
275 ndev = Pa_CountDevices();
276 for (i = 0; i < ndev; i++)
277 {
278 const PaDeviceInfo *pdi = Pa_GetDeviceInfo(i);
279 if (pdi->maxInputChannels > 0 && nin < maxndev)
280 {
281 strcpy(indevlist + nin * devdescsize, pdi->name);
282 nin++;
283 }
284 if (pdi->maxOutputChannels > 0 && nout < maxndev)
285 {
286 strcpy(outdevlist + nout * devdescsize, pdi->name);
287 nout++;
288 }
289 }
290 *nindevs = nin;
291 *noutdevs = nout;
292}
293/* Copyright (c) 2001 Miller Puckette and others.
294* For information on usage and redistribution, and for a DISCLAIMER OF ALL
295* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
296
297/* this file calls Ross Bencina's and Phil Burk's Portaudio package. It's
298 the main way in for Mac OS and, with Michael Casey's help, also into
299 ASIO in Windows. */
300
301
302#include "m_pd.h"
303#include "s_stuff.h"
304#include <stdio.h>
305#include <stdlib.h>
306#include "portaudio.h"
307#include "pablio_pd.h"
308
309 /* LATER try to figure out how to handle default devices in portaudio;
310 the way s_audio.c handles them isn't going to work here. */
311
312#if defined(MACOSX) || defined(MSW)
313#define Pa_GetDefaultInputDevice Pa_GetDefaultInputDeviceID
314#define Pa_GetDefaultOutputDevice Pa_GetDefaultOutputDeviceID
315#endif
316
317 /* public interface declared in m_imp.h */
318
319 /* implementation */
320static PABLIO_Stream *pa_stream;
321static int pa_inchans, pa_outchans;
322static float *pa_soundin, *pa_soundout;
323
324#define MAX_PA_CHANS 32
325#define MAX_SAMPLES_PER_FRAME MAX_PA_CHANS * DEFDACBLKSIZE
326
327int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin,
328 t_sample *soundout, int framesperbuf, int nbuffers,
329 int indeviceno, int outdeviceno)
330{
331 PaError err;
332 static int initialized;
333 int j, devno, pa_indev = 0, pa_outdev = 0;
334
335 if (!initialized)
336 {
337 /* Initialize PortAudio */
338 int err = Pa_Initialize();
339 if ( err != paNoError )
340 {
341 fprintf( stderr,
342 "Error number %d occured initializing portaudio\n",
343 err);
344 fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
345 return (1);
346 }
347 initialized = 1;
348 }
349 /* post("in %d out %d rate %d device %d", inchans, outchans, rate, deviceno); */
350 if (inchans != 0 && outchans != 0 && inchans != outchans)
351 error("portaudio: number of input and output channels must match");
352 if (inchans > MAX_PA_CHANS)
353 {
354 post("input channels reduced to maximum %d", MAX_PA_CHANS);
355 inchans = MAX_PA_CHANS;
356 }
357 if (outchans > MAX_PA_CHANS)
358 {
359 post("output channels reduced to maximum %d", MAX_PA_CHANS);
360 outchans = MAX_PA_CHANS;
361 }
362
363 if (inchans > 0)
364 {
365 for (j = 0, devno = 0; j < Pa_CountDevices(); j++)
366 {
367 const PaDeviceInfo *info = Pa_GetDeviceInfo(j);
368 if (info->maxInputChannels > 0)
369 {
370 if (devno == indeviceno)
371 {
372 pa_indev = j;
373 break;
374 }
375 devno++;
376 }
377 }
378 }
379
380 if (outchans > 0)
381 {
382 for (j = 0, devno = 0; j < Pa_CountDevices(); j++)
383 {
384 const PaDeviceInfo *info = Pa_GetDeviceInfo(j);
385 if (info->maxOutputChannels > 0)
386 {
387 if (devno == outdeviceno)
388 {
389 pa_outdev = j;
390 break;
391 }
392 devno++;
393 }
394 }
395 }
396
397 if (sys_verbose)
398 {
399 post("input device %d, channels %d", pa_indev, inchans);
400 post("output device %d, channels %d", pa_outdev, outchans);
401 post("framesperbuf %d, nbufs %d", framesperbuf, nbuffers);
402 }
403 if (inchans && outchans)
404 err = OpenAudioStream( &pa_stream, rate, paFloat32,
405 PABLIO_READ_WRITE, inchans, framesperbuf, nbuffers,
406 pa_indev, pa_outdev);
407 else if (inchans)
408 err = OpenAudioStream( &pa_stream, rate, paFloat32,
409 PABLIO_READ, inchans, framesperbuf, nbuffers,
410 pa_indev, pa_outdev);
411 else if (outchans)
412 err = OpenAudioStream( &pa_stream, rate, paFloat32,
413 PABLIO_WRITE, outchans, framesperbuf, nbuffers,
414 pa_indev, pa_outdev);
415 else err = 0;
416 if ( err != paNoError )
417 {
418 fprintf( stderr, "Error number %d occured opening portaudio stream\n",
419 err);
420 fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
421 Pa_Terminate();
422 sys_inchannels = sys_outchannels = 0;
423 return (1);
424 }
425 else if (sys_verbose)
426 post("... opened OK.");
427 pa_inchans = inchans;
428 pa_outchans = outchans;
429 pa_soundin = soundin;
430 pa_soundout = soundout;
431 return (0);
432}
433
434void pa_close_audio( void)
435{
436 if (pa_inchans || pa_outchans)
437 CloseAudioStream( pa_stream );
438 pa_inchans = pa_outchans = 0;
439}
440
441int pa_send_dacs(void)
442{
443 float samples[MAX_SAMPLES_PER_FRAME], *fp1, *fp2;
444 int i, j;
445 double timebefore;
446
447 timebefore = sys_getrealtime();
448 if ((pa_inchans && GetAudioStreamReadable(pa_stream) < DEFDACBLKSIZE) ||
449 (pa_outchans && GetAudioStreamWriteable(pa_stream) < DEFDACBLKSIZE))
450 {
451 if (pa_inchans && pa_outchans)
452 {
453 int synced = 0;
454 while (GetAudioStreamWriteable(pa_stream) > 2*DEFDACBLKSIZE)
455 {
456 for (j = 0; j < pa_outchans; j++)
457 for (i = 0, fp2 = samples + j; i < DEFDACBLKSIZE; i++,
458 fp2 += pa_outchans)
459 {
460 *fp2 = 0;
461 }
462 synced = 1;
463 WriteAudioStream(pa_stream, samples, DEFDACBLKSIZE);
464 }
465 while (GetAudioStreamReadable(pa_stream) > 2*DEFDACBLKSIZE)
466 {
467 synced = 1;
468 ReadAudioStream(pa_stream, samples, DEFDACBLKSIZE);
469 }
470 /* if (synced)
471 post("sync"); */
472 }
473 return (SENDDACS_NO);
474 }
475 if (pa_inchans)
476 {
477 ReadAudioStream(pa_stream, samples, DEFDACBLKSIZE);
478 for (j = 0, fp1 = pa_soundin; j < pa_inchans; j++, fp1 += DEFDACBLKSIZE)
479 for (i = 0, fp2 = samples + j; i < DEFDACBLKSIZE; i++,
480 fp2 += pa_inchans)
481 {
482 fp1[i] = *fp2;
483 }
484 }
485#if 0
486 {
487 static int nread;
488 if (nread == 0)
489 {
490 post("it's %f %f %f %f",
491 pa_soundin[0], pa_soundin[1], pa_soundin[2], pa_soundin[3]);
492 nread = 1000;
493 }
494 nread--;
495 }
496#endif
497 if (pa_outchans)
498 {
499 for (j = 0, fp1 = pa_soundout; j < pa_outchans; j++,
500 fp1 += DEFDACBLKSIZE)
501 for (i = 0, fp2 = samples + j; i < DEFDACBLKSIZE; i++,
502 fp2 += pa_outchans)
503 {
504 *fp2 = fp1[i];
505 fp1[i] = 0;
506 }
507 WriteAudioStream(pa_stream, samples, DEFDACBLKSIZE);
508 }
509
510 if (sys_getrealtime() > timebefore + 0.002)
511 {
512 /* post("slept"); */
513 return (SENDDACS_SLEPT);
514 }
515 else return (SENDDACS_YES);
516}
517
518
519void pa_listdevs(void) /* lifted from pa_devs.c in portaudio */
520{
521 int i,j;
522 int numDevices;
523 const PaDeviceInfo *pdi;
524 PaError err;
525 Pa_Initialize();
526 numDevices = Pa_CountDevices();
527 if( numDevices < 0 )
528 {
529 fprintf(stderr, "ERROR: Pa_CountDevices returned 0x%x\n", numDevices );
530 err = numDevices;
531 goto error;
532 }
533 fprintf(stderr, "Audio Devices:\n");
534 for( i=0; i<numDevices; i++ )
535 {
536 pdi = Pa_GetDeviceInfo( i );
537 fprintf(stderr, "device %d:", i+1 );
538 fprintf(stderr, " %s;", pdi->name );
539 fprintf(stderr, "%d inputs, ", pdi->maxInputChannels );
540 fprintf(stderr, "%d outputs", pdi->maxOutputChannels );
541 if ( i == Pa_GetDefaultInputDevice() )
542 fprintf(stderr, " (Default Input)");
543 if ( i == Pa_GetDefaultOutputDevice() )
544 fprintf(stderr, " (Default Output)");
545 fprintf(stderr, "\n");
546 }
547
548 fprintf(stderr, "\n");
549 return;
550
551error:
552 fprintf( stderr, "An error occured while using the portaudio stream\n" );
553 fprintf( stderr, "Error number: %d\n", err );
554 fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
555
556}
557
558 /* scanning for devices */
559void pa_getdevs(char *indevlist, int *nindevs,
560 char *outdevlist, int *noutdevs, int *canmulti,
561 int maxndev, int devdescsize)
562{
563 int i, nin = 0, nout = 0, ndev;
564 *canmulti = 1; /* one dev each for input and output */
565
566 Pa_Initialize();
567 ndev = Pa_CountDevices();
568 for (i = 0; i < ndev; i++)
569 {
570 const PaDeviceInfo *pdi = Pa_GetDeviceInfo(i);
571 if (pdi->maxInputChannels > 0 && nin < maxndev)
572 {
573 strcpy(indevlist + nin * devdescsize, pdi->name);
574 nin++;
575 }
576 if (pdi->maxOutputChannels > 0 && nout < maxndev)
577 {
578 strcpy(outdevlist + nout * devdescsize, pdi->name);
579 nout++;
580 }
581 }
582 *nindevs = nin;
583 *noutdevs = nout;
584}