Add FS #10214. Initial commit of the original PDa code for the GSoC Pure Data plugin...
[kugel-rb.git] / apps / plugins / pdbox / PDa / src / s_audio_pa.c
blobebae9679dc6a8a718a8e65c64089e9428bf4e215
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. */
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. */
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"
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. */
20 #if defined(MACOSX) || defined(MSW)
21 #define Pa_GetDefaultInputDevice Pa_GetDefaultInputDeviceID
22 #define Pa_GetDefaultOutputDevice Pa_GetDefaultOutputDeviceID
23 #endif
25 /* public interface declared in m_imp.h */
27 /* implementation */
28 static PABLIO_Stream *pa_stream;
29 static int pa_inchans, pa_outchans;
30 static float *pa_soundin, *pa_soundout;
32 #define MAX_PA_CHANS 32
33 #define MAX_SAMPLES_PER_FRAME MAX_PA_CHANS * DEFDACBLKSIZE
35 int 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)
39 PaError err;
40 static int initialized;
41 int j, devno, pa_indev = 0, pa_outdev = 0;
43 if (!initialized)
45 /* Initialize PortAudio */
46 int err = Pa_Initialize();
47 if ( err != paNoError )
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);
55 initialized = 1;
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)
62 post("input channels reduced to maximum %d", MAX_PA_CHANS);
63 inchans = MAX_PA_CHANS;
65 if (outchans > MAX_PA_CHANS)
67 post("output channels reduced to maximum %d", MAX_PA_CHANS);
68 outchans = MAX_PA_CHANS;
71 if (inchans > 0)
73 for (j = 0, devno = 0; j < Pa_CountDevices(); j++)
75 const PaDeviceInfo *info = Pa_GetDeviceInfo(j);
76 if (info->maxInputChannels > 0)
78 if (devno == indeviceno)
80 pa_indev = j;
81 break;
83 devno++;
88 if (outchans > 0)
90 for (j = 0, devno = 0; j < Pa_CountDevices(); j++)
92 const PaDeviceInfo *info = Pa_GetDeviceInfo(j);
93 if (info->maxOutputChannels > 0)
95 if (devno == outdeviceno)
97 pa_outdev = j;
98 break;
100 devno++;
105 if (sys_verbose)
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);
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 )
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);
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);
142 void pa_close_audio( void)
144 if (pa_inchans || pa_outchans)
145 CloseAudioStream( pa_stream );
146 pa_inchans = pa_outchans = 0;
149 int pa_send_dacs(void)
151 float samples[MAX_SAMPLES_PER_FRAME], *fp1, *fp2;
152 int i, j;
153 double timebefore;
155 timebefore = sys_getrealtime();
156 if ((pa_inchans && GetAudioStreamReadable(pa_stream) < DEFDACBLKSIZE) ||
157 (pa_outchans && GetAudioStreamWriteable(pa_stream) < DEFDACBLKSIZE))
159 if (pa_inchans && pa_outchans)
161 int synced = 0;
162 while (GetAudioStreamWriteable(pa_stream) > 2*DEFDACBLKSIZE)
164 for (j = 0; j < pa_outchans; j++)
165 for (i = 0, fp2 = samples + j; i < DEFDACBLKSIZE; i++,
166 fp2 += pa_outchans)
168 *fp2 = 0;
170 synced = 1;
171 WriteAudioStream(pa_stream, samples, DEFDACBLKSIZE);
173 while (GetAudioStreamReadable(pa_stream) > 2*DEFDACBLKSIZE)
175 synced = 1;
176 ReadAudioStream(pa_stream, samples, DEFDACBLKSIZE);
178 /* if (synced)
179 post("sync"); */
181 return (SENDDACS_NO);
183 if (pa_inchans)
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)
190 fp1[i] = *fp2;
193 #if 0
195 static int nread;
196 if (nread == 0)
198 post("it's %f %f %f %f",
199 pa_soundin[0], pa_soundin[1], pa_soundin[2], pa_soundin[3]);
200 nread = 1000;
202 nread--;
204 #endif
205 if (pa_outchans)
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)
212 *fp2 = fp1[i];
213 fp1[i] = 0;
215 WriteAudioStream(pa_stream, samples, DEFDACBLKSIZE);
218 if (sys_getrealtime() > timebefore + 0.002)
220 /* post("slept"); */
221 return (SENDDACS_SLEPT);
223 else return (SENDDACS_YES);
227 void pa_listdevs(void) /* lifted from pa_devs.c in portaudio */
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 )
237 fprintf(stderr, "ERROR: Pa_CountDevices returned 0x%x\n", numDevices );
238 err = numDevices;
239 goto error;
241 fprintf(stderr, "Audio Devices:\n");
242 for( i=0; i<numDevices; i++ )
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");
256 fprintf(stderr, "\n");
257 return;
259 error:
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 ) );
266 /* scanning for devices */
267 void pa_getdevs(char *indevlist, int *nindevs,
268 char *outdevlist, int *noutdevs, int *canmulti,
269 int maxndev, int devdescsize)
271 int i, nin = 0, nout = 0, ndev;
272 *canmulti = 1; /* one dev each for input and output */
274 Pa_Initialize();
275 ndev = Pa_CountDevices();
276 for (i = 0; i < ndev; i++)
278 const PaDeviceInfo *pdi = Pa_GetDeviceInfo(i);
279 if (pdi->maxInputChannels > 0 && nin < maxndev)
281 strcpy(indevlist + nin * devdescsize, pdi->name);
282 nin++;
284 if (pdi->maxOutputChannels > 0 && nout < maxndev)
286 strcpy(outdevlist + nout * devdescsize, pdi->name);
287 nout++;
290 *nindevs = nin;
291 *noutdevs = nout;
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. */
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. */
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"
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. */
312 #if defined(MACOSX) || defined(MSW)
313 #define Pa_GetDefaultInputDevice Pa_GetDefaultInputDeviceID
314 #define Pa_GetDefaultOutputDevice Pa_GetDefaultOutputDeviceID
315 #endif
317 /* public interface declared in m_imp.h */
319 /* implementation */
320 static PABLIO_Stream *pa_stream;
321 static int pa_inchans, pa_outchans;
322 static float *pa_soundin, *pa_soundout;
324 #define MAX_PA_CHANS 32
325 #define MAX_SAMPLES_PER_FRAME MAX_PA_CHANS * DEFDACBLKSIZE
327 int 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)
331 PaError err;
332 static int initialized;
333 int j, devno, pa_indev = 0, pa_outdev = 0;
335 if (!initialized)
337 /* Initialize PortAudio */
338 int err = Pa_Initialize();
339 if ( err != paNoError )
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);
347 initialized = 1;
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)
354 post("input channels reduced to maximum %d", MAX_PA_CHANS);
355 inchans = MAX_PA_CHANS;
357 if (outchans > MAX_PA_CHANS)
359 post("output channels reduced to maximum %d", MAX_PA_CHANS);
360 outchans = MAX_PA_CHANS;
363 if (inchans > 0)
365 for (j = 0, devno = 0; j < Pa_CountDevices(); j++)
367 const PaDeviceInfo *info = Pa_GetDeviceInfo(j);
368 if (info->maxInputChannels > 0)
370 if (devno == indeviceno)
372 pa_indev = j;
373 break;
375 devno++;
380 if (outchans > 0)
382 for (j = 0, devno = 0; j < Pa_CountDevices(); j++)
384 const PaDeviceInfo *info = Pa_GetDeviceInfo(j);
385 if (info->maxOutputChannels > 0)
387 if (devno == outdeviceno)
389 pa_outdev = j;
390 break;
392 devno++;
397 if (sys_verbose)
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);
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 )
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);
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);
434 void pa_close_audio( void)
436 if (pa_inchans || pa_outchans)
437 CloseAudioStream( pa_stream );
438 pa_inchans = pa_outchans = 0;
441 int pa_send_dacs(void)
443 float samples[MAX_SAMPLES_PER_FRAME], *fp1, *fp2;
444 int i, j;
445 double timebefore;
447 timebefore = sys_getrealtime();
448 if ((pa_inchans && GetAudioStreamReadable(pa_stream) < DEFDACBLKSIZE) ||
449 (pa_outchans && GetAudioStreamWriteable(pa_stream) < DEFDACBLKSIZE))
451 if (pa_inchans && pa_outchans)
453 int synced = 0;
454 while (GetAudioStreamWriteable(pa_stream) > 2*DEFDACBLKSIZE)
456 for (j = 0; j < pa_outchans; j++)
457 for (i = 0, fp2 = samples + j; i < DEFDACBLKSIZE; i++,
458 fp2 += pa_outchans)
460 *fp2 = 0;
462 synced = 1;
463 WriteAudioStream(pa_stream, samples, DEFDACBLKSIZE);
465 while (GetAudioStreamReadable(pa_stream) > 2*DEFDACBLKSIZE)
467 synced = 1;
468 ReadAudioStream(pa_stream, samples, DEFDACBLKSIZE);
470 /* if (synced)
471 post("sync"); */
473 return (SENDDACS_NO);
475 if (pa_inchans)
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)
482 fp1[i] = *fp2;
485 #if 0
487 static int nread;
488 if (nread == 0)
490 post("it's %f %f %f %f",
491 pa_soundin[0], pa_soundin[1], pa_soundin[2], pa_soundin[3]);
492 nread = 1000;
494 nread--;
496 #endif
497 if (pa_outchans)
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)
504 *fp2 = fp1[i];
505 fp1[i] = 0;
507 WriteAudioStream(pa_stream, samples, DEFDACBLKSIZE);
510 if (sys_getrealtime() > timebefore + 0.002)
512 /* post("slept"); */
513 return (SENDDACS_SLEPT);
515 else return (SENDDACS_YES);
519 void pa_listdevs(void) /* lifted from pa_devs.c in portaudio */
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 )
529 fprintf(stderr, "ERROR: Pa_CountDevices returned 0x%x\n", numDevices );
530 err = numDevices;
531 goto error;
533 fprintf(stderr, "Audio Devices:\n");
534 for( i=0; i<numDevices; i++ )
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");
548 fprintf(stderr, "\n");
549 return;
551 error:
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 ) );
558 /* scanning for devices */
559 void pa_getdevs(char *indevlist, int *nindevs,
560 char *outdevlist, int *noutdevs, int *canmulti,
561 int maxndev, int devdescsize)
563 int i, nin = 0, nout = 0, ndev;
564 *canmulti = 1; /* one dev each for input and output */
566 Pa_Initialize();
567 ndev = Pa_CountDevices();
568 for (i = 0; i < ndev; i++)
570 const PaDeviceInfo *pdi = Pa_GetDeviceInfo(i);
571 if (pdi->maxInputChannels > 0 && nin < maxndev)
573 strcpy(indevlist + nin * devdescsize, pdi->name);
574 nin++;
576 if (pdi->maxOutputChannels > 0 && nout < maxndev)
578 strcpy(outdevlist + nout * devdescsize, pdi->name);
579 nout++;
582 *nindevs = nin;
583 *noutdevs = nout;