diff options
Diffstat (limited to 'pd/src/s_audio.c')
-rw-r--r-- | pd/src/s_audio.c | 196 |
1 files changed, 160 insertions, 36 deletions
diff --git a/pd/src/s_audio.c b/pd/src/s_audio.c index 2f274fc6..bff3c3ab 100644 --- a/pd/src/s_audio.c +++ b/pd/src/s_audio.c @@ -9,17 +9,18 @@ #include "m_pd.h" #include "s_stuff.h" #include <stdio.h> -#ifdef HAVE_UNISTD_H +#ifdef _WIN32 +#include <time.h> +#else #include <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) @@ -37,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 */ @@ -64,8 +64,9 @@ 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; @@ -82,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; @@ -96,12 +97,13 @@ void sys_get_audio_params( *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; @@ -115,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 @@ -156,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); @@ -180,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; @@ -195,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 @@ -324,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) @@ -360,12 +366,29 @@ void sys_close_audio(void) 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; sys_audioapiopened = -1; 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 */ @@ -373,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) { @@ -385,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, @@ -398,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 @@ -413,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) @@ -493,6 +540,21 @@ int sys_send_dacs(void) 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); } @@ -549,6 +611,7 @@ static void audio_getdevs(char *indevlist, int *nindevs, { jack_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti, maxndev, devdescsize); + *cancallback = 1; } else #endif @@ -576,6 +639,28 @@ static void audio_getdevs(char *indevlist, int *nindevs, } 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. */ int i; @@ -635,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; @@ -654,7 +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); + &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback, + &blocksize); /* post("naudioindev %d naudiooutdev %d longform %f", naudioindev, naudiooutdev, flongform); */ @@ -681,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); } @@ -706,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++) { @@ -738,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(); } @@ -777,19 +877,34 @@ void sys_listdevs(void ) 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) @@ -872,6 +987,15 @@ void sys_get_audio_apis(char *buf) #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. */ if (n < 2) |