From 61aa1bbe16f53ee6abb499c1f0a6e3bf010d15fd Mon Sep 17 00:00:00 2001 From: Ivica Ico Bukvic <ico@vt.edu> Date: Sun, 7 Oct 2012 21:10:59 -0400 Subject: [PATCH] backported audio driver support from 0.43 and the pd/extra folder with supporting fixes/merges where needed. Removed outdated expr-help file in favor of new documentation. --- extra/bonk~/bonk~-help.pd | 4 +- extra/bonk~/bonk~.c | 179 ++++++++++- extra/bonk~/makefile | 2 +- extra/choice/choice.c | 2 +- extra/choice/makefile | 2 +- extra/expr~/makefile | 10 +- extra/expr~/vexp_if.c | 4 +- extra/fiddle~/makefile | 2 +- extra/loop~/loop~-help.pd | 22 +- extra/loop~/loop~.c | 26 +- extra/loop~/makefile | 2 +- extra/lrshift~/lrshift~.c | 8 +- extra/lrshift~/makefile | 2 +- extra/pd~/makefile | 3 +- extra/pd~/pdsched.c | 25 +- extra/pd~/pd~.c | 12 +- extra/pique/makefile | 2 +- extra/pique/pique.c | 42 +-- extra/sigmund~/makefile | 2 +- extra/sigmund~/sigmund~.c | 40 ++- extra/stdout/makefile | 2 +- src/s_audio.c | 219 +++++++++---- src/s_audio_alsa.c | 39 ++- src/s_audio_alsa.h | 2 +- src/s_audio_alsamm.c | 8 +- src/s_audio_jack.c | 645 ++++++++++++++++++++++---------------- src/s_audio_oss.c | 21 +- src/s_file.c | 15 +- src/s_main.c | 12 +- src/s_stuff.h | 55 +++- 30 files changed, 934 insertions(+), 475 deletions(-) diff --git a/extra/bonk~/bonk~-help.pd b/extra/bonk~/bonk~-help.pd index e52b7c506..4666d6f55 100644 --- a/extra/bonk~/bonk~-help.pd +++ b/extra/bonk~/bonk~-help.pd @@ -1,4 +1,4 @@ -#N canvas 43 123 1054 583 12; +#N canvas 0 0 1052 581 12; #X obj 382 492 spigot; #X msg 484 293 bang; #X obj 483 454 bonk~; @@ -107,7 +107,7 @@ Bonk check the attack against a collection of stored templates to try to guess which of two or more instruments was hit. Bonk is described theoretically in the 1998 ICMC proceedings \, reprinted on crca.ucsd.edu/~msp .; -#N canvas 723 241 701 719 creation-arguments 0; +#N canvas 0 0 699 717 creation-arguments 1; #X text 228 14 creation arguments for bonk~; #X text 70 272 -npts 256; #X text 44 244 default value:; diff --git a/extra/bonk~/bonk~.c b/extra/bonk~/bonk~.c index d0f18de96..f1d49c9c1 100644 --- a/extra/bonk~/bonk~.c +++ b/extra/bonk~/bonk~.c @@ -82,7 +82,9 @@ void *bonk_class; static t_class *bonk_class; #endif -#ifndef _MSC_VER +#ifdef _WIN32 +#include <malloc.h> +#elif ! defined(_MSC_VER) #include <alloca.h> #endif @@ -195,6 +197,7 @@ typedef struct _bonk t_object x_obj; t_outlet *x_cookedout; t_clock *x_clock; + t_canvas *x_canvas; /* ptr to current canvas --fbar */ #endif /* PD */ #ifdef MSP t_pxobject x_obj; @@ -256,7 +259,12 @@ static void bonk_print(t_bonk *x, t_floatarg f); static void bonk_bang(t_bonk *x); static void bonk_write(t_bonk *x, t_symbol *s); +static void bonk_dowrite(t_bonk *x, t_symbol *s); +static void bonk_writefile(t_bonk *x, char *filename, short path); + static void bonk_read(t_bonk *x, t_symbol *s); +static void bonk_doread(t_bonk *x, t_symbol *s); +static void bonk_openfile(t_bonk *x, char *filename, short path); void bonk_minvel_set(t_bonk *x, void *attr, long ac, t_atom *av); void bonk_lothresh_set(t_bonk *x, void *attr, long ac, t_atom *av); @@ -960,13 +968,21 @@ static void bonk_bang(t_bonk *x) bonk_tick(x); } +#ifdef PD static void bonk_read(t_bonk *x, t_symbol *s) { - FILE *fd = fopen(s->s_name, "r"); float vec[MAXNFILTERS]; int i, ntemplate = 0, remaining; float *fp, *fp2; - if (!fd) + + /* fbar: canvas_open code taken from g_array.c */ + FILE *fd; + char buf[MAXPDSTRING], *bufptr; + int filedesc; + + if ((filedesc = canvas_open(x->x_canvas, + s->s_name, "", buf, &bufptr, MAXPDSTRING, 0)) < 0 + || !(fd = fdopen(filedesc, "r"))) { post("%s: open failed", s->s_name); return; @@ -998,14 +1014,103 @@ nomore: x->x_ntemplate = ntemplate; fclose(fd); } +#endif + +#ifdef MSP +static void bonk_read(t_bonk *x, t_symbol *s) +{ + defer(x, (method)bonk_doread, s, 0, NULL); +} + +static void bonk_doread(t_bonk *x, t_symbol *s) +{ + long filetype = 'TEXT', outtype; + char filename[512]; + short path; + + if (s == gensym("")) { + if (open_dialog(filename, &path, &outtype, &filetype, 1)) + return; + } else { + strcpy(filename, s->s_name); + if (locatefile_extended(filename, &path, &outtype, &filetype, 1)) { + object_error((t_object *) x, "%s: not found", s->s_name); + return; + } + } + // we have a file + bonk_openfile(x, filename, path); +} + +static void bonk_openfile(t_bonk *x, char *filename, short path) { + float vec[MAXNFILTERS]; + int i, ntemplate = 0, remaining; + float *fp, *fp2; + + t_filehandle fh; + char **texthandle; + char *tokptr; + + if (path_opensysfile(filename, path, &fh, READ_PERM)) { + object_error((t_object *) x, "error opening %s", filename); + return; + } + + texthandle = sysmem_newhandle(0); + sysfile_readtextfile(fh, texthandle, 0, TEXT_LB_NATIVE); + sysfile_close(fh); + + x->x_template = (t_template *)t_resizebytes(x->x_template, + x->x_ntemplate * sizeof(t_template), 0); + + tokptr = strtok(*texthandle, " \n"); + + while(tokptr != NULL) + { + for (i = x->x_nfilters, fp = vec; i--; fp++) { + if (sscanf(tokptr, "%f", fp) < 1) + goto nomore; + tokptr = strtok(NULL, " \n"); + } + x->x_template = (t_template *)t_resizebytes(x->x_template, + ntemplate * sizeof(t_template), + (ntemplate + 1) * sizeof(t_template)); + for (i = x->x_nfilters, fp = vec, + fp2 = x->x_template[ntemplate].t_amp; i--;) + *fp2++ = *fp++; + ntemplate++; + } +nomore: + if (remaining = (ntemplate % x->x_ninsig)) + { + post("bonk_read: %d templates not a multiple of %d; dropping extras"); + x->x_template = (t_template *)t_resizebytes(x->x_template, + ntemplate * sizeof(t_template), + (ntemplate - remaining) * sizeof(t_template)); + ntemplate = ntemplate - remaining; + } + + sysmem_freehandle(texthandle); + post("bonk: read %d templates\n", ntemplate); + x->x_ntemplate = ntemplate; +} +#endif +#ifdef PD static void bonk_write(t_bonk *x, t_symbol *s) { - FILE *fd = fopen(s->s_name, "w"); + FILE *fd; + char buf[MAXPDSTRING]; /* fbar */ int i, ntemplate = x->x_ntemplate; t_template *tp = x->x_template; float *fp; - if (!fd) + + /* fbar: canvas-code as in g_array.c */ + canvas_makefilename(x->x_canvas, s->s_name, + buf, MAXPDSTRING); + sys_bashfilename(buf, buf); + + if (!(fd = fopen(buf, "w"))) { post("%s: couldn't create", s->s_name); return; @@ -1019,6 +1124,63 @@ static void bonk_write(t_bonk *x, t_symbol *s) post("bonk: wrote %d templates\n", x->x_ntemplate); fclose(fd); } +#endif + +#ifdef MSP +static void bonk_write(t_bonk *x, t_symbol *s) +{ + defer(x, (method)bonk_dowrite, s, 0, NULL); +} + +static void bonk_dowrite(t_bonk *x, t_symbol *s) +{ + long filetype = 'TEXT', outtype; + char filename[MAX_FILENAME_CHARS]; + short path; + + if (s == gensym("")) { + sprintf(filename, "bonk_template.txt"); + saveas_promptset("Save template as..."); + if (saveasdialog_extended(filename, &path, &outtype, &filetype, 0)) + return; + } else { + strcpy(filename, s->s_name); + path = path_getdefault(); + } + bonk_writefile(x, filename, path); +} + +void bonk_writefile(t_bonk *x, char *filename, short path) +{ + int i, ntemplate = x->x_ntemplate; + t_template *tp = x->x_template; + float *fp; + long err; + long buflen; + + t_filehandle fh; + + char buf[20]; + + err = path_createsysfile(filename, path, 'TEXT', &fh); + + if (err) + return; + + for (; ntemplate--; tp++) + { + for (i = x->x_nfilters, fp = tp->t_amp; i--; fp++) { + snprintf(buf, 20, "%6.2f ", *fp); + buflen = strlen(buf); + sysfile_write(fh, &buflen, buf); + } + buflen = 1; + sysfile_write(fh, &buflen, "\n"); + } + + sysfile_close(fh); +} +#endif static void bonk_free(t_bonk *x) { @@ -1048,6 +1210,7 @@ static void *bonk_new(t_symbol *s, int argc, t_atom *argv) firstbin = DEFFIRSTBIN, minbandwidth = DEFMINBANDWIDTH; t_insig *g; + x->x_canvas = canvas_getcurrent(); /* fbar: bind current canvas to x */ if (argc > 0 && argv[0].a_type == A_FLOAT) { /* old style args for compatibility */ @@ -1176,7 +1339,7 @@ void bonk_tilde_setup(void) gensym("read"), A_SYMBOL, 0); class_addmethod(bonk_class, (t_method)bonk_write, gensym("write"), A_SYMBOL, 0); - post("bonk version 1.3"); + post("bonk version 1.5"); } #endif @@ -1265,7 +1428,7 @@ int main() class_register(CLASS_BOX, c); bonk_class = c; - post("bonk~ v1.3"); + post("bonk~ v1.5"); return (0); } @@ -1446,7 +1609,7 @@ void bonk_learn_set(t_bonk *x, void *attr, long ac, t_atom *av) x->x_ntemplate * sizeof(x->x_template[0]), 0); x->x_ntemplate = 0; } - x->x_learn = (n != 0); + x->x_learn = n; x->x_learncount = 0; } } diff --git a/extra/bonk~/makefile b/extra/bonk~/makefile index af6399cca..7d56ed4d6 100644 --- a/extra/bonk~/makefile +++ b/extra/bonk~/makefile @@ -1,4 +1,4 @@ NAME=bonk~ CSYM=bonk_tilde -include ../makefile +include ../makefile.subdir diff --git a/extra/choice/choice.c b/extra/choice/choice.c index b7bf23ab1..a50c66ac2 100644 --- a/extra/choice/choice.c +++ b/extra/choice/choice.c @@ -18,7 +18,7 @@ static t_class *choice_class; typedef struct _elem { float e_age; - float e_weight[DIMENSION]; + t_float e_weight[DIMENSION]; } t_elem; typedef struct _choice diff --git a/extra/choice/makefile b/extra/choice/makefile index 7fc711593..ee63e8fdf 100644 --- a/extra/choice/makefile +++ b/extra/choice/makefile @@ -1,4 +1,4 @@ NAME=choice CSYM=choice -include ../makefile +include ../makefile.subdir diff --git a/extra/expr~/makefile b/extra/expr~/makefile index 4c6481407..5dee147a7 100644 --- a/extra/expr~/makefile +++ b/extra/expr~/makefile @@ -6,7 +6,7 @@ install: install_linux clean: clean_linux -PDEXTERN=/usr/local/lib/pd/externs +PDEXTERN=/usr/local/lib/pd/extra # ----------------------- NT ----------------------- @@ -89,7 +89,6 @@ LINUXINCLUDE = -I../../src expr.pd_linux: $(LINUXOBJ) $(CC) -shared -o expr.pd_linux $(LINUXOBJ) -lc -lm - strip --strip-unneeded expr.pd_linux expr~.pd_linux: expr.pd_linux -ln -s expr.pd_linux expr~.pd_linux @@ -110,12 +109,11 @@ install_linux: install expr.pd_linux $(PDEXTERN) rm -f $(PDEXTERN)/expr~.pd_linux rm -f $(PDEXTERN)/fexpr~.pd_linux - cd $(PDEXTERN); \ - -ln -s expr.pd_linux expr~.pd_linux - -ln -s expr.pd_linux fexpr~.pd_linux + cd $(PDEXTERN); ln -s expr.pd_linux expr~.pd_linux + cd $(PDEXTERN); ln -s expr.pd_linux fexpr~.pd_linux -linux_clean: +clean_linux: rm -f *.pd_linux_o *.o # ----------------------- MAC OSX ----------------------- diff --git a/extra/expr~/vexp_if.c b/extra/expr~/vexp_if.c index 648aba732..aaaf4ef3c 100644 --- a/extra/expr~/vexp_if.c +++ b/extra/expr~/vexp_if.c @@ -381,7 +381,7 @@ SDY the following coredumps why? post("expr: internal error expr_new"); default: pd_error(x, "expr: bad type (%lx) inlet = %d\n", - eptr->ex_type, i + 1, 0, 0, 0); + eptr->ex_type, i + 1); break; } } @@ -955,7 +955,7 @@ if (!sym || !(garray = (t_garray *)pd_findbyclass(sym, garray_class)) || \ !garray_getfloatwords(garray, &size, &vec)) { \ optr->ex_type = ET_FLT; \ optr->ex_int = 0; \ - error("no such table '%s'", sym->s_name); \ + error("no such table '%s'", sym?(sym->s_name):"(null)"); \ return; \ } diff --git a/extra/fiddle~/makefile b/extra/fiddle~/makefile index 247c905e6..0820a8382 100644 --- a/extra/fiddle~/makefile +++ b/extra/fiddle~/makefile @@ -1,4 +1,4 @@ NAME=fiddle~ CSYM=fiddle_tilde -include ../makefile +include ../makefile.subdir diff --git a/extra/loop~/loop~-help.pd b/extra/loop~/loop~-help.pd index a445b805e..ff3d3a634 100644 --- a/extra/loop~/loop~-help.pd +++ b/extra/loop~/loop~-help.pd @@ -1,4 +1,4 @@ -#N canvas 33 0 647 662 12; +#N canvas 234 90 647 662 12; #X floatatom 41 204 0 0 0 0 - - -; #X obj 254 382 print~; #X msg 254 347 bang; @@ -7,7 +7,7 @@ #X msg 55 252 bang; #X obj 183 382 print~; #X msg 183 347 bang; -#N canvas 0 0 450 300 graph1 0; +#N canvas 0 0 450 300 (subpatch) 0; #X array array2 150000 float 0; #X coords 0 1 150000 -1 200 150 1; #X restore 393 464 graph; @@ -22,7 +22,6 @@ #X floatatom 96 303 0 0 0 0 - - -; #X obj 96 326 *~ 1000; #X msg 43 568 read ../doc/sound/bell.aiff array2; -#X msg 43 591 read ../doc/sound/vocal.aiff array2; #X msg 47 229 set 0.5; #X text 95 196 left signal input is transposition (1 is normal \, 2 is up an octave \, etc); @@ -46,6 +45,7 @@ that changing window size doesn't change the transposition.; to zero--you should mute the output before doing so. This may be desirable if you've set a large window size but then want to decrease it without waiting for the next phase crossing.; +#X msg 43 591 read ../doc/sound/voice.wav array2; #X connect 0 0 3 0; #X connect 2 0 1 0; #X connect 3 0 6 0; @@ -56,7 +56,7 @@ waiting for the next phase crossing.; #X connect 4 0 3 1; #X connect 5 0 3 0; #X connect 7 0 6 0; -#X connect 11 0 28 0; +#X connect 11 0 27 0; #X connect 12 0 16 0; #X connect 14 0 13 0; #X connect 14 0 13 1; @@ -65,10 +65,10 @@ waiting for the next phase crossing.; #X connect 17 0 18 0; #X connect 18 0 15 0; #X connect 19 0 10 0; -#X connect 20 0 10 0; -#X connect 21 0 3 0; -#X connect 28 0 14 0; -#X connect 29 0 31 0; -#X connect 30 0 28 1; -#X connect 31 0 32 0; -#X connect 32 0 30 0; +#X connect 20 0 3 0; +#X connect 27 0 14 0; +#X connect 28 0 30 0; +#X connect 29 0 27 1; +#X connect 30 0 31 0; +#X connect 31 0 29 0; +#X connect 36 0 10 0; diff --git a/extra/loop~/loop~.c b/extra/loop~/loop~.c index 2f4400307..2fc3193e3 100644 --- a/extra/loop~/loop~.c +++ b/extra/loop~/loop~.c @@ -13,20 +13,24 @@ This file is downloadable from http://www.crca.ucsd.edu/~msp . #ifdef PD #include "m_pd.h" +#else +#define t_sample float #endif + + typedef struct _loopctl { double l_phase; - float l_invwindow; - float l_window; + t_sample l_invwindow; + t_sample l_window; int l_resync; } t_loopctl; -static void loopctl_run(t_loopctl *x, float *transposein, - float *windowin, float *rawout, float *windowout, int n) +static void loopctl_run(t_loopctl *x, t_sample *transposein, + t_sample *windowin, t_sample *rawout, t_sample *windowout, int n) { - float window, invwindow; + t_sample window, invwindow; double phase = x->l_phase; if (x->l_resync) { @@ -55,7 +59,7 @@ static void loopctl_run(t_loopctl *x, float *transposein, { double phaseinc = invwindow * *transposein++; double newphase; - float nwind = *windowin++; + t_sample nwind = *windowin++; if (phaseinc >= 1 || phaseinc < 0) phaseinc = 0; newphase = phase + phaseinc; @@ -77,7 +81,7 @@ static void loopctl_run(t_loopctl *x, float *transposein, newphase -= 1.; } phase = newphase; - *rawout++ = (float)phase; + *rawout++ = (t_sample)phase; *windowout++ = window; } x->l_invwindow = invwindow; @@ -124,10 +128,10 @@ static void *loop_new(void) static t_int *loop_perform(t_int *w) { t_loopctl *ctl = (t_loopctl *)(w[1]); - t_float *in1 = (t_float *)(w[2]); - t_float *in2 = (t_float *)(w[3]); - t_float *out1 = (t_float *)(w[4]); - t_float *out2 = (t_float *)(w[5]); + t_sample *in1 = (t_sample *)(w[2]); + t_sample *in2 = (t_sample *)(w[3]); + t_sample *out1 = (t_sample *)(w[4]); + t_sample *out2 = (t_sample *)(w[5]); int n = (int)(w[6]); loopctl_run(ctl, in1, in2, out1, out2, n); return (w+7); diff --git a/extra/loop~/makefile b/extra/loop~/makefile index fd21f2b4c..dc367b20a 100644 --- a/extra/loop~/makefile +++ b/extra/loop~/makefile @@ -1,4 +1,4 @@ NAME=loop~ CSYM=loop_tilde -include ../makefile +include ../makefile.subdir diff --git a/extra/lrshift~/lrshift~.c b/extra/lrshift~/lrshift~.c index 166facc16..b3c90ff6b 100644 --- a/extra/lrshift~/lrshift~.c +++ b/extra/lrshift~/lrshift~.c @@ -13,8 +13,8 @@ typedef struct _lrshift_tilde static t_int *leftshift_perform(t_int *w) { - t_float *in = (t_float *)(w[1]); - t_float *out= (t_float *)(w[2]); + t_sample *in = (t_sample *)(w[1]); + t_sample *out= (t_sample *)(w[2]); int n = (int)(w[3]); int shift = (int)(w[4]); in += shift; @@ -28,8 +28,8 @@ static t_int *leftshift_perform(t_int *w) static t_int *rightshift_perform(t_int *w) { - t_float *in = (t_float *)(w[1]); - t_float *out= (t_float *)(w[2]); + t_sample *in = (t_sample *)(w[1]); + t_sample *out= (t_sample *)(w[2]); int n = (int)(w[3]); int shift = (int)(w[4]); n -= shift; diff --git a/extra/lrshift~/makefile b/extra/lrshift~/makefile index d6a24cfe3..cbd9e8a08 100644 --- a/extra/lrshift~/makefile +++ b/extra/lrshift~/makefile @@ -1,4 +1,4 @@ NAME=lrshift~ CSYM=lrshift_tilde -include ../makefile +include ../makefile.subdir diff --git a/extra/pd~/makefile b/extra/pd~/makefile index d069c73dc..5fc5d26b3 100644 --- a/extra/pd~/makefile +++ b/extra/pd~/makefile @@ -1,7 +1,7 @@ NAME=pd~ CSYM=pd_tilde -include ../makefile +include ../makefile.subdir pd_linux: pdsched.pd_linux @@ -11,5 +11,4 @@ d_ppc: pdsched.d_ppc pdsched.pd_linux: pdsched.c $(CC) $(LINUXCFLAGS) $(LINUXINCLUDE) -o $*.o -c $*.c $(CC) -shared -o $*.pd_linux $*.o -lc -lm - strip --strip-unneeded $*.pd_linux rm -f $*.o diff --git a/extra/pd~/pdsched.c b/extra/pd~/pdsched.c index 7efe49a95..6c6060c14 100644 --- a/extra/pd~/pdsched.c +++ b/extra/pd~/pdsched.c @@ -17,15 +17,33 @@ outputs audio and messages. */ #define BUFSIZE 65536 static char inbuf[BUFSIZE]; +#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__) +void glob_watchdog(t_pd *dummy); + +static void pollwatchdog( void) +{ + static int sched_diddsp, sched_nextpingtime; + sched_diddsp++; + if (sys_nogui && sys_hipriority && (sched_diddsp - sched_nextpingtime > 0)) + { + glob_watchdog(0); + /* ping every 2 seconds */ + sched_nextpingtime = sched_diddsp + + 2 * (int)(sys_dacsr /(double)sys_schedblocksize); + } +} +#endif + int pd_extern_sched(char *flags) { int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV]; int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV]; - int i, j, rate, advance, callback, chin, chout, fill = 0, c; + int i, j, rate, advance, callback, chin, chout, fill = 0, c, blocksize; t_binbuf *b = binbuf_new(); sys_get_audio_params(&naudioindev, audioindev, chindev, - &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback); + &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback, + &blocksize); chin = (naudioindev < 1 ? 0 : chindev[0]); chout = (naudiooutdev < 1 ? 0 : choutdev[0]); @@ -57,6 +75,9 @@ int pd_extern_sched(char *flags) *fp++ = 0; sched_tick(sys_time+sys_time_per_dsp_tick); sys_pollgui(); +#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__) + pollwatchdog(); +#endif printf(";\n"); for (i = chout*DEFDACBLKSIZE, fp = sys_soundout; i--; fp++) { diff --git a/extra/pd~/pd~.c b/extra/pd~/pd~.c index 165065f8a..8a1f5c398 100644 --- a/extra/pd~/pd~.c +++ b/extra/pd~/pd~.c @@ -14,8 +14,9 @@ #include <sys/types.h> #include <sys/stat.h> #include <sys/wait.h> +#include <fcntl.h> -#ifdef NT +#ifdef _MSC_VER #pragma warning (disable: 4305 4244) #endif @@ -47,7 +48,7 @@ char *class_gethelpdir(t_class *c); #endif -#ifdef __linux__ +#if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__GNU__) #ifdef __x86_64__ static char pd_tilde_dllextent[] = ".l_ia64", pd_tilde_dllextent2[] = ".pd_linux"; @@ -60,6 +61,9 @@ static char pd_tilde_dllextent[] = ".l_i386", static char pd_tilde_dllextent[] = ".d_fat", pd_tilde_dllextent2[] = ".pd_darwin"; #endif +#if defined(_WIN32) || defined(__CYGWIN__) +static char pd_tilde_dllextent[] = ".m_i386", pd_tilde_dllextent2[] = ".dll"; +#endif /* ------------------------ pd_tilde~ ----------------------------- */ @@ -249,6 +253,8 @@ static void pd_tilde_donew(t_pd_tilde *x, char *pddir, char *schedlibdir, /* OK, we're parent */ close(pipe1[0]); close(pipe2[1]); + fcntl(pipe1[1], F_SETFD, FD_CLOEXEC); + fcntl(pipe2[0], F_SETFD, FD_CLOEXEC); x->x_outfd = fdopen(pipe1[1], "w"); x->x_infd = fdopen(pipe2[0], "r"); x->x_childpid = pid; @@ -512,7 +518,7 @@ static void *pd_tilde_new(t_symbol *s, int argc, t_atom *argv) int ninsig = 2, noutsig = 2, j, fifo = 5; float sr = sys_getsr(); t_sample **g; - t_symbol *pddir = sys_guidir, + t_symbol *pddir = sys_libdir, *scheddir = gensym(class_gethelpdir(pd_tilde_class)); /* fprintf(stderr, "pd %s, sched %s\n", pddir->s_name, scheddir->s_name); */ while (argc > 0) diff --git a/extra/pique/makefile b/extra/pique/makefile index 562ce23b9..ebcbd93a8 100644 --- a/extra/pique/makefile +++ b/extra/pique/makefile @@ -1,4 +1,4 @@ NAME=pique CSYM=pique -include ../makefile +include ../makefile.subdir diff --git a/extra/pique/pique.c b/extra/pique/pique.c index a53ad765c..19cee2ae2 100644 --- a/extra/pique/pique.c +++ b/extra/pique/pique.c @@ -51,7 +51,7 @@ static float hanning(float pidetune, float sinpidetune) (sinpidetune/(pidetune+pi) + sinpidetune/(pidetune-pi))); } -static float peakerror(float *fpreal, float *fpimag, float pidetune, +static float peakerror(t_word *fpreal, t_word *fpimag, float pidetune, float norm, float peakreal, float peakimag) { float sinpidetune = sin(pidetune); @@ -61,8 +61,10 @@ static float peakerror(float *fpreal, float *fpimag, float pidetune, peakreal * cospidetune + peakimag * sinpidetune); float imagshould = windowshould * ( peakimag * cospidetune - peakreal * sinpidetune); - float realgot = norm * (fpreal[0] - 0.5 * (fpreal[1] + fpreal[-1])); - float imaggot = norm * (fpimag[0] - 0.5 * (fpimag[1] + fpimag[-1])); + float realgot = norm * (fpreal[0].w_float - + 0.5 * (fpreal[1].w_float + fpreal[-1].w_float)); + float imaggot = norm * (fpimag[0].w_float - + 0.5 * (fpimag[1].w_float + fpimag[-1].w_float)); float realdev = realshould - realgot, imagdev = imagshould - imaggot; /* post("real %f->%f; imag %f->%f", realshould, realgot, @@ -70,7 +72,7 @@ static float peakerror(float *fpreal, float *fpimag, float pidetune, return (realdev * realdev + imagdev * imagdev); } -static void pique_doit(int npts, t_float *fpreal, t_float *fpimag, +static void pique_doit(int npts, t_word *fpreal, t_word *fpimag, int npeak, int *nfound, t_float *fpfreq, t_float *fpamp, t_float *fpampre, t_float *fpampim, float errthresh) { @@ -78,13 +80,15 @@ static void pique_doit(int npts, t_float *fpreal, t_float *fpimag, float oneovern = 1.0/ (float)npts; float fperbin = srate * oneovern; float pow1, pow2 = 0, pow3 = 0, pow4 = 0, pow5 = 0; - float re1, re2 = 0, re3 = *fpreal; + float re1, re2 = 0, re3 = fpreal->w_float; float im1, im2 = 0, im3 = 0, powthresh, relativeerror; int count, peakcount = 0, n2 = (npts >> 1); float *fp1, *fp2; - for (count = n2, fp1 = fpreal, fp2 = fpimag, powthresh = 0; - count--; fp1++, fp2++) - powthresh += (*fp1) * (*fp1) + (*fp2) * (*fp2) ; + t_word *wp1, *wp2; + for (count = n2, wp1 = fpreal, wp2 = fpimag, powthresh = 0; + count--; wp1++, wp2++) + powthresh += (wp1->w_float) * (wp1->w_float) + + (wp2->w_float) * (wp2->w_float) ; powthresh *= 0.00001; for (count = 1; count < n2; count++) { @@ -98,10 +102,10 @@ static void pique_doit(int npts, t_float *fpreal, t_float *fpimag, fpimag++; re1 = re2; re2 = re3; - re3 = *fpreal; + re3 = fpreal->w_float; im1 = im2; im2 = im3; - im3 = *fpimag; + im3 = fpimag->w_float; if (count < 2) continue; pow1 = pow2; pow2 = pow3; @@ -118,12 +122,12 @@ static void pique_doit(int npts, t_float *fpreal, t_float *fpimag, || pow3 < powthresh) continue; /* go back for the raw FFT values around the peak. */ - rpeak = fpreal[-3]; - rpeaknext = fpreal[-2]; - rpeakprev = fpreal[-4]; - ipeak = fpimag[-3]; - ipeaknext = fpimag[-2]; - ipeakprev = fpimag[-4]; + rpeak = fpreal[-3].w_float; + rpeaknext = fpreal[-2].w_float; + rpeakprev = fpreal[-4].w_float; + ipeak = fpimag[-3].w_float; + ipeaknext = fpimag[-2].w_float; + ipeakprev = fpimag[-4].w_float; /* recalculate Hanning-windowed spectrum by convolution */ windreal = rpeak - 0.5 * (rpeaknext + rpeakprev); windimag = ipeak - 0.5 * (ipeaknext + ipeakprev); @@ -180,15 +184,15 @@ static void pique_list(t_pique *x, t_symbol *s, int argc, t_atom *argv) int npeak = atom_getintarg(3, argc, argv); int n; t_garray *a; - t_float *fpreal, *fpimag; + t_word *fpreal, *fpimag; if (npts < 8 || npeak < 1) error("pique: bad npoints or npeak"); if (npeak > x->x_n) npeak = x->x_n; if (!(a = (t_garray *)pd_findbyclass(symreal, garray_class)) || - !garray_getfloatarray(a, &n, &fpreal) || + !garray_getfloatwords(a, &n, &fpreal) || n < npts) error("%s: missing or bad array", symreal->s_name); else if (!(a = (t_garray *)pd_findbyclass(symimag, garray_class)) || - !garray_getfloatarray(a, &n, &fpimag) || + !garray_getfloatwords(a, &n, &fpimag) || n < npts) error("%s: missing or bad array", symimag->s_name); else diff --git a/extra/sigmund~/makefile b/extra/sigmund~/makefile index 3dc176b3b..3c2f8f1c0 100644 --- a/extra/sigmund~/makefile +++ b/extra/sigmund~/makefile @@ -1,4 +1,4 @@ NAME=sigmund~ CSYM=sigmund_tilde -include ../makefile +include ../makefile.subdir diff --git a/extra/sigmund~/sigmund~.c b/extra/sigmund~/sigmund~.c index 92604b7ea..968c5c630 100644 --- a/extra/sigmund~/sigmund~.c +++ b/extra/sigmund~/sigmund~.c @@ -13,7 +13,7 @@ and usable in other contexts. The one external requirement is a real single-precision FFT, invoked as in the Mayer one: */ -#ifdef NT +#ifdef _MSC_VER /* this is only needed with Microsoft's compiler */ __declspec(dllimport) extern #endif void mayer_realfft(int npoints, float *buf); @@ -28,7 +28,7 @@ for example, defines this in the file d_fft_mayer.c or d_fft_fftsg.c. */ #include <string.h> #ifdef _WIN32 #include <malloc.h> -#else +#elif ! defined(_MSC_VER) #include <alloca.h> #endif #include <stdlib.h> @@ -230,9 +230,12 @@ static void sigmund_remask(int maxbin, int bestindex, float powmask, } } +#define PEAKMASKFACTOR 1. +#define PEAKTHRESHFACTOR 0.6 + static void sigmund_getrawpeaks(int npts, float *insamps, int npeak, t_peak *peakv, int *nfound, float *power, float srate, int loud, - float param1, float param2, float param3, float hifreq) + float hifreq) { float oneovern = 1.0/ (float)npts; float fperbin = 0.5 * srate * oneovern, totalpower = 0; @@ -242,7 +245,6 @@ static void sigmund_getrawpeaks(int npts, float *insamps, float *rawreal, *rawimag, *maskbuf, *powbuf; float *bigbuf = alloca(sizeof (float ) * (2*NEGBINS + 6*npts)); int maxbin = hifreq/fperbin; - int tweak = (param3 == 0); if (maxbin > npts - NEGBINS) maxbin = npts - NEGBINS; /* if (loud) post("tweak %d", tweak); */ @@ -294,7 +296,7 @@ static void sigmund_getrawpeaks(int npts, float *insamps, pow1 = powbuf[bin]; if (pow1 > maxpower && pow1 > maskbuf[bin]) { - float thresh = param2 * (powbuf[bin-2]+powbuf[bin+2]); + float thresh = PEAKTHRESHFACTOR * (powbuf[bin-2]+powbuf[bin+2]); if (pow1 > thresh) maxpower = pow1, bestindex = bin; } @@ -304,7 +306,7 @@ static void sigmund_getrawpeaks(int npts, float *insamps, break; fp1 = rawreal+bestindex; fp2 = rawimag+bestindex; - powmask = maxpower * exp(-param1 * log(10.) / 10.); + powmask = maxpower * PEAKMASKFACTOR; /* if (loud > 2) post("maxpower %f, powmask %f, param1 %f", maxpower, powmask, param1); */ @@ -344,11 +346,8 @@ static void sigmund_getrawpeaks(int npts, float *insamps, peakv[peakcount].p_ampreal = oneovern * ampoutreal; peakv[peakcount].p_ampimag = oneovern * ampoutimag; } - if (tweak) - { - sigmund_tweak(npts, rawreal, rawimag, peakcount, peakv, fperbin, loud); - sigmund_tweak(npts, rawreal, rawimag, peakcount, peakv, fperbin, loud); - } + sigmund_tweak(npts, rawreal, rawimag, peakcount, peakv, fperbin, loud); + sigmund_tweak(npts, rawreal, rawimag, peakcount, peakv, fperbin, loud); for (i = 0; i < peakcount; i++) { peakv[i].p_pit = sigmund_ftom(peakv[i].p_freq); @@ -360,13 +359,12 @@ static void sigmund_getrawpeaks(int npts, float *insamps, /*************** Routines for finding fundamental pitch *************/ #define PITCHNPEAK 12 -#define PITCHUNCERTAINTY 0.3 #define HALFTONEINC 0.059 #define SUBHARMONICS 16 #define DBPERHALFTONE 0.0 static void sigmund_getpitch(int npeak, t_peak *peakv, float *freqp, - float npts, float srate, int loud) + float npts, float srate, float nharmonics, float amppower, int loud) { float fperbin = 0.5 * srate / npts; int npit = 48 * sigmund_ilog2(npts), i, j, k, nsalient; @@ -407,7 +405,7 @@ static void sigmund_getpitch(int npeak, t_peak *peakv, float *freqp, t_peak *thispeak = bigpeaks[i]; float weightindex = (48./LOG2) * log(thispeak->p_freq/(2.*fperbin)); - float loudness = sqrt(thispeak->p_amp); + float loudness = pow(thispeak->p_amp, amppower); /* post("index %f, uncertainty %f", weightindex, pitchuncertainty); */ for (j = 0; j < SUBHARMONICS; j++) { @@ -422,7 +420,7 @@ static void sigmund_getpitch(int npeak, t_peak *peakv, float *freqp, if (loindex < 0) loindex = 0; for (k = loindex; k <= hiindex; k++) - weights[k] += loudness * 6. / (6. + j); + weights[k] += loudness * nharmonics / (nharmonics + j); } sumweight += loudness; } @@ -860,8 +858,8 @@ typedef struct _sigmund static void sigmund_preinit(t_sigmund *x) { x->x_npts = NPOINTS_DEF; - x->x_param1 = 0; - x->x_param2 = 0.6; + x->x_param1 = 6; + x->x_param2 = 0.5; x->x_param3 = 0; x->x_hop = HOP_DEF; x->x_mode = MODE_STREAM; @@ -977,10 +975,10 @@ static void sigmund_doit(t_sigmund *x, int npts, float *arraypoints, int nfound, i, cnt; float freq = 0, power, note = 0; sigmund_getrawpeaks(npts, arraypoints, x->x_npeak, peakv, - &nfound, &power, srate, loud, x->x_param1, x->x_param2, x->x_param3, - x->x_maxfreq); + &nfound, &power, srate, loud, x->x_maxfreq); if (x->x_dopitch) - sigmund_getpitch(nfound, peakv, &freq, npts, srate, loud); + sigmund_getpitch(nfound, peakv, &freq, npts, srate, + x->x_param1, x->x_param2, loud); if (x->x_donote) notefinder_doit(&x->x_notefinder, freq, power, ¬e, x->x_vibrato, 1 + x->x_stabletime * 0.001f * x->x_sr / (float)x->x_hop, @@ -1112,7 +1110,7 @@ static void sigmund_tick(t_sigmund *x) static t_int *sigmund_perform(t_int *w) { t_sigmund *x = (t_sigmund *)(w[1]); - float *in = (float *)(w[2]); + t_sample *in = (float *)(w[2]); int n = (int)(w[3]); if (x->x_hop % n) diff --git a/extra/stdout/makefile b/extra/stdout/makefile index 67801999b..6041eeb71 100644 --- a/extra/stdout/makefile +++ b/extra/stdout/makefile @@ -1,4 +1,4 @@ NAME=stdout CSYM=stdout -include ../makefile +include ../makefile.subdir diff --git a/src/s_audio.c b/src/s_audio.c index cfd2c64ea..bff3c3abc 100644 --- a/src/s_audio.c +++ b/src/s_audio.c @@ -6,23 +6,21 @@ audio settings from argparse routine and from dialog window. */ -#include "config.h" - #include "m_pd.h" #include "s_stuff.h" #include <stdio.h> -#ifdef HAVE_UNISTD_H +#ifdef _WIN32 +#include <time.h> +#else #include <unistd.h> -/* XXX Hack!!! These should be checked for independently of unistd.h ... */ #include <sys/time.h> #include <sys/resource.h> -#endif +#endif /* _WIN32 */ #include <stdlib.h> #include <string.h> #include <errno.h> #define SYS_DEFAULTCH 2 -#define SYS_MAXCH 100 typedef long t_pa_sample; #define SYS_SAMPLEWIDTH sizeof(t_pa_sample) #define SYS_BYTESPERCHAN (DEFDACBLKSIZE * SYS_SAMPLEWIDTH) @@ -40,7 +38,6 @@ static void audio_getdevs(char *indevlist, int *nindevs, int sys_inchannels; int sys_outchannels; int sys_advance_samples; /* scheduler advance in samples */ -int sys_blocksize = 0; /* audio I/O block size in sample frames */ int sys_audioapi = API_DEFAULT; int sys_audioapiopened = -1; /* save last API opened for later closing */ static int sys_meters; /* true if we're metering */ @@ -67,19 +64,15 @@ static int audio_naudiooutdev = -1; static int audio_audiooutdev[MAXAUDIOOUTDEV]; static int audio_audiochoutdev[MAXAUDIOOUTDEV]; static int audio_rate; -static int audio_advance; +static int audio_advance = -1; static int audio_callback; +static int audio_blocksize; static int audio_callback_is_open; /* reflects true actual state */ static int audio_nextinchans, audio_nextoutchans; void sched_audio_callbackfn(void); void sched_reopenmeplease(void); -#ifdef USEAPI_JACK - /* needed to fix srate when using jack, inclded in s_audio_jack.c */ -extern int jack_get_srate(void); -#endif /* JACK */ - static int audio_isopen(void) { return (audio_state && @@ -90,7 +83,7 @@ static int audio_isopen(void) void sys_get_audio_params( int *pnaudioindev, int *paudioindev, int *chindev, int *pnaudiooutdev, int *paudiooutdev, int *choutdev, - int *prate, int *padvance, int *pcallback) + int *prate, int *padvance, int *pcallback, int *pblocksize) { int i; *pnaudioindev = audio_naudioindev; @@ -100,23 +93,17 @@ void sys_get_audio_params( *pnaudiooutdev = audio_naudiooutdev; for (i = 0; i < MAXAUDIOOUTDEV; i++) paudiooutdev[i] = audio_audiooutdev[i], - choutdev[i] = audio_audiochoutdev[i]; -#ifdef USEAPI_JACK - if (sys_audioapiopened == API_JACK) { - if (jack_get_srate()) { - audio_rate = jack_get_srate(); - } - } -#endif /* JACK */ + choutdev[i] = audio_audiochoutdev[i]; *prate = audio_rate; *padvance = audio_advance; *pcallback = audio_callback; + *pblocksize = audio_blocksize; } void sys_save_audio_params( int naudioindev, int *audioindev, int *chindev, int naudiooutdev, int *audiooutdev, int *choutdev, - int rate, int advance, int callback) + int rate, int advance, int callback, int blocksize) { int i; audio_naudioindev = naudioindev; @@ -130,6 +117,7 @@ void sys_save_audio_params( audio_rate = rate; audio_advance = advance; audio_callback = callback; + audio_blocksize = blocksize; } /* init routines for any API which needs to set stuff up before @@ -171,8 +159,8 @@ void sys_setchsr(int chin, int chout, int sr) sys_outchannels = chout; sys_dacsr = sr; sys_advance_samples = (sys_schedadvance * sys_dacsr) / (1000000.); - if (sys_advance_samples < 3 * DEFDACBLKSIZE) - sys_advance_samples = 3 * DEFDACBLKSIZE; + if (sys_advance_samples < DEFDACBLKSIZE) + sys_advance_samples = DEFDACBLKSIZE; sys_soundin = (t_sample *)getbytes(inbytes); memset(sys_soundin, 0, inbytes); @@ -195,7 +183,7 @@ void sys_setchsr(int chin, int chout, int sr) void sys_set_audio_settings(int naudioindev, int *audioindev, int nchindev, int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev, - int *choutdev, int rate, int advance, int callback) + int *choutdev, int rate, int advance, int callback, int blocksize) { int i, *ip; int defaultchannels = SYS_DEFAULTCH; @@ -210,8 +198,10 @@ void sys_set_audio_settings(int naudioindev, int *audioindev, int nchindev, if (rate < 1) rate = DEFAULTSRATE; - if (advance <= 0) + if (advance < 0) advance = DEFAULTADVANCE; + if (blocksize != (1 << ilog2(blocksize)) || blocksize < DEFDACBLKSIZE) + blocksize = DEFDACBLKSIZE; audio_init(); /* Since the channel vector might be longer than the audio device vector, or vice versa, we fill the shorter one @@ -339,7 +329,8 @@ void sys_set_audio_settings(int naudioindev, int *audioindev, int nchindev, audio_nextinchans = inchans; audio_nextoutchans = outchans; sys_save_audio_params(nrealindev, realindev, realinchans, - nrealoutdev, realoutdev, realoutchans, rate, advance, callback); + nrealoutdev, realoutdev, realoutchans, rate, advance, callback, + blocksize); } void sys_close_audio(void) @@ -374,6 +365,21 @@ void sys_close_audio(void) if (sys_audioapiopened == API_MMIO) mmio_close_audio(); else +#endif +#ifdef USEAPI_AUDIOUNIT + if (sys_audioapiopened == API_AUDIOUNIT) + audiounit_close_audio(); + else +#endif +#ifdef USEAPI_ESD + if (sys_audioapiopened == API_ESD) + esd_close_audio(); + else +#endif +#ifdef USEAPI_DUMMY + if (sys_audioapiopened == API_DUMMY) + dummy_close_audio(); + else #endif post("sys_close_audio: unknown API %d", sys_audioapiopened); sys_inchannels = sys_outchannels = 0; @@ -381,6 +387,8 @@ void sys_close_audio(void) sched_set_using_audio(SCHED_AUDIO_NONE); audio_state = 0; audio_callback_is_open = 0; + + sys_vgui("set pd_whichapi 0\n"); } /* open audio using whatever parameters were last used */ @@ -388,9 +396,10 @@ void sys_reopen_audio( void) { int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV]; int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV]; - int rate, advance, callback, outcome = 0; + int rate, advance, callback, blocksize, outcome = 0; sys_get_audio_params(&naudioindev, audioindev, chindev, - &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback); + &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback, + &blocksize); sys_setchsr(audio_nextinchans, audio_nextoutchans, rate); if (!naudioindev && !naudiooutdev) { @@ -400,7 +409,9 @@ void sys_reopen_audio( void) #ifdef USEAPI_PORTAUDIO if (sys_audioapi == API_PORTAUDIO) { - int blksize = (sys_blocksize ? sys_blocksize : 64); + int blksize = (audio_blocksize ? audio_blocksize : 64); + if (sys_verbose) + fprintf(stderr, "blksize %d, advance %d\n", blksize, sys_advance_samples/blksize); outcome = pa_open_audio((naudioindev > 0 ? chindev[0] : 0), (naudiooutdev > 0 ? choutdev[0] : 0), rate, sys_soundin, sys_soundout, blksize, sys_advance_samples/blksize, @@ -413,14 +424,16 @@ void sys_reopen_audio( void) #ifdef USEAPI_JACK if (sys_audioapi == API_JACK) outcome = jack_open_audio((naudioindev > 0 ? chindev[0] : 0), - (naudioindev > 0 ? choutdev[0] : 0), rate); + (naudioindev > 0 ? choutdev[0] : 0), rate, + (callback ? sched_audio_callbackfn : 0)); else #endif #ifdef USEAPI_OSS if (sys_audioapi == API_OSS) outcome = oss_open_audio(naudioindev, audioindev, naudioindev, - chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate); + chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate, + audio_blocksize); else #endif #ifdef USEAPI_ALSA @@ -428,13 +441,32 @@ void sys_reopen_audio( void) be open for both input and output. */ if (sys_audioapi == API_ALSA) outcome = alsa_open_audio(naudioindev, audioindev, naudioindev, - chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate); + chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate, + audio_blocksize); else #endif #ifdef USEAPI_MMIO if (sys_audioapi == API_MMIO) outcome = mmio_open_audio(naudioindev, audioindev, naudioindev, + chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate, + audio_blocksize); + else +#endif +#ifdef USEAPI_AUDIOUNIT + if (sys_audioapi == API_AUDIOUNIT) + outcome = audiounit_open_audio((naudioindev > 0 ? chindev[0] : 0), + (naudioindev > 0 ? choutdev[0] : 0), rate); + else +#endif +#ifdef USEAPI_ESD + if (sys_audioapi == API_ALSA) + outcome = esd_open_audio(naudioindev, audioindev, naudioindev, chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate); + else +#endif +#ifdef USEAPI_DUMMY + if (sys_audioapi == API_DUMMY) + outcome = dummy_open_audio(naudioindev, naudiooutdev, rate); else #endif if (sys_audioapi == API_NONE) @@ -507,6 +539,21 @@ int sys_send_dacs(void) if (sys_audioapi == API_MMIO) return (mmio_send_dacs()); else +#endif +#ifdef USEAPI_AUDIOUNIT + if (sys_audioapi == API_AUDIOUNIT) + return (audiounit_send_dacs()); + else +#endif +#ifdef USEAPI_ESD + if (sys_audioapi == API_ESD) + return (esd_send_dacs()); + else +#endif +#ifdef USEAPI_DUMMY + if (sys_audioapi == API_DUMMY) + return (dummy_send_dacs()); + else #endif post("unknown API"); return (0); @@ -564,6 +611,7 @@ static void audio_getdevs(char *indevlist, int *nindevs, { jack_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti, maxndev, devdescsize); + *cancallback = 1; } else #endif @@ -590,6 +638,28 @@ static void audio_getdevs(char *indevlist, int *nindevs, maxndev, devdescsize); } else +#endif +#ifdef USEAPI_AUDIOUNIT + if (sys_audioapi == API_AUDIOUNIT) + { + } + else +#endif +#ifdef USEAPI_ESD + if (sys_audioapi == API_ESD) + { + esd_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti, + maxndev, devdescsize); + } + else +#endif +#ifdef USEAPI_DUMMY + if (sys_audioapi == API_DUMMY) + { + dummy_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti, + maxndev, devdescsize); + } + else #endif { /* this shouldn't happen once all the above get filled in. */ @@ -650,7 +720,7 @@ void glob_audio_properties(t_pd *dummy, t_floatarg flongform) audioinchan1, audioinchan2, audioinchan3, audioinchan4, audiooutdev1, audiooutdev2, audiooutdev3, audiooutdev4, audiooutchan1, audiooutchan2, audiooutchan3, audiooutchan4; - int rate, advance, callback; + int rate, advance, callback, blocksize; /* these are all the devices on your system: */ char indevlist[MAXNDEV*DEVDESCSIZE], outdevlist[MAXNDEV*DEVDESCSIZE]; int nindevs = 0, noutdevs = 0, canmulti = 0, cancallback = 0, i; @@ -669,13 +739,8 @@ void glob_audio_properties(t_pd *dummy, t_floatarg flongform) outdevlist + i * DEVDESCSIZE); sys_get_audio_params(&naudioindev, audioindev, chindev, - &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback); - -#ifdef USEAPI_JACK - if (sys_audioapiopened == API_JACK) { - sys_setchsr(audio_nextinchans, audio_nextoutchans, rate); - } -#endif /* JACK */ + &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback, + &blocksize); /* post("naudioindev %d naudiooutdev %d longform %f", naudioindev, naudiooutdev, flongform); */ @@ -702,13 +767,13 @@ void glob_audio_properties(t_pd *dummy, t_floatarg flongform) "pdtk_audio_dialog %%s \ %d %d %d %d %d %d %d %d \ %d %d %d %d %d %d %d %d \ -%d %d %d %d %d\n", +%d %d %d %d %d %d\n", audioindev1, audioindev2, audioindev3, audioindev4, audioinchan1, audioinchan2, audioinchan3, audioinchan4, audiooutdev1, audiooutdev2, audiooutdev3, audiooutdev4, audiooutchan1, audiooutchan2, audiooutchan3, audiooutchan4, rate, advance, canmulti, (cancallback ? callback : -1), - (flongform != 0)); + (flongform != 0), blocksize); gfxstub_deleteforkey(0); gfxstub_new(&glob_pdobject, (void *)glob_audio_properties, buf); } @@ -727,6 +792,7 @@ void glob_audio_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv) int newrate = atom_getintarg(16, argc, argv); int newadvance = atom_getintarg(17, argc, argv); int newcallback = atom_getintarg(18, argc, argv); + int newblocksize = atom_getintarg(19, argc, argv); for (i = 0; i < 4; i++) { @@ -759,14 +825,27 @@ void glob_audio_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv) } } - if (newcallback < 0) - newcallback = 0; - if (!audio_callback_is_open && !newcallback) - sys_close_audio(); - sys_set_audio_settings(nindev, newaudioindev, nindev, newaudioinchan, + sys_set_audio_settings_reopen(nindev, newaudioindev, nindev, newaudioinchan, noutdev, newaudiooutdev, noutdev, newaudiooutchan, - newrate, newadvance, (newcallback >= 0 ? newcallback : 0)); - if (!audio_callback_is_open && !newcallback) + newrate, newadvance, newcallback, newblocksize); +} + +void sys_set_audio_settings_reopen(int naudioindev, int *audioindev, int nchindev, + int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev, + int *choutdev, int rate, int advance, int callback, int newblocksize) +{ + if (callback < 0) + callback = 0; + if (newblocksize != (1<<ilog2(newblocksize)) || + newblocksize < DEFDACBLKSIZE || newblocksize > 2048) + newblocksize = DEFDACBLKSIZE; + + if (!audio_callback_is_open && !callback) + sys_close_audio(); + sys_set_audio_settings(naudioindev, audioindev, nchindev, chindev, + naudiooutdev, audiooutdev, nchoutdev, choutdev, + rate, advance, (callback >= 0 ? callback : 0), newblocksize); + if (!audio_callback_is_open && !callback) sys_reopen_audio(); else sched_reopenmeplease(); } @@ -797,20 +876,35 @@ void sys_listdevs(void ) if (sys_audioapi == API_MMIO) sys_listaudiodevs(); else +#endif +#ifdef USEAPI_AUDIOUNIT + if (sys_audioapi == API_AUDIOUNIT) + sys_listaudiodevs(); + else +#endif +#ifdef USEAPI_ESD + if (sys_audioapi == API_ESD) + sys_listaudiodevs(); + else +#endif +#ifdef USEAPI_DUMMY + if (sys_audioapi == API_DUMMY) + sys_listaudiodevs(); + else #endif post("unknown API"); sys_listmididevs(); } -void sys_setblocksize(int n) +void sys_get_audio_devs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int *canmulti, int *cancallback, + int maxndev, int devdescsize) { - if (n < 1) - n = 1; - if (n != (1 << ilog2(n))) - post("warning: adjusting blocksize to power of 2: %d", - (n = (1 << ilog2(n)))); - sys_blocksize = n; + audio_getdevs(indevlist, nindevs, + outdevlist, noutdevs, + canmulti, cancallback, + maxndev, devdescsize); } void sys_set_audio_api(int which) @@ -892,6 +986,15 @@ void sys_get_audio_apis(char *buf) #endif #ifdef USEAPI_JACK sprintf(buf + strlen(buf), "{jack %d} ", API_JACK); n++; +#endif +#ifdef USEAPI_AUDIOUNIT + sprintf(buf + strlen(buf), "{AudioUnit %d} ", API_AUDIOUNIT); n++; +#endif +#ifdef USEAPI_ESD + sprintf(buf + strlen(buf), "{ESD %d} ", API_ESD); n++; +#endif +#ifdef USEAPI_DUMMY + sprintf(buf + strlen(buf), "{dummy %d} ", API_DUMMY); n++; #endif strcat(buf, "}"); /* then again, if only one API (or none) we don't offer any choice. */ diff --git a/src/s_audio_alsa.c b/src/s_audio_alsa.c index a5034c8dc..cf7311091 100644 --- a/src/s_audio_alsa.c +++ b/src/s_audio_alsa.c @@ -90,9 +90,17 @@ static int alsaio_canmmap(t_alsa_dev *dev) return ((err1 < 0) && (err2 >= 0)); } +static void check_setup_error(int err, int out, const char *why) { + char bf[256]; + snprintf(bf, sizeof bf, "%s (%s)", why, out ? "output" : "input"); + check_error(err, bf); +} + static int alsaio_setup(t_alsa_dev *dev, int out, int *channels, int *rate, int nfrags, int frag_size) { +#define CHECK_ERROR(why_) check_setup_error(err, out, why_) + int bufsizeforthis, err; snd_pcm_hw_params_t* hw_params; unsigned int tmp_uint; @@ -110,14 +118,14 @@ static int alsaio_setup(t_alsa_dev *dev, int out, int *channels, int *rate, /* get the default params */ err = snd_pcm_hw_params_any(dev->a_handle, hw_params); - check_error(err, "snd_pcm_hw_params_any"); + CHECK_ERROR("snd_pcm_hw_params_any"); /* try to set interleaved access */ err = snd_pcm_hw_params_set_access(dev->a_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); if (err < 0) return (-1); - check_error(err, "snd_pcm_hw_params_set_access"); + CHECK_ERROR("snd_pcm_hw_params_set_access"); #if 0 /* enable this to print out which formats are available */ { int i; @@ -141,7 +149,7 @@ static int alsaio_setup(t_alsa_dev *dev, int out, int *channels, int *rate, "PD-ALSA: 32/24 bit format not available - using 16\n"); */ err = snd_pcm_hw_params_set_format(dev->a_handle, hw_params, SND_PCM_FORMAT_S16); - check_error(err, "snd_pcm_hw_params_set_format"); + CHECK_ERROR("_pcm_hw_params_set_format"); dev->a_sampwidth = 2; } else dev->a_sampwidth = 3; @@ -154,22 +162,22 @@ static int alsaio_setup(t_alsa_dev *dev, int out, int *channels, int *rate, /* set the subformat */ err = snd_pcm_hw_params_set_subformat(dev->a_handle, hw_params, SND_PCM_SUBFORMAT_STD); - check_error(err, "snd_pcm_hw_params_set_subformat"); + CHECK_ERROR("snd_pcm_hw_params_set_subformat"); /* set the number of channels */ tmp_uint = *channels; err = snd_pcm_hw_params_set_channels_min(dev->a_handle, hw_params, &tmp_uint); - check_error(err, "snd_pcm_hw_params_set_channels"); + CHECK_ERROR("snd_pcm_hw_params_set_channels"); if (tmp_uint != (unsigned)*channels) post("ALSA: set %s channels to %d", (out?"output":"input"), tmp_uint); *channels = tmp_uint; dev->a_channels = *channels; /* set the sampling rate */ - err = snd_pcm_hw_params_set_rate_min(dev->a_handle, hw_params, + err = snd_pcm_hw_params_set_rate_near(dev->a_handle, hw_params, (unsigned int *)rate, 0); - check_error(err, "snd_pcm_hw_params_set_rate_min (input)"); + CHECK_ERROR("snd_pcm_hw_params_set_rate_min"); #if 0 err = snd_pcm_hw_params_get_rate(hw_params, &subunitdir); post("input sample rate %d", err); @@ -185,7 +193,7 @@ static int alsaio_setup(t_alsa_dev *dev, int out, int *channels, int *rate, err = snd_pcm_hw_params_set_period_size_near(dev->a_handle, hw_params, &tmp_snd_pcm_uframes, 0); #endif - check_error(err, "snd_pcm_hw_params_set_period_size_near (input)"); + CHECK_ERROR("snd_pcm_hw_params_set_period_size_near"); /* set the buffer size */ #ifdef ALSAAPI9 @@ -196,10 +204,10 @@ static int alsaio_setup(t_alsa_dev *dev, int out, int *channels, int *rate, err = snd_pcm_hw_params_set_buffer_size_near(dev->a_handle, hw_params, &tmp_snd_pcm_uframes); #endif - check_error(err, "snd_pcm_hw_params_set_buffer_size_near (input)"); + CHECK_ERROR("snd_pcm_hw_params_set_buffer_size_near"); err = snd_pcm_hw_params(dev->a_handle, hw_params); - check_error(err, "snd_pcm_hw_params (input)"); + CHECK_ERROR("snd_pcm_hw_params"); /* set up the buffer */ bufsizeforthis = DEFDACBLKSIZE * dev->a_sampwidth * *channels; @@ -227,18 +235,19 @@ static int alsaio_setup(t_alsa_dev *dev, int out, int *channels, int *rate, alsa_snd_bufsize = bufsizeforthis; } return (1); +#undef CHECK_ERROR } /* return 0 on success */ int alsa_open_audio(int naudioindev, int *audioindev, int nchindev, int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev, - int *choutdev, int rate) + int *choutdev, int rate, int blocksize) { int err, inchans = 0, outchans = 0, subunitdir; char devname[512]; snd_output_t* out; - int frag_size = (sys_blocksize ? sys_blocksize : ALSA_DEFFRAGSIZE); + int frag_size = (blocksize ? blocksize : ALSA_DEFFRAGSIZE); int nfrags, i, iodev, dev2; int wantinchans, wantoutchans, device; @@ -292,7 +301,7 @@ int alsa_open_audio(int naudioindev, int *audioindev, int nchindev, if (alsa_usemmap) { post("using mmap audio interface"); - if (alsamm_open_audio(rate)) + if (alsamm_open_audio(rate, blocksize)) goto blewit; else return (0); } @@ -469,7 +478,7 @@ int alsa_send_dacs(void) ((char *)(alsa_snd_buf))[3*j+1] = ((s>>8) & 255); ((char *)(alsa_snd_buf))[3*j+2] = ((s>>16) & 255); #else - fprintf(stderr("big endian 24-bit not supported"); + fprintf(stderr, "big endian 24-bit not supported"); #endif } for (; i < thisdevchans; i++, ch++) @@ -581,7 +590,7 @@ int alsa_send_dacs(void) * (1./ INT32_MAX); } #else - fprintf(stderr("big endian 24-bit not supported"); + fprintf(stderr, "big endian 24-bit not supported"); #endif } else diff --git a/src/s_audio_alsa.h b/src/s_audio_alsa.h index 813be2114..f59cff3c2 100644 --- a/src/s_audio_alsa.h +++ b/src/s_audio_alsa.h @@ -35,6 +35,6 @@ extern t_alsa_dev alsa_outdev[ALSA_MAXDEV]; extern int alsa_nindev; extern int alsa_noutdev; -int alsamm_open_audio(int rate); +int alsamm_open_audio(int rate, int blocksize); void alsamm_close_audio(void); int alsamm_send_dacs(void); diff --git a/src/s_audio_alsamm.c b/src/s_audio_alsamm.c index 3bc4b3692..abcb0a85e 100644 --- a/src/s_audio_alsamm.c +++ b/src/s_audio_alsamm.c @@ -182,7 +182,7 @@ static void check_error(int err, const char *why) error("%s: %s\n", why, snd_strerror(err)); } -int alsamm_open_audio(int rate) +int alsamm_open_audio(int rate, int blocksize) { int err; char devname[80]; @@ -238,16 +238,16 @@ int alsamm_open_audio(int rate) /* set the asked buffer time (alsa buffertime in us)*/ alsamm_buffertime = alsamm_buffersize = 0; - if(sys_blocksize == 0) + if(blocksize == 0) alsamm_buffertime = sys_schedadvance; else - alsamm_buffersize = sys_blocksize; + alsamm_buffersize = blocksize; if(sys_verbose) post("syschedadvance=%d us(%d Samples)so buffertime max should be this=%d" "or sys_blocksize=%d (samples) to use buffersize=%d", sys_schedadvance,sys_advance_samples,alsamm_buffertime, - sys_blocksize,alsamm_buffersize); + blocksize,alsamm_buffersize); alsamm_periods = 0; /* no one wants periods setting from command line ;-) */ diff --git a/src/s_audio_jack.c b/src/s_audio_jack.c index 5181085b9..79d4692ee 100644 --- a/src/s_audio_jack.c +++ b/src/s_audio_jack.c @@ -11,88 +11,140 @@ #include <jack/jack.h> #include <regex.h> - #define MAX_CLIENTS 100 -#define NUM_JACK_PORTS 128 +#define MAX_JACK_PORTS 128 /* seems like higher values give bad xrun problems */ #define BUF_JACK 4096 static jack_nframes_t jack_out_max; #define JACK_OUT_MAX 64 static jack_nframes_t jack_filled = 0; -static t_sample jack_outbuf[NUM_JACK_PORTS*BUF_JACK]; -static t_sample jack_inbuf[NUM_JACK_PORTS*BUF_JACK]; +static t_sample *jack_outbuf; +static t_sample *jack_inbuf; static int jack_started = 0; -static jack_port_t *input_port[NUM_JACK_PORTS]; -static jack_port_t *output_port[NUM_JACK_PORTS]; +static jack_port_t *input_port[MAX_JACK_PORTS]; +static jack_port_t *output_port[MAX_JACK_PORTS]; static int outport_count = 0; static jack_client_t *jack_client = NULL; char *jack_client_names[MAX_CLIENTS]; static int jack_dio_error; - +static t_audiocallback jack_callback; pthread_mutex_t jack_mutex; pthread_cond_t jack_sem; -int jack_get_srate(void) -{ - if (jack_client) return jack_get_sample_rate (jack_client); - else return 0; -} static int process (jack_nframes_t nframes, void *arg) { - int j; - jack_default_audio_sample_t *out, *in; - - if (nframes > JACK_OUT_MAX) jack_out_max = nframes; - else jack_out_max = JACK_OUT_MAX; - if (jack_filled >= nframes) { - if (jack_filled != nframes) fprintf(stderr,"Partial read"); - /* hmm, how to find out whether 't_sample' and 'jack_default_audio_sample_t' are actually the same type??? */ - if(sizeof(t_sample)==sizeof(jack_default_audio_sample_t)) + int j; + jack_default_audio_sample_t *out, *in; + + pthread_mutex_lock(&jack_mutex); + if (nframes > JACK_OUT_MAX) jack_out_max = nframes; + else jack_out_max = JACK_OUT_MAX; + if (jack_filled >= nframes) + { + if (jack_filled != nframes) + fprintf(stderr,"Partial read\n"); + /* hmm, how to find out whether 't_sample' and + 'jack_default_audio_sample_t' are actually the same type??? */ + if (sizeof(t_sample)==sizeof(jack_default_audio_sample_t)) + { + for (j = 0; j < sys_outchannels; j++) + { + out = jack_port_get_buffer (output_port[j], nframes); + memcpy(out, jack_outbuf + (j * BUF_JACK), + sizeof (jack_default_audio_sample_t) * nframes); + } + for (j = 0; j < sys_inchannels; j++) + { + in = jack_port_get_buffer( input_port[j], nframes); + memcpy(jack_inbuf + (j * BUF_JACK), in, + sizeof (jack_default_audio_sample_t) * nframes); + } + } + else + { + unsigned int frame=0; + t_sample*data; + for (j = 0; j < sys_outchannels; j++) + { + out = jack_port_get_buffer (output_port[j], nframes); + data = jack_outbuf + (j * BUF_JACK); + for(frame=0; frame<nframes; frame++) { - for (j = 0; j < sys_outchannels; j++) { - out = jack_port_get_buffer (output_port[j], nframes); - memcpy(out, jack_outbuf + (j * BUF_JACK), sizeof (jack_default_audio_sample_t) * nframes); - } - for (j = 0; j < sys_inchannels; j++) { - in = jack_port_get_buffer( input_port[j], nframes); - memcpy(jack_inbuf + (j * BUF_JACK), in, sizeof (jack_default_audio_sample_t) * nframes); - } - } - else + *out++=*data++; + } + } + for (j = 0; j < sys_inchannels; j++) + { + in = jack_port_get_buffer( input_port[j], nframes); + data = jack_inbuf + (j * BUF_JACK); + for(frame=0; frame<nframes; frame++) { - unsigned int frame=0; - t_sample*data; - for (j = 0; j < sys_outchannels; j++) { - out = jack_port_get_buffer (output_port[j], nframes); - data=jack_outbuf + (j * BUF_JACK); - for(frame=0; frame<nframes; frame++) { - *out++=*data++; - } - } - for (j = 0; j < sys_inchannels; j++) { - in = jack_port_get_buffer( input_port[j], nframes); - data=jack_inbuf+(j*BUF_JACK); - for(frame=0; frame<nframes; frame++) { - *data++=*in++; - } - } + *data++=*in++; } - jack_filled -= nframes; - } else { /* PD could not keep up ! */ - if (jack_started) jack_dio_error = 1; - for (j = 0; j < outport_count; j++) { - out = jack_port_get_buffer (output_port[j], nframes); - memset(out, 0, sizeof (float) * nframes); - } - memset(jack_outbuf,0,sizeof(jack_outbuf)); - jack_filled = 0; + } } - pthread_cond_broadcast(&jack_sem); - return 0; + jack_filled -= nframes; + } + else + { /* PD could not keep up ! */ + if (jack_started) jack_dio_error = 1; + for (j = 0; j < outport_count; j++) + { + out = jack_port_get_buffer (output_port[j], nframes); + memset(out, 0, sizeof (float) * nframes); + memset(jack_outbuf + j * BUF_JACK, 0, BUF_JACK * sizeof(t_sample)); + } + jack_filled = 0; + } + pthread_cond_broadcast(&jack_sem); + pthread_mutex_unlock(&jack_mutex); + return 0; +} + +static int callbackprocess(jack_nframes_t nframes, void *arg) +{ + int chan, j, k; + unsigned int n; + jack_default_audio_sample_t *out[MAX_JACK_PORTS], *in[MAX_JACK_PORTS], *jp; + + if (nframes % DEFDACBLKSIZE) + { + fprintf(stderr, "jack: nframes %d not a multiple of blocksize %d\n", + nframes, DEFDACBLKSIZE); + nframes -= (nframes % DEFDACBLKSIZE); + } + for (chan = 0; chan < sys_inchannels; chan++) + in[chan] = jack_port_get_buffer(input_port[chan], nframes); + for (chan = 0; chan < sys_outchannels; chan++) + out[chan] = jack_port_get_buffer(output_port[chan], nframes); + for (n = 0; n < nframes; n += DEFDACBLKSIZE) + { + t_sample *fp; + for (chan = 0; chan < sys_inchannels; chan++) + { + for (fp = sys_soundin + chan*DEFDACBLKSIZE, + jp = in[chan] + n, j=0; j < DEFDACBLKSIZE; j++) + *fp++ = *jp++; + } + for (chan = 0; chan < sys_outchannels; chan++) + { + for (fp = sys_soundout + chan*DEFDACBLKSIZE, + j = 0; j < DEFDACBLKSIZE; j++) + *fp++ = 0; + } + (*jack_callback)(); + for (chan = 0; chan < sys_outchannels; chan++) + { + for (fp = sys_soundout + chan*DEFDACBLKSIZE, jp = out[chan] + n, + j=0; j < DEFDACBLKSIZE; j++) + *jp++ = *fp++; + } + } + return 0; } static int @@ -102,16 +154,22 @@ jack_srate (jack_nframes_t srate, void *arg) return 0; } + +void glob_audio_setapi(void *dummy, t_floatarg f); + static void jack_shutdown (void *arg) { - verbose(1, "JACK-server shut down"); - sys_close_audio(); + error("JACK: server shut down"); + + jack_deactivate (jack_client); + //jack_client_close(jack_client); /* likely to hang if the server shut down */ jack_client = NULL; + + glob_audio_setapi(NULL, API_NONE); // set pd_whichapi 0 } static int jack_xrun(void* arg) { - verbose(1, "JACK-server xrun"); jack_dio_error = 1; return 0; } @@ -129,55 +187,55 @@ static char** jack_get_clients(void) jack_client_names[0] = NULL; /* Build a list of clients from the list of ports */ - if (jack_ports != NULL) { - for( i = 0; jack_ports[i] != NULL; i++ ) - { - int client_seen; - regmatch_t match_info; - char tmp_client_name[100]; - - /* extract the client name from the port name, using a regex - * that parses the clientname:portname syntax */ - regexec( &port_regex, jack_ports[i], 1, &match_info, 0 ); - memcpy( tmp_client_name, &jack_ports[i][match_info.rm_so], - match_info.rm_eo - match_info.rm_so ); - tmp_client_name[ match_info.rm_eo - match_info.rm_so ] = '\0'; - - /* do we know about this port's client yet? */ - client_seen = 0; - - for( j = 0; j < num_clients; j++ ) - if( strcmp( tmp_client_name, jack_client_names[j] ) == 0 ) - client_seen = 1; - - if( client_seen == 0 ) - { - jack_client_names[num_clients] = (char*)getbytes(strlen(tmp_client_name) + 1); - - /* The alsa_pcm client should go in spot 0. If this - * is the alsa_pcm client AND we are NOT about to put - * it in spot 0 put it in spot 0 and move whatever - * was already in spot 0 to the end. */ - - if( strcmp( "system", tmp_client_name ) == 0 && num_clients > 0 ) - { - char* tmp; - /* alsa_pcm goes in spot 0 */ - tmp = jack_client_names[ num_clients ]; - jack_client_names[ num_clients ] = jack_client_names[0]; - jack_client_names[0] = tmp; - strcpy( jack_client_names[0], tmp_client_name); - } - else - { - /* put the new client at the end of the client list */ - strcpy( jack_client_names[ num_clients ], tmp_client_name ); - } - num_clients++; - - } - } - } + for( i = 0; jack_ports[i] != NULL; i++ ) + { + int client_seen; + regmatch_t match_info; + char tmp_client_name[100]; + + if(num_clients>=MAX_CLIENTS)break; + + + /* extract the client name from the port name, using a regex + * that parses the clientname:portname syntax */ + regexec( &port_regex, jack_ports[i], 1, &match_info, 0 ); + memcpy( tmp_client_name, &jack_ports[i][match_info.rm_so], + match_info.rm_eo - match_info.rm_so ); + tmp_client_name[ match_info.rm_eo - match_info.rm_so ] = '\0'; + + /* do we know about this port's client yet? */ + client_seen = 0; + + for( j = 0; j < num_clients; j++ ) + if( strcmp( tmp_client_name, jack_client_names[j] ) == 0 ) + client_seen = 1; + + if( client_seen == 0 ) + { + jack_client_names[num_clients] = (char*)getbytes(strlen(tmp_client_name) + 1); + + /* The alsa_pcm client should go in spot 0. If this + * is the alsa_pcm client AND we are NOT about to put + * it in spot 0 put it in spot 0 and move whatever + * was already in spot 0 to the end. */ + + if( strcmp( "alsa_pcm", tmp_client_name ) == 0 && num_clients > 0 ) + { + char* tmp; + /* alsa_pcm goes in spot 0 */ + tmp = jack_client_names[ num_clients ]; + jack_client_names[ num_clients ] = jack_client_names[0]; + jack_client_names[0] = tmp; + strcpy( jack_client_names[0], tmp_client_name); + } + else + { + /* put the new client at the end of the client list */ + strcpy( jack_client_names[ num_clients ], tmp_client_name ); + } + num_clients++; + } + } /* for (i=0;i<num_clients;i++) post("client: %s",jack_client_names[i]); */ @@ -205,7 +263,7 @@ static int jack_connect_ports(char* client) if (jack_ports) for (i=0;jack_ports[i] != NULL && i < sys_inchannels;i++) if (jack_connect (jack_client, jack_ports[i], jack_port_name (input_port[i]))) - error("JACK: cannot connect input ports %s -> %s", jack_ports[i],jack_port_name (input_port[i])); + error ("JACK: cannot connect input ports %s -> %s", jack_ports[i],jack_port_name (input_port[i])); @@ -214,7 +272,7 @@ static int jack_connect_ports(char* client) if (jack_ports) for (i=0;jack_ports[i] != NULL && i < sys_outchannels;i++) if (jack_connect (jack_client, jack_port_name (output_port[i]), jack_ports[i])) - error("JACK: cannot connect output ports %s -> %s", jack_port_name (output_port[i]),jack_ports[i]); + error( "JACK: cannot connect output ports %s -> %s", jack_port_name (output_port[i]),jack_ports[i]); @@ -223,199 +281,244 @@ static int jack_connect_ports(char* client) } -void jack_error(const char *desc) { - error("JACK error: %s", desc); +static void pd_jack_error_callback(const char *desc) { + error("JACKerror: %s", desc); return; } - int -jack_open_audio(int inchans, int outchans, int rate) - +jack_open_audio(int inchans, int outchans, int rate, t_audiocallback callback) { - int j; - char port_name[80] = ""; - int client_iterator = 0; - int new_jack = 0; - int srate; - jack_status_t status; + int j; + char port_name[80] = ""; + char client_name[80] = ""; - jack_dio_error = 0; - - if ((inchans == 0) && (outchans == 0)) return 0; + int client_iterator = 0; + int new_jack = 0; + int srate; + jack_status_t status; - if (outchans > NUM_JACK_PORTS) { - error("JACK: %d output ports not supported, setting to %d",outchans, NUM_JACK_PORTS); - outchans = NUM_JACK_PORTS; - } + if (NULL==jack_client_new) + { + fprintf(stderr,"JACK framework not available\n"); + return 1; + } - if (inchans > NUM_JACK_PORTS) { - error("JACK: %d input ports not supported, setting to %d",inchans, NUM_JACK_PORTS); - inchans = NUM_JACK_PORTS; - } + jack_dio_error = 0; - /* try to become a client of the JACK server */ - /* if no JACK server exists, start a default one (jack_client_open() does that for us... */ - if (!jack_client) { - do { - sprintf(port_name,"pure_data_%d",client_iterator); - client_iterator++; - /* do not try to start the jack-server...seems to make problems... */ - jack_client = jack_client_open (port_name, JackNoStartServer, &status, NULL); - if (status & JackServerFailed) { - error("JACK: unable to connect to JACK server"); - jack_client=NULL; - break; - } - } while (status & JackNameNotUnique); + if ((inchans == 0) && (outchans == 0)) return 0; - if(status) { - if (status & JackServerStarted) { - post("JACK: started JACK server?"); - } else { - post("JACK: jack returned status %d", status); - } + if (outchans > MAX_JACK_PORTS) { + error("JACK: %d output ports not supported, setting to %d", + outchans, MAX_JACK_PORTS); + outchans = MAX_JACK_PORTS; + } + + if (inchans > MAX_JACK_PORTS) { + error("JACK: %d input ports not supported, setting to %d", + inchans, MAX_JACK_PORTS); + inchans = MAX_JACK_PORTS; + } + /* try to become a client of the JACK server */ + /* if no JACK server exists, start a default one (jack_client_open() does that for us... */ + if (!jack_client) { + do { + sprintf(client_name,"pure_data_%d",client_iterator); + client_iterator++; + jack_client = jack_client_open (client_name, JackNullOption, &status, NULL); + if (status & JackServerFailed) { + error("JACK: unable to connect to JACK server"); + jack_client=NULL; + break; } - - if (!jack_client) { // jack spits out enough messages already, do not warn + } while (status & JackNameNotUnique); + + if(status) { + if (status & JackServerStarted) { + verbose(1, "JACK: started server"); + } else { + error("JACK: server returned status %d", status); + } + } + verbose(1, "JACK: started server as '%s'", client_name); + + if (!jack_client) { + /* jack spits out enough messages already, do not warn */ sys_inchannels = sys_outchannels = 0; return 1; - } - - jack_get_clients(); - - /* tell the JACK server to call `process()' whenever - there is work to be done. - */ - - jack_set_process_callback (jack_client, process, 0); - - // jack_set_error_function (jack_error); - + } + + sys_inchannels = inchans; + sys_outchannels = outchans; + if (jack_inbuf) + free(jack_inbuf); + if (sys_inchannels) + jack_inbuf = calloc(sizeof(t_sample), sys_inchannels * BUF_JACK); + if (jack_outbuf) + free(jack_outbuf); + if (sys_outchannels) + jack_outbuf = calloc(sizeof(t_sample), sys_outchannels * BUF_JACK); + + jack_get_clients(); + + /* tell the JACK server to call `process()' whenever + there is work to be done. + */ + jack_callback = callback; + jack_set_process_callback (jack_client, + (callback? callbackprocess : process), 0); + + jack_set_error_function (pd_jack_error_callback); + #ifdef JACK_XRUN - jack_set_xrun_callback (jack_client, jack_xrun, NULL); + jack_set_xrun_callback (jack_client, jack_xrun, NULL); #endif - - /* tell the JACK server to call `srate()' whenever - the sample rate of the system changes. - */ - - jack_set_sample_rate_callback (jack_client, jack_srate, 0); - - - /* tell the JACK server to call `jack_shutdown()' if - it ever shuts down, either entirely, or if it - just decides to stop calling us. - */ - - jack_on_shutdown (jack_client, jack_shutdown, 0); - - for (j=0;j<NUM_JACK_PORTS;j++) { - input_port[j]=NULL; - output_port[j] = NULL; - } - - new_jack = 1; - } - /* display the current sample rate. once the client is activated - (see below), you should rely on your own sample rate - callback (see above) for this value. + /* tell the JACK server to call `srate()' whenever + the sample rate of the system changes. */ - - srate = jack_get_sample_rate (jack_client); - sys_dacsr = srate; - - /* create the ports */ - - for (j = 0; j < inchans; j++) { - sprintf(port_name, "input%d", j); - if (!input_port[j]) input_port[j] = jack_port_register (jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); - if (!input_port[j]) { - error("JACK: can only register %d input ports (instead of requested %d)", j, inchans); - sys_inchannels = inchans = j; - break; - } + + jack_set_sample_rate_callback (jack_client, jack_srate, 0); + + + /* tell the JACK server to call `jack_shutdown()' if + it ever shuts down, either entirely, or if it + just decides to stop calling us. + */ + + jack_on_shutdown (jack_client, jack_shutdown, 0); + + for (j=0; j<sys_inchannels; j++) + input_port[j]=NULL; + for (j=0; j<sys_outchannels; j++) + output_port[j] = NULL; + + new_jack = 1; + } + + /* display the current sample rate. once the client is activated + (see below), you should rely on your own sample rate + callback (see above) for this value. + */ + + srate = jack_get_sample_rate (jack_client); + sys_dacsr = srate; + + /* create the ports */ + + for (j = 0; j < inchans; j++) { + sprintf(port_name, "input%d", j); + if (!input_port[j]) input_port[j] = jack_port_register (jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); + if (!input_port[j]) { + error("JACK: can only register %d input ports (instead of requested %d)", j, inchans); + sys_inchannels = inchans = j; + break; } + } - for (j = 0; j < outchans; j++) { - sprintf(port_name, "output%d", j); - if (!output_port[j]) output_port[j] = jack_port_register (jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); - if (!output_port[j]) { - error("JACK: can only register %d output ports (instead of requested %d)", j, outchans); - sys_outchannels = outchans = j; - break; - } - } - outport_count = outchans; + for (j = 0; j < outchans; j++) { + sprintf(port_name, "output%d", j); + if (!output_port[j]) output_port[j] = jack_port_register (jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); + if (!output_port[j]) { + error("JACK: can only register %d output ports (instead of requested %d)", j, outchans); + sys_outchannels = outchans = j; + break; + } + } + outport_count = outchans; - /* tell the JACK server that we are ready to roll */ - - if (new_jack) { - if (jack_activate (jack_client)) { - error("JACK: cannot activate client"); + /* tell the JACK server that we are ready to roll */ + + if (new_jack) { + if (jack_activate (jack_client)) { + error("cannot activate client"); sys_inchannels = sys_outchannels = 0; return 1; - } - - memset(jack_outbuf,0,sizeof(jack_outbuf)); - - if (jack_client_names[0]) + } + + for (j = 0; j < outchans; j++) + memset(jack_outbuf + j * BUF_JACK, 0, + BUF_JACK * sizeof(t_sample)); + + if (jack_client_names[0]) jack_connect_ports(jack_client_names[0]); - pthread_mutex_init(&jack_mutex,NULL); - pthread_cond_init(&jack_sem,NULL); - } - return 0; + pthread_mutex_init(&jack_mutex, NULL); + pthread_cond_init(&jack_sem, NULL); + } + return 0; } void jack_close_audio(void) - { - jack_started = 0; + if (jack_client){ + jack_deactivate (jack_client); + jack_client_close(jack_client); + } + + jack_client=NULL; + jack_started = 0; + + pthread_cond_broadcast(&jack_sem); + + pthread_cond_destroy(&jack_sem); + pthread_mutex_destroy(&jack_mutex); + if (jack_inbuf) + free(jack_inbuf), jack_inbuf = 0; + if (jack_outbuf) + free(jack_outbuf), jack_outbuf = 0; + } int jack_send_dacs(void) { - t_sample * fp; - int j; - int rtnval = SENDDACS_YES; - int timenow; - int timeref = sys_getrealtime(); - - if (!jack_client) return SENDDACS_NO; - - if (!sys_inchannels && !sys_outchannels) return (SENDDACS_NO); - - if (jack_dio_error) { - sys_log_error(ERR_RESYNC); - jack_dio_error = 0; - } - if (jack_filled >= jack_out_max) - pthread_cond_wait(&jack_sem,&jack_mutex); - - jack_started = 1; - - fp = sys_soundout; - for (j = 0; j < sys_outchannels; j++) { - memcpy(jack_outbuf + (j * BUF_JACK) + jack_filled,fp, DEFDACBLKSIZE*sizeof(t_sample)); - fp += DEFDACBLKSIZE; - } - fp = sys_soundin; - for (j = 0; j < sys_inchannels; j++) { - memcpy(fp, jack_inbuf + (j * BUF_JACK) + jack_filled, DEFDACBLKSIZE*sizeof(t_sample)); - fp += DEFDACBLKSIZE; - } + t_sample * fp; + int j; + int rtnval = SENDDACS_YES; + int timenow; + int timeref = sys_getrealtime(); + if (!jack_client) return SENDDACS_NO; + if (!sys_inchannels && !sys_outchannels) return (SENDDACS_NO); + if (jack_dio_error) + { + sys_log_error(ERR_RESYNC); + jack_dio_error = 0; + } + pthread_mutex_lock(&jack_mutex); + if (jack_filled >= jack_out_max) + pthread_cond_wait(&jack_sem,&jack_mutex); - if ((timenow = sys_getrealtime()) - timeref > 0.002) - { - rtnval = SENDDACS_SLEPT; - } + if (!jack_client) + { + pthread_mutex_unlock(&jack_mutex); + return SENDDACS_NO; + } + jack_started = 1; - memset(sys_soundout,0,DEFDACBLKSIZE*sizeof(t_sample)*sys_outchannels); - jack_filled += DEFDACBLKSIZE; - return rtnval; + fp = sys_soundout; + for (j = 0; j < sys_outchannels; j++) + { + memcpy(jack_outbuf + (j * BUF_JACK) + jack_filled, fp, + DEFDACBLKSIZE*sizeof(t_sample)); + fp += DEFDACBLKSIZE; + } + fp = sys_soundin; + for (j = 0; j < sys_inchannels; j++) + { + memcpy(fp, jack_inbuf + (j * BUF_JACK) + jack_filled, + DEFDACBLKSIZE*sizeof(t_sample)); + fp += DEFDACBLKSIZE; + } + jack_filled += DEFDACBLKSIZE; + pthread_mutex_unlock(&jack_mutex); + + if ((timenow = sys_getrealtime()) - timeref > 0.002) + { + rtnval = SENDDACS_SLEPT; + } + memset(sys_soundout, 0, DEFDACBLKSIZE*sizeof(t_sample)*sys_outchannels); + return rtnval; } void jack_getdevs(char *indevlist, int *nindevs, @@ -435,7 +538,7 @@ void jack_getdevs(char *indevlist, int *nindevs, void jack_listdevs( void) { - error("device listing not implemented for jack yet"); + post("device listing not implemented for jack yet\n"); } #endif /* JACK */ diff --git a/src/s_audio_oss.c b/src/s_audio_oss.c index 73f916ce2..10329fed9 100644 --- a/src/s_audio_oss.c +++ b/src/s_audio_oss.c @@ -5,7 +5,11 @@ /* this file inputs and outputs audio using the OSS API available on linux. */ -#include <linux/soundcard.h> +#if defined(__FreeBSD_kernel__) +# include <sys/soundcard.h> +#else +# include <linux/soundcard.h> +#endif #include "m_pd.h" #include "s_stuff.h" @@ -45,7 +49,7 @@ static int linux_meters; /* true if we're metering */ static t_sample linux_inmax; /* max input amplitude */ static t_sample linux_outmax; /* max output amplitude */ static int linux_fragsize = 0; /* for block mode; block size (sample frames) */ - +extern int audio_blocksize; /* stolen from s_audio.c */ /* our device handles */ typedef struct _oss_dev @@ -121,7 +125,8 @@ int oss_reset(int fd) { return err; } -void oss_configure(t_oss_dev *dev, int srate, int dac, int skipblocksize) +void oss_configure(t_oss_dev *dev, int srate, int dac, int skipblocksize, + int suggestedblocksize) { int orig, param, nblk, fd = dev->d_fd, wantformat; int nchannels = dev->d_nchannels; @@ -153,7 +158,7 @@ void oss_configure(t_oss_dev *dev, int srate, int dac, int skipblocksize) { int fragbytes, logfragsize, nfragment; /* setting fragment count and size. */ - linux_fragsize = sys_blocksize; + linux_fragsize = suggestedblocksize; if (!linux_fragsize) { linux_fragsize = OSS_DEFFRAGSIZE; @@ -256,7 +261,8 @@ whynot: #define O_AUDIOFLAG O_NDELAY int oss_open_audio(int nindev, int *indev, int nchin, int *chin, - int noutdev, int *outdev, int nchout, int *chout, int rate) + int noutdev, int *outdev, int nchout, int *chout, int rate, + int blocksize) { int capabilities = 0; int inchannels = 0, outchannels = 0; @@ -358,7 +364,7 @@ int oss_open_audio(int nindev, int *indev, int nchin, int *chin, { linux_dacs[linux_noutdevs].d_nchannels = gotchans; linux_dacs[linux_noutdevs].d_fd = fd; - oss_configure(linux_dacs+linux_noutdevs, rate, 1, 0); + oss_configure(linux_dacs+linux_noutdevs, rate, 1, 0, blocksize); linux_noutdevs++; outchannels += gotchans; @@ -433,7 +439,8 @@ int oss_open_audio(int nindev, int *indev, int nchin, int *chin, linux_adcs[linux_nindevs].d_nchannels = gotchans; - oss_configure(linux_adcs+linux_nindevs, rate, 0, alreadyopened); + oss_configure(linux_adcs+linux_nindevs, rate, 0, alreadyopened, + blocksize); inchannels += gotchans; linux_nindevs++; diff --git a/src/s_file.c b/src/s_file.c index 7fe081a50..7d4ddb6fa 100644 --- a/src/s_file.c +++ b/src/s_file.c @@ -322,7 +322,8 @@ void sys_loadpreferences( void) int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV]; int nmidiindev, midiindev[MAXMIDIINDEV]; int nmidioutdev, midioutdev[MAXMIDIOUTDEV]; - int i, rate = 0, advance = 0, callback = 0, api, nolib, maxi; + int i, rate = 0, advance = -1, callback = 0, blocksize = 0, + api, nolib, maxi; char prefbuf[MAXPDSTRING], keybuf[80]; sys_initloadpreferences(); @@ -373,9 +374,11 @@ void sys_loadpreferences( void) sscanf(prefbuf, "%d", &advance); if (sys_getpreference("callback", prefbuf, MAXPDSTRING)) sscanf(prefbuf, "%d", &callback); + if (sys_getpreference("blocksize", prefbuf, MAXPDSTRING)) + sscanf(prefbuf, "%d", &blocksize); sys_set_audio_settings(naudioindev, audioindev, naudioindev, chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate, advance, - callback); + callback, blocksize); /* load MIDI preferences */ /* JMZ/MB: brackets for initializing */ @@ -460,7 +463,7 @@ void glob_savepreferences(t_pd *dummy) { int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV]; int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV]; - int i, rate, advance, callback; + int i, rate, advance, callback, blocksize; char buf1[MAXPDSTRING], buf2[MAXPDSTRING]; int nmidiindev, midiindev[MAXMIDIINDEV]; int nmidioutdev, midioutdev[MAXMIDIOUTDEV]; @@ -473,7 +476,8 @@ void glob_savepreferences(t_pd *dummy) sys_putpreference("audioapi", buf1); sys_get_audio_params(&naudioindev, audioindev, chindev, - &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback); + &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback, + &blocksize); sys_putpreference("noaudioin", (naudioindev <= 0 ? "True" : "False")); for (i = 0; i < naudioindev; i++) @@ -499,6 +503,9 @@ void glob_savepreferences(t_pd *dummy) sprintf(buf1, "%d", callback); sys_putpreference("callback", buf1); + sprintf(buf1, "%d", blocksize); + sys_putpreference("blocksize", buf1); + /* MIDI settings */ sys_get_midi_params(&nmidiindev, midiindev, &nmidioutdev, midioutdev); sys_putpreference("nomidiin", (nmidiindev <= 0 ? "True" : "False")); diff --git a/src/s_main.c b/src/s_main.c index 7f4079e49..af13585c0 100644 --- a/src/s_main.c +++ b/src/s_main.c @@ -73,6 +73,7 @@ char sys_fontweight[] = "normal"; /* currently only used for iemguis */ static int sys_main_srate; static int sys_main_advance; static int sys_main_callback; +static int sys_main_blocksize; static int sys_listplease; int sys_externalschedlib; @@ -582,7 +583,7 @@ int sys_argparse(int argc, char **argv) } else if (!strcmp(*argv, "-blocksize")) { - sys_setblocksize(atoi(argv[1])); + sys_main_blocksize = atoi(argv[1]); argc -= 2; argv += 2; } else if (!strcmp(*argv, "-sleepgrain") && (argc > 1)) @@ -928,7 +929,7 @@ static void sys_afterargparse(void) int i; int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV]; int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV]; - int nchindev, nchoutdev, rate, advance, callback; + int nchindev, nchoutdev, rate, advance, callback, blocksize; int nmidiindev = 0, midiindev[MAXMIDIINDEV]; int nmidioutdev = 0, midioutdev[MAXMIDIOUTDEV]; /* add "extra" library to path */ @@ -964,7 +965,8 @@ static void sys_afterargparse(void) else are the default. Overwrite them with any results of argument parsing, and store them again. */ sys_get_audio_params(&naudioindev, audioindev, chindev, - &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback); + &naudiooutdev, audiooutdev, choutdev, &rate, &advance, + &callback, &blocksize); if (sys_nchin >= 0) { nchindev = sys_nchin; @@ -1012,9 +1014,11 @@ static void sys_afterargparse(void) rate = sys_main_srate; if (sys_main_callback) callback = sys_main_callback; + if (sys_main_blocksize) + blocksize = sys_main_blocksize; sys_set_audio_settings(naudioindev, audioindev, nchindev, chindev, naudiooutdev, audiooutdev, nchoutdev, choutdev, rate, advance, - callback); + callback, blocksize); sys_open_midi(nmidiindev, midiindev, nmidioutdev, midioutdev, 0); } diff --git a/src/s_stuff.h b/src/s_stuff.h index ceec125ff..18e602abc 100644 --- a/src/s_stuff.h +++ b/src/s_stuff.h @@ -78,12 +78,17 @@ extern int sys_blocksize; /* audio I/O block size in sample frames */ extern t_float sys_dacsr; extern int sys_schedadvance; extern int sys_sleepgrain; -void sys_set_audio_settings(int naudioindev, int *audioindev, +EXTERN void sys_set_audio_settings(int naudioindev, int *audioindev, int nchindev, int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev, int *choutdev, - int srate, int advance, int callback); -void sys_reopen_audio( void); -void sys_close_audio(void); + int srate, int advance, int callback, int blocksize); +/* the same as above, but reopens the audio subsystem if needed */ +EXTERN void sys_set_audio_settings_reopen(int naudioindev, int *audioindev, + int nchindev, int *chindev, + int naudiooutdev, int *audiooutdev, int nchoutdev, int *choutdev, + int srate, int advance, int callback, int blocksize); +EXTERN void sys_reopen_audio( void); +EXTERN void sys_close_audio(void); int sys_send_dacs(void); @@ -236,7 +241,7 @@ void pa_getdevs(char *indevlist, int *nindevs, int oss_open_audio(int naudioindev, int *audioindev, int nchindev, int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev, - int *choutdev, int rate); + int *choutdev, int rate, int blocksize); void oss_close_audio(void); int oss_send_dacs(void); void oss_reportidle(void); @@ -246,7 +251,7 @@ void oss_getdevs(char *indevlist, int *nindevs, int alsa_open_audio(int naudioindev, int *audioindev, int nchindev, int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev, - int *choutdev, int rate); + int *choutdev, int rate, int blocksize); void alsa_close_audio(void); int alsa_send_dacs(void); void alsa_reportidle(void); @@ -254,7 +259,8 @@ void alsa_getdevs(char *indevlist, int *nindevs, char *outdevlist, int *noutdevs, int *canmulti, int maxndev, int devdescsize); -int jack_open_audio(int wantinchans, int wantoutchans, int srate); +int jack_open_audio(int wantinchans, int wantoutchans, int srate, + t_audiocallback callback); void jack_close_audio(void); int jack_send_dacs(void); void jack_reportidle(void); @@ -265,7 +271,7 @@ void jack_listdevs(void); int mmio_open_audio(int naudioindev, int *audioindev, int nchindev, int *chindev, int naudiooutdev, int *audiooutdev, - int nchoutdev, int *choutdev, int rate); + int nchoutdev, int *choutdev, int rate, int blocksize); void mmio_close_audio( void); void mmio_reportidle(void); int mmio_send_dacs(void); @@ -273,6 +279,33 @@ void mmio_getdevs(char *indevlist, int *nindevs, char *outdevlist, int *noutdevs, int *canmulti, int maxndev, int devdescsize); +int audiounit_open_audio(int naudioindev, int *audioindev, int nchindev, + int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev, + int *choutdev, int rate); +void audiounit_close_audio(void); +int audiounit_send_dacs(void); +void audiounit_listdevs(void); +void audiounit_getdevs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int *canmulti, + int maxndev, int devdescsize); + +int esd_open_audio(int naudioindev, int *audioindev, int nchindev, + int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev, + int *choutdev, int rate); +void esd_close_audio(void); +int esd_send_dacs(void); +void esd_listdevs(void); +void esd_getdevs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int *canmulti, + int maxndev, int devdescsize); + +int dummy_open_audio(int nin, int nout, int sr); +int dummy_close_audio( void); +int dummy_send_dacs( void); +void dummy_getdevs(char *indevlist, int *nindevs, char *outdevlist, + int *noutdevs, int *canmulti, int maxndev, int devdescsize); +void dummy_listdevs( void); + void sys_listmididevs(void); void sys_set_midi_api(int whichapi); void sys_set_audio_api(int whichapi); @@ -284,14 +317,14 @@ void sys_set_audio_state(int onoff); void oss_set32bit( void); void linux_alsa_devname(char *devname); -void sys_get_audio_params( +EXTERN void sys_get_audio_params( int *pnaudioindev, int *paudioindev, int *chindev, int *pnaudiooutdev, int *paudiooutdev, int *choutdev, - int *prate, int *padvance, int *callback); + int *prate, int *padvance, int *callback, int *blocksize); void sys_save_audio_params( int naudioindev, int *audioindev, int *chindev, int naudiooutdev, int *audiooutdev, int *choutdev, - int rate, int advance, int callback); + int rate, int advance, int callback, int blocksize); /* s_file.c */ -- GitLab