diff --git a/pd/src/dialog_audio.tcl b/pd/src/dialog_audio.tcl
index b88b84681a844e8c97b18fb0f28af0c5f44a65ff..94f0ad5fce800d42aec7d3a7eda58bed3cae24fd 100644
--- a/pd/src/dialog_audio.tcl
+++ b/pd/src/dialog_audio.tcl
@@ -205,7 +205,7 @@ proc ::dialog_audio::pdtk_audio_dialog {id \
     set audio_callback $callback
     set audio_blocksize $blocksize
     set audio_longform $longform
-
+    
     set mytoplevel .prefs.nb.audio
     set apifr $mytoplevel.api
     if {![winfo exists $apifr]} {
diff --git a/pd/src/pd.tk b/pd/src/pd.tk
index 108326ad0c2f8792a44c0fa242f08fa3eeb9e7ec..b1b4bcb817494fd96788b9992acdb0bbfc0d828a 100644
--- a/pd/src/pd.tk
+++ b/pd/src/pd.tk
@@ -8493,8 +8493,7 @@ proc pdtk_audio_dialog {mytoplevel indev1 indev2 indev3 indev4 \
         inchan1 inchan2 inchan3 inchan4 \
         outdev1 outdev2 outdev3 outdev4 \
         outchan1 outchan2 outchan3 outchan4 sr advance multi callback \
-        longform} {
-    set blocksize 64
+        longform blocksize} {
     ::dialog_audio::pdtk_audio_dialog \
         $mytoplevel $indev1 $indev2 $indev3 $indev4 \
         $inchan1 $inchan2 $inchan3 $inchan4 \
diff --git a/pd/src/s_audio.c b/pd/src/s_audio.c
index 33f8ef04fccb9460cf6118e59de155ec24fefd30..1d658800025f4d158c6c16ad1423cc4cc128ec54 100644
--- a/pd/src/s_audio.c
+++ b/pd/src/s_audio.c
@@ -90,6 +90,11 @@ int audio_isopen(void)
             || (audio_naudiooutdev > 0 && audio_audiochoutdev[0] > 0)));
 }
 
+int sys_audio_get_blocksize(void)
+{
+    return (audio_blocksize);
+}
+
 void sys_get_audio_params(
     int *pnaudioindev, int *paudioindev, int *chindev,
     int *pnaudiooutdev, int *paudiooutdev, int *choutdev,
@@ -146,7 +151,6 @@ void sys_save_audio_params(
     audio_advance = advance;
     audio_callback = callback;
     audio_blocksize = blocksize;
-    fprintf(stderr,"blocksize=%d\n", blocksize);
 }
 
     /* init routines for any API which needs to set stuff up before
@@ -421,7 +425,7 @@ 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);
         outcome = pa_open_audio((naudioindev > 0 ? chindev[0] : 0),
         (naudiooutdev > 0 ? choutdev[0] : 0), rate, sys_soundin,
             sys_soundout, blksize, sys_advance_samples/blksize, 
@@ -441,7 +445,8 @@ void sys_reopen_audio( void)
 #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
@@ -456,7 +461,25 @@ void sys_reopen_audio( void)
 #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)
@@ -735,7 +758,7 @@ 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,
diff --git a/pd/src/s_audio_mmio.c b/pd/src/s_audio_mmio.c
index fd17a1ce03d0ea39d6b9d559ea174c51cb500c94..6bb1f0877b304083aaf60f6d085463b7229b1b95 100644
--- a/pd/src/s_audio_mmio.c
+++ b/pd/src/s_audio_mmio.c
@@ -11,7 +11,7 @@
 
 #include <windows.h>
 
-#include <MMSYSTEM.H>
+#include <mmsystem.h>
 
 /* ------------------------- audio -------------------------- */
 
@@ -696,11 +696,11 @@ idle:
 
 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)
 {
     int nbuf;
 
-    nt_realdacblksize = (sys_blocksize ? sys_blocksize : DEFREALDACBLKSIZE);
+    nt_realdacblksize = (blocksize ? blocksize : DEFREALDACBLKSIZE);
     nbuf = sys_advance_samples/nt_realdacblksize;
     if (nbuf >= MAXBUFFER)
     {
diff --git a/pd/src/s_audio_oss.c b/pd/src/s_audio_oss.c
index 8c2da61d6681783e4ec134a28e3b553fc9a0888d..f7f7a1934ab80ec9ee8a23a883c6817b3357411f 100644
--- a/pd/src/s_audio_oss.c
+++ b/pd/src/s_audio_oss.c
@@ -5,7 +5,14 @@
 
 /* this file inputs and outputs audio using the OSS API available on linux. */
 
-#include <linux/soundcard.h>
+#include <sys/soundcard.h>
+
+#ifndef SNDCTL_DSP_GETISPACE
+#define SNDCTL_DSP_GETISPACE SOUND_PCM_GETISPACE
+#endif
+#ifndef SNDCTL_DSP_GETOSPACE
+#define SNDCTL_DSP_GETOSPACE SOUND_PCM_GETOSPACE
+#endif
 
 #include "m_pd.h"
 #include "s_stuff.h"
@@ -41,8 +48,11 @@ typedef int32_t t_oss_int32;
 #define OSS_XFERSIZE(chans, width) (DEFDACBLKSIZE * (chans) * (width))
 
 /* GLOBALS */
+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
@@ -67,6 +77,7 @@ t_sample *sys_soundin;
 
     /* OSS-specific private variables */
 static int oss_blockmode = 1;   /* flag to use "blockmode"  */
+static char ossdsp[] = "/dev/dsp%d"; 
 
     /* don't assume we can turn all 31 bits when doing float-to-fix; 
     otherwise some audio drivers (e.g. Midiman/ALSA) wrap around. */
@@ -117,10 +128,12 @@ 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, fd = dev->d_fd, wantformat;
+    int orig, param, nblk, fd = dev->d_fd, wantformat;
     int nchannels = dev->d_nchannels;
+    int advwas = sys_schedadvance;
 
     audio_buf_info ainfo;
 
@@ -148,7 +161,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;
@@ -192,7 +205,7 @@ void oss_configure(t_oss_dev *dev, int srate, int dac, int skipblocksize)
         out.  */
 
         int defect;
-        if (ioctl(fd, SOUND_PCM_GETOSPACE,&ainfo) < 0)
+        if (ioctl(fd, SNDCTL_DSP_GETOSPACE,&ainfo) < 0)
            fprintf(stderr,"OSS: ioctl on output device failed");
         dev->d_bufsize = ainfo.bytes;
 
@@ -234,7 +247,7 @@ static int oss_setchannels(int fd, int wantchannels, char *devname)
         }
     }
     param = wantchannels;
-//whynot:    
+whynot:    
     while (param > 1)
     {
         int save = param;
@@ -251,15 +264,19 @@ static int oss_setchannels(int fd, int wantchannels, char *devname)
 #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;
     char devname[20];
     int n, i, fd, flags;
     char buf[OSS_MAXSAMPLEWIDTH * DEFDACBLKSIZE * OSS_MAXCHPERDEV];
+    int num_devs = 0;
     int wantmore=0;
-  
+    int spread = 0;
+    audio_buf_info ainfo;
+
     linux_nindevs = linux_noutdevs = 0;
         /* mark devices unopened */
     for (i = 0; i < OSS_MAXDEV; i++)
@@ -350,7 +367,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;
@@ -425,7 +442,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++;
@@ -499,14 +517,14 @@ static void oss_calcspace(void)
     audio_buf_info ainfo;
     for (dev=0; dev < linux_noutdevs; dev++)
     {
-        if (ioctl(linux_dacs[dev].d_fd, SOUND_PCM_GETOSPACE, &ainfo) < 0)
+        if (ioctl(linux_dacs[dev].d_fd, SNDCTL_DSP_GETOSPACE, &ainfo) < 0)
            fprintf(stderr,"OSS: ioctl on output device %d failed",dev);
         linux_dacs[dev].d_space = ainfo.bytes;
     }
 
     for (dev = 0; dev < linux_nindevs; dev++)
     {
-        if (ioctl(linux_adcs[dev].d_fd, SOUND_PCM_GETISPACE,&ainfo) < 0)
+        if (ioctl(linux_adcs[dev].d_fd, SNDCTL_DSP_GETISPACE,&ainfo) < 0)
             fprintf(stderr, "OSS: ioctl on input device %d, fd %d failed",
                 dev, linux_adcs[dev].d_fd);
         linux_adcs[dev].d_space = ainfo.bytes;
@@ -533,7 +551,7 @@ in audio output and/or input. */
 
 static void oss_doresync( void)
 {
-    int dev, zeroed = 0;
+    int dev, zeroed = 0, wantsize;
     char buf[OSS_MAXSAMPLEWIDTH * DEFDACBLKSIZE * OSS_MAXCHPERDEV];
     audio_buf_info ainfo;
 
@@ -554,7 +572,7 @@ static void oss_doresync( void)
             linux_adcs_read(linux_adcs[dev].d_fd, buf, 
                 OSS_XFERSIZE(linux_adcs[dev].d_nchannels,
                     linux_adcs[dev].d_bytespersamp));
-            if (ioctl(linux_adcs[dev].d_fd, SOUND_PCM_GETISPACE, &ainfo) < 0)
+            if (ioctl(linux_adcs[dev].d_fd, SNDCTL_DSP_GETISPACE, &ainfo) < 0)
             {
                 fprintf(stderr, "OSS: ioctl on input device %d, fd %d failed",
                     dev, linux_adcs[dev].d_fd);
@@ -583,7 +601,7 @@ static void oss_doresync( void)
             linux_dacs_write(linux_dacs[dev].d_fd, buf,
                 OSS_XFERSIZE(linux_dacs[dev].d_nchannels,
                     linux_dacs[dev].d_bytespersamp));
-            if (ioctl(linux_dacs[dev].d_fd, SOUND_PCM_GETOSPACE, &ainfo) < 0)
+            if (ioctl(linux_dacs[dev].d_fd, SNDCTL_DSP_GETOSPACE, &ainfo) < 0)
             {
                 fprintf(stderr, "OSS: ioctl on output device %d, fd %d failed",
                     dev, linux_dacs[dev].d_fd);
@@ -612,9 +630,11 @@ static void oss_doresync( void)
 int oss_send_dacs(void)
 {
     t_sample *fp1, *fp2;
+    long fill;
     int i, j, dev, rtnval = SENDDACS_YES;
     char buf[OSS_MAXSAMPLEWIDTH * DEFDACBLKSIZE * OSS_MAXCHPERDEV];
     t_oss_int16 *sp;
+    t_oss_int32 *lp;
         /* the maximum number of samples we should have in the ADC buffer */
     int idle = 0;
     int thischan;
@@ -655,6 +675,7 @@ int oss_send_dacs(void)
         for (dev = 0;dev < linux_nindevs; dev++) 
             if (linux_adcs[dev].d_space == 0)
         {
+            audio_buf_info ainfo;
             sys_microsleep(2000);
             oss_calcspace();
             if (linux_adcs[dev].d_space != 0) continue;
diff --git a/pd/src/s_audio_pa.c b/pd/src/s_audio_pa.c
index de5fe711b46e8f836a33d710529507b5d6af810f..d87770a1154526edb1a2aff1ee393ebeaef8558c 100644
--- a/pd/src/s_audio_pa.c
+++ b/pd/src/s_audio_pa.c
@@ -4,63 +4,114 @@
 
 /* this file calls Ross Bencina's and Phil Burk's Portaudio package.  It's
     the main way in for Mac OS and, with Michael Casey's help, also into
-    ASIO in Windows. */
+    ASIO in Windows.
+    
+    Both blocking and non-blocking call styles are supported.  If non-blocking
+    is requested, either we call portaudio in non-blocking mode, or else we
+    call portaudio in callback mode and manage our own FIFO se we can offer
+    Pd "blocking" I/O calls.  To do the latter we define FAKEBLOCKING; this
+    works better in MAXOSX (gets 40 msec lower latency!) and might also in
+    Windows.  If FAKEBLOCKING is defined we can choose between two methods
+    for waiting on the (presumebly other-thread) I/O to complete, either
+    correct thread synchronization (by defining THREADSIGNAL) or just sleeping
+    and polling; the latter seems to work better so far.
+*/
 
+/* dolist...  
+    switch to usleep in s_inter.c
+*/
 
 #include "m_pd.h"
 #include "s_stuff.h"
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <portaudio.h>
-#include "s_audio_pablio.h"
-#ifdef MSW
-#include <malloc.h>
+
+#ifdef _MSC_VER
+#define snprintf sprintf_s
+#endif
+
+#ifndef _WIN32          /* for the "dup2" workaround -- do we still need it? */
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_ALLOCA_H        /* ifdef nonsense to find include for alloca() */
+# include <alloca.h>        /* linux, mac, mingw, cygwin */
+#elif defined _MSC_VER
+# include <malloc.h>        /* MSVC */
 #else
-#include <alloca.h>
+# include <stddef.h>        /* BSDs for example */
+#endif                      /* end alloca() ifdef nonsense */
+
+#if 1
+#define FAKEBLOCKING
 #endif
 
+#if defined (FAKEBLOCKING) && defined(_WIN32)
+#include <windows.h>    /* for Sleep() */
+#endif
+
+/* define this to enable thread signaling instead of polling */
+/* #define THREADSIGNAL */
+
     /* LATER try to figure out how to handle default devices in portaudio;
     the way s_audio.c handles them isn't going to work here. */
 
     /* public interface declared in m_imp.h */
 
     /* implementation */
-static PABLIO_Stream  *pa_stream;
+static PaStream *pa_stream;
 static int pa_inchans, pa_outchans;
 static float *pa_soundin, *pa_soundout;
 static t_audiocallback pa_callback;
 
-int pa_foo;
+static int pa_started;
+static int pa_nbuffers;
+static int pa_dio_error;
 
-#ifndef MSW
-#include <unistd.h>
-#endif
-static void pa_init(void)
+#ifdef FAKEBLOCKING
+#include "s_audio_paring.h"
+static PA_VOLATILE char *pa_outbuf;
+static PA_VOLATILE sys_ringbuf pa_outring;
+static PA_VOLATILE char *pa_inbuf;
+static PA_VOLATILE sys_ringbuf pa_inring;
+#ifdef THREADSIGNAL
+#include <pthread.h>
+pthread_mutex_t pa_mutex;
+pthread_cond_t pa_sem;
+#endif /* THREADSIGNAL */
+#endif  /* FAKEBLOCKING */
+
+static void pa_init(void)        /* Initialize PortAudio  */
 {
     static int initialized;
     if (!initialized)
     {
-#ifndef MSW
-        /* Initialize PortAudio  */
-        /* for some reason Pa_Initialize(0 closes file descriptor 1.
-        As a workaround, dup it to another number and dup2 it back
-        afterward. */
+#ifdef __APPLE__
+        /* for some reason, on the Mac Pa_Initialize() closes file descriptor
+        1 (standard output) As a workaround, dup it to another number and dup2
+        it back afterward. */
         int newfd = dup(1);
+        int another = open("/dev/null", 0);
+        dup2(another, 1);
         int err = Pa_Initialize();
+        close(1);
+        close(another);
         if (newfd >= 0)
         {
+            fflush(stdout);
             dup2(newfd, 1);
             close(newfd);
         }
 #else
         int err = Pa_Initialize();
 #endif
+
+
         if ( err != paNoError ) 
         {
-            fprintf( stderr,
-                "Error number %d occured initializing portaudio\n",
-                err); 
-            fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
+            post("Error opening audio: %s", err, Pa_GetErrorText(err));
             return;
         }
         initialized = 1;
@@ -68,120 +119,207 @@ static void pa_init(void)
 }
 
 static int pa_lowlevel_callback(const void *inputBuffer,
-    void *outputBuffer, unsigned long framesPerBuffer,
+    void *outputBuffer, unsigned long nframes,
     const PaStreamCallbackTimeInfo *outTime, PaStreamCallbackFlags myflags, 
     void *userData)
 {
     int i; 
-    unsigned int j;
+    unsigned int n, j;
     float *fbuf, *fp2, *fp3, *soundiop;
-    if (pa_foo)
-       fprintf(stderr, "pa_lowlevel_callback\n");
-    if (framesPerBuffer != DEFDACBLKSIZE)
+    if (nframes % DEFDACBLKSIZE)
     {
-        fprintf(stderr, "ignoring buffer size %d\n", (int)framesPerBuffer);
-        return 0;
+        post("warning: audio nframes %ld not a multiple of blocksize %d",
+            nframes, (int)DEFDACBLKSIZE);
+        nframes -= (nframes % DEFDACBLKSIZE);
     }
-        if (inputBuffer != NULL)
+    for (n = 0; n < nframes; n += DEFDACBLKSIZE)
     {
-        fbuf = (float *)inputBuffer;
-        soundiop = pa_soundin;
-        for (i = 0, fp2 = fbuf; i < pa_inchans; i++, fp2++)
-            for (j = 0, fp3 = fp2; j < framesPerBuffer; j++, fp3 += pa_inchans)
-                *soundiop++ = *fp3;
+        if (inputBuffer != NULL)
+        {
+            fbuf = ((float *)inputBuffer) + n*pa_inchans;
+            soundiop = pa_soundin;
+            for (i = 0, fp2 = fbuf; i < pa_inchans; i++, fp2++)
+                    for (j = 0, fp3 = fp2; j < DEFDACBLKSIZE;
+                        j++, fp3 += pa_inchans)
+                            *soundiop++ = *fp3;
+        }
+        else memset((void *)pa_soundin, 0,
+            DEFDACBLKSIZE * pa_inchans * sizeof(float));
+        memset((void *)pa_soundout, 0,
+            DEFDACBLKSIZE * pa_outchans * sizeof(float));
+        (*pa_callback)();
+        if (outputBuffer != NULL)
+        {
+            fbuf = ((float *)outputBuffer) + n*pa_outchans;
+            soundiop = pa_soundout;
+            for (i = 0, fp2 = fbuf; i < pa_outchans; i++, fp2++)
+                for (j = 0, fp3 = fp2; j < DEFDACBLKSIZE;
+                    j++, fp3 += pa_outchans)
+                        *fp3 = *soundiop++;
+        }
     }
-    else memset((void *)pa_soundin, 0,
-        framesPerBuffer * pa_inchans * sizeof(float));
-    memset((void *)pa_soundout, 0,
-        framesPerBuffer * pa_outchans * sizeof(float));
-    (*pa_callback)();
-    if (outputBuffer != NULL)
+    return 0;
+}
+
+#ifdef FAKEBLOCKING
+    /* callback for "non-callback" case in which we actualy open portaudio
+    in callback mode but fake "blocking mode". We communicate with the
+    main thread via FIFO.  First read the audio output FIFO (which
+    we sync on, not waiting for it but supplying zeros to the audio output if
+    there aren't enough samples in the FIFO when we are called), then write
+    to the audio input FIFO.  The main thread will wait for the input fifo.
+    We can either throw it a pthreads condition or just allow the main thread
+    to poll for us; so far polling seems to work better. */
+static int pa_fifo_callback(const void *inputBuffer,
+    void *outputBuffer, unsigned long nframes,
+    const PaStreamCallbackTimeInfo *outTime, PaStreamCallbackFlags myflags, 
+    void *userData)
+{
+    /* callback routine for non-callback client... throw samples into
+            and read them out of a FIFO */
+    int ch;
+    long fiforoom;
+    float *fbuf;
+
+#if CHECKFIFOS
+    if (pa_inchans * sys_ringbuf_getreadavailable(&pa_outring) !=   
+        pa_outchans * sys_ringbuf_getwriteavailable(&pa_inring))
+            post("warning: in and out rings unequal (%d, %d)",
+                sys_ringbuf_getreadavailable(&pa_outring),
+                 sys_ringbuf_getwriteavailable(&pa_inring));
+#endif
+    fiforoom = sys_ringbuf_getreadavailable(&pa_outring);
+    if ((unsigned)fiforoom >= nframes*pa_outchans*sizeof(float))
     {
-        fbuf = (float *)outputBuffer;
-        soundiop = pa_soundout;
-        for (i = 0, fp2 = fbuf; i < pa_outchans; i++, fp2++)
-            for (j = 0, fp3 = fp2; j < framesPerBuffer; j++, fp3 += pa_outchans)
-                *fp3 = *soundiop++;
+        if (outputBuffer)
+            sys_ringbuf_read(&pa_outring, outputBuffer,
+                nframes*pa_outchans*sizeof(float), pa_outbuf);
+        else if (pa_outchans)
+            post("audio error: no outputBuffer but output channels");
+        if (inputBuffer)
+            sys_ringbuf_write(&pa_inring, inputBuffer,
+                nframes*pa_inchans*sizeof(float), pa_inbuf);
+        else if (pa_inchans)
+            post("audio error: no inputBuffer but input channels");
+    }
+    else
+    {        /* PD could not keep up; generate zeros */
+        if (pa_started)
+            pa_dio_error = 1;
+        if (outputBuffer)
+        {
+            for (ch = 0; ch < pa_outchans; ch++)
+            {
+                unsigned long frame;
+                fbuf = ((float *)outputBuffer) + ch;
+                for (frame = 0; frame < nframes; frame++, fbuf += pa_outchans)
+                    *fbuf = 0;
+            }
+        }
     }
-    if (pa_foo)
-        fprintf(stderr, "done pa_lowlevel_callback\n"); 
+#ifdef THREADSIGNAL
+    pthread_mutex_lock(&pa_mutex);
+    pthread_cond_signal(&pa_sem);
+    pthread_mutex_unlock(&pa_mutex);
+#endif
     return 0;
 }
+#endif /* FAKEBLOCKING */
 
 PaError pa_open_callback(double sampleRate, int inchannels, int outchannels,
-    int framesperbuf, int nbuffers, int indeviceno, int outdeviceno)
+    int framesperbuf, int nbuffers, int indeviceno, int outdeviceno, PaStreamCallback *callbackfn)
 {
     long   bytesPerSample;
     PaError err;
-    PABLIO_Stream *pastream;
-    long   numFrames;
     PaStreamParameters instreamparams, outstreamparams;
+    PaStreamParameters*p_instreamparams=0, *p_outstreamparams=0;
 
-    if (indeviceno < 0) 
-    {
-        indeviceno = Pa_GetDefaultInputDevice();
-        fprintf(stderr, "using default input device number: %d\n", indeviceno);
-    }
-    if (outdeviceno < 0)
-    {
-        outdeviceno = Pa_GetDefaultOutputDevice();
-        fprintf(stderr, "using default output device number: %d\n", outdeviceno);
-    }
     /* fprintf(stderr, "nchan %d, flags %d, bufs %d, framesperbuf %d\n",
             nchannels, flags, nbuffers, framesperbuf); */
 
-    /* Allocate PABLIO_Stream structure for caller. */
-    pastream = (PABLIO_Stream *)malloc( sizeof(PABLIO_Stream));
-    if (pastream == NULL)
-        return (1);
-    memset(pastream, 0, sizeof(PABLIO_Stream));
-
-    /* Determine size of a sample. */
-    bytesPerSample = Pa_GetSampleSize(paFloat32);
-    if (bytesPerSample < 0)
-    {
-        err = (PaError) bytesPerSample;
-        goto error;
-    }
-    pastream->insamplesPerFrame = inchannels;
-    pastream->inbytesPerFrame = bytesPerSample * pastream->insamplesPerFrame;
-    pastream->outsamplesPerFrame = outchannels;
-    pastream->outbytesPerFrame = bytesPerSample * pastream->outsamplesPerFrame;
-
-    numFrames = nbuffers * framesperbuf;
-
     instreamparams.device = indeviceno;
     instreamparams.channelCount = inchannels;
     instreamparams.sampleFormat = paFloat32;
-    instreamparams.suggestedLatency = nbuffers*framesperbuf/sampleRate;
     instreamparams.hostApiSpecificStreamInfo = 0;
     
     outstreamparams.device = outdeviceno;
     outstreamparams.channelCount = outchannels;
     outstreamparams.sampleFormat = paFloat32;
-    outstreamparams.suggestedLatency = nbuffers*framesperbuf/sampleRate;
     outstreamparams.hostApiSpecificStreamInfo = 0;
 
+#ifdef FAKEBLOCKING
+    instreamparams.suggestedLatency = outstreamparams.suggestedLatency = 0;
+#else
+    instreamparams.suggestedLatency = outstreamparams.suggestedLatency =
+        nbuffers*framesperbuf/sampleRate;
+#endif /* FAKEBLOCKING */
+
+    if( inchannels>0 && indeviceno >= 0)
+        p_instreamparams=&instreamparams;
+    if( outchannels>0 && outdeviceno >= 0)
+        p_outstreamparams=&outstreamparams;
+
+    err=Pa_IsFormatSupported(p_instreamparams, p_outstreamparams, sampleRate);
+
+    if (paFormatIsSupported != err)
+    {
+        /* check whether we have to change the numbers of channel and/or samplerate */
+        const PaDeviceInfo* info = 0;
+        double inRate=0, outRate=0;
+
+        if (inchannels>0)
+        {
+            if (NULL != (info = Pa_GetDeviceInfo( instreamparams.device )))
+            {
+              inRate=info->defaultSampleRate;
+
+              if(info->maxInputChannels<inchannels)
+                instreamparams.channelCount=info->maxInputChannels;
+            }
+        }
+
+        if (outchannels>0)
+        {
+            if (NULL != (info = Pa_GetDeviceInfo( outstreamparams.device )))
+            {
+              outRate=info->defaultSampleRate;
+
+              if(info->maxOutputChannels<outchannels)
+                outstreamparams.channelCount=info->maxOutputChannels;
+            }
+        }
+
+        if (err == paInvalidSampleRate)
+        {
+            sampleRate=outRate;
+        }
+
+        err=Pa_IsFormatSupported(p_instreamparams, p_outstreamparams,
+            sampleRate);
+        if (paFormatIsSupported != err)
+        goto error;
+    }
     err = Pa_OpenStream(
-              &pastream->stream,
-              (inchannels ? &instreamparams : 0),
-              (outchannels ? &outstreamparams : 0),
+              &pa_stream,
+              p_instreamparams,
+              p_outstreamparams,
               sampleRate,
-              DEFDACBLKSIZE,
+              framesperbuf,
               paNoFlag,      /* portaudio will clip for us */
-              pa_lowlevel_callback,
-              pastream);
+              callbackfn,
+              0);
     if (err != paNoError)
         goto error;
 
-    err = Pa_StartStream(pastream->stream);
+    err = Pa_StartStream(pa_stream);
     if (err != paNoError)
     {
-        fprintf(stderr, "Pa_StartStream failed; closing audio stream...\n");
-        CloseAudioStream( pastream );
+        post("error opening failed; closing audio stream: %s",
+            Pa_GetErrorText(err));
+        pa_close_audio();
         goto error;
     }
-    pa_stream = pastream;
+    sys_dacsr=sampleRate;
     return paNoError;
 error:
     pa_stream = NULL;
@@ -193,13 +331,16 @@ int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin,
     int indeviceno, int outdeviceno, t_audiocallback callbackfn)
 {
     PaError err;
-    int j, devno, pa_indev = 0, pa_outdev = 0;
+    int j, devno, pa_indev = -1, pa_outdev = -1;
     
     pa_callback = callbackfn;
     /* fprintf(stderr, "open callback %d\n", (callbackfn != 0)); */
     pa_init();
     /* post("in %d out %d rate %d device %d", inchans, outchans, rate, deviceno); */
     
+    if (pa_stream)
+        pa_close_audio();
+
     if (inchans > 0)
     {
         for (j = 0, devno = 0; j < Pa_GetDeviceCount(); j++)
@@ -209,6 +350,9 @@ int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin,
             {
                 if (devno == indeviceno)
                 {
+                    if (inchans > info->maxInputChannels)
+                      inchans = info->maxInputChannels;
+
                     pa_indev = j;
                     break;
                 }
@@ -226,6 +370,9 @@ int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin,
             {
                 if (devno == outdeviceno)
                 {
+                    if (outchans > info->maxOutputChannels)
+                      outchans = info->maxOutputChannels;
+
                     pa_outdev = j;
                     break;
                 }
@@ -234,36 +381,68 @@ int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin,
         }
     }   
 
+    if (inchans > 0 && pa_indev == -1)
+        inchans = 0;
+    if (outchans > 0 && pa_outdev == -1)
+        outchans = 0;
+    
     if (sys_verbose)
     {
         post("input device %d, channels %d", pa_indev, inchans);
         post("output device %d, channels %d", pa_outdev, outchans);
         post("framesperbuf %d, nbufs %d", framesperbuf, nbuffers);
+        post("rate %d", rate);
     }
-    pa_inchans = inchans;
-    pa_outchans = outchans;
+    pa_inchans = sys_inchannels = inchans;
+    pa_outchans = sys_outchannels = outchans;
     pa_soundin = soundin;
     pa_soundout = soundout;
+
+#ifdef FAKEBLOCKING
+    if (pa_inbuf)
+        free((char *)pa_inbuf), pa_inbuf = 0;
+    if (pa_outbuf)
+        free((char *)pa_outbuf), pa_outbuf = 0;
+#endif
+
     if (! inchans && !outchans)
-        return(0);
+        return (0);
+    
     if (callbackfn)
     {
         pa_callback = callbackfn;
         err = pa_open_callback(rate, inchans, outchans,
-            framesperbuf, nbuffers, pa_indev, pa_outdev);
+            framesperbuf, nbuffers, pa_indev, pa_outdev, pa_lowlevel_callback);
     }
     else
     {
-        err = OpenAudioStream( &pa_stream, rate, paFloat32,
-            inchans, outchans, framesperbuf, nbuffers,
-                pa_indev, pa_outdev);
+#ifdef FAKEBLOCKING
+        if (pa_inchans)
+        {
+            pa_inbuf = malloc(nbuffers*framesperbuf*pa_inchans*sizeof(float));
+            sys_ringbuf_init(&pa_inring,
+                nbuffers*framesperbuf*pa_inchans*sizeof(float), pa_inbuf,
+                    nbuffers*framesperbuf*pa_inchans*sizeof(float));
+        }
+        if (pa_outchans)
+        {
+            pa_outbuf = malloc(nbuffers*framesperbuf*pa_outchans*sizeof(float));
+            sys_ringbuf_init(&pa_outring,
+                nbuffers*framesperbuf*pa_outchans*sizeof(float), pa_outbuf, 0);
+        }
+        err = pa_open_callback(rate, inchans, outchans,
+            framesperbuf, nbuffers, pa_indev, pa_outdev, pa_fifo_callback);
+#else
+        err = pa_open_callback(rate, inchans, outchans,
+            framesperbuf, nbuffers, pa_indev, pa_outdev, 0);
+#endif
     }
+    pa_started = 0;
+    pa_nbuffers = nbuffers;
     if ( err != paNoError ) 
     {
-        fprintf(stderr, "Error number %d opening portaudio stream\n",
-            err); 
-        fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
-        Pa_Terminate();
+        post("Error opening audio: %s", Pa_GetErrorText(err));
+        /* Pa_Terminate(); */
         return (1);
     }
     else if (sys_verbose)
@@ -273,132 +452,142 @@ int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin,
 
 void pa_close_audio( void)
 {
-    /* fprintf(stderr, "close\n"); */
-    if (pa_inchans || pa_outchans)
-        CloseAudioStream( pa_stream );
-    pa_inchans = pa_outchans = 0;
+    if (pa_stream)
+    {
+        Pa_AbortStream(pa_stream);
+        Pa_CloseStream(pa_stream);
+    }
+    pa_stream = 0;
+#ifdef FAKEBLOCKING
+    if (pa_inbuf)
+        free((char *)pa_inbuf), pa_inbuf = 0;
+    if (pa_outbuf)
+        free((char *)pa_outbuf), pa_outbuf = 0;
+#endif
 }
 
 int pa_send_dacs(void)
 {
-    unsigned int framesize = (sizeof(float) * DEFDACBLKSIZE) *
-        (pa_inchans > pa_outchans ? pa_inchans:pa_outchans);
-    float *samples, *fp1, *fp2;
-    int i, j;
+    t_sample *fp;
+    float *fp2, *fp3;
+    float *conversionbuf;
+    int j, k;
+    int rtnval =  SENDDACS_YES;
+#ifndef FAKEBLOCKING
     double timebefore;
-    
-    
-    samples = alloca(framesize);
-    
-    timebefore = sys_getrealtime();
-    if ((pa_inchans && GetAudioStreamReadable(pa_stream) < DEFDACBLKSIZE) ||
-        (pa_outchans && GetAudioStreamWriteable(pa_stream) < DEFDACBLKSIZE))
+#endif /* FAKEBLOCKING */
+    if (!sys_inchannels && !sys_outchannels || !pa_stream)
+        return (SENDDACS_NO); 
+    conversionbuf = (float *)alloca((sys_inchannels > sys_outchannels?
+        sys_inchannels:sys_outchannels) * DEFDACBLKSIZE * sizeof(float));
+
+#ifdef FAKEBLOCKING
+    if (!sys_inchannels)    /* if no input channels sync on output */
     {
-        if (pa_inchans && pa_outchans)
+#ifdef THREADSIGNAL
+        pthread_mutex_lock(&pa_mutex);
+#endif
+        while (sys_ringbuf_getwriteavailable(&pa_outring) <
+            (long)(sys_outchannels * DEFDACBLKSIZE * sizeof(float)))
         {
-            int synced = 0;
-            while (GetAudioStreamWriteable(pa_stream) > 2*DEFDACBLKSIZE)
-            {
-                for (j = 0; j < pa_outchans; j++)
-                    for (i = 0, fp2 = samples + j; i < DEFDACBLKSIZE; i++,
-                        fp2 += pa_outchans)
-                {
-                    *fp2 = 0;
-                }
-                synced = 1;
-                WriteAudioStream(pa_stream, samples, DEFDACBLKSIZE);
-            }
-            while (GetAudioStreamReadable(pa_stream) > 2*DEFDACBLKSIZE)
-            {
-                synced = 1;
-                ReadAudioStream(pa_stream, samples, DEFDACBLKSIZE);
-            }
-            /* if (synced)
-                post("sync"); */
+            rtnval = SENDDACS_SLEPT;
+#ifdef THREADSIGNAL
+            pthread_cond_wait(&pa_sem, &pa_mutex);
+#else
+#ifdef _WIN32
+            Sleep(1);
+#else
+            usleep(1000);
+#endif /* _WIN32 */
+#endif /* THREADSIGNAL */
         }
-        return (SENDDACS_NO);
+#ifdef THREADSIGNAL
+        pthread_mutex_unlock(&pa_mutex);
+#endif
     }
-    if (pa_inchans)
+        /* write output */
+    if (sys_outchannels)
     {
-        ReadAudioStream(pa_stream, samples, DEFDACBLKSIZE);
-        for (j = 0, fp1 = pa_soundin; j < pa_inchans; j++, fp1 += DEFDACBLKSIZE)
-            for (i = 0, fp2 = samples + j; i < DEFDACBLKSIZE; i++,
-                fp2 += pa_inchans)
-        {
-            fp1[i] = *fp2;
-        }
+        for (j = 0, fp = sys_soundout, fp2 = conversionbuf;
+            j < sys_outchannels; j++, fp2++)
+                for (k = 0, fp3 = fp2; k < DEFDACBLKSIZE;
+                    k++, fp++, fp3 += sys_outchannels)
+                        *fp3 = *fp;
+        sys_ringbuf_write(&pa_outring, conversionbuf,
+            sys_outchannels*(DEFDACBLKSIZE*sizeof(float)), pa_outbuf);
     }
-#if 0 
+    if (sys_inchannels)    /* if there is input sync on it */
+    {
+#ifdef THREADSIGNAL
+        pthread_mutex_lock(&pa_mutex);
+#endif
+        while (sys_ringbuf_getreadavailable(&pa_inring) <
+            (long)(sys_inchannels * DEFDACBLKSIZE * sizeof(float)))
         {
-                static int nread;
-                if (nread == 0)
-                {
-                        post("it's %f %f %f %f",
-                        pa_soundin[0], pa_soundin[1], pa_soundin[2],                                    pa_soundin[3]);
-                        nread = 1000;
-                }
-                nread--;
+            rtnval = SENDDACS_SLEPT;
+#ifdef THREADSIGNAL
+            pthread_cond_wait(&pa_sem, &pa_mutex);
+#else
+#ifdef _WIN32
+            Sleep(1);
+#else
+            usleep(1000);
+#endif /* _WIN32 */
+#endif /* THREADSIGNAL */
         }
+#ifdef THREADSIGNAL
+        pthread_mutex_unlock(&pa_mutex);
 #endif
-    if (pa_outchans)
+    }
+    if (sys_inchannels)
     {
-        for (j = 0, fp1 = pa_soundout; j < pa_outchans; j++,
-            fp1 += DEFDACBLKSIZE)
-                for (i = 0, fp2 = samples + j; i < DEFDACBLKSIZE; i++,
-                    fp2 += pa_outchans)
-        {
-            *fp2 = fp1[i];
-            fp1[i] = 0;
-        }
-        WriteAudioStream(pa_stream, samples, DEFDACBLKSIZE);
+        sys_ringbuf_read(&pa_inring, conversionbuf,
+            sys_inchannels*(DEFDACBLKSIZE*sizeof(float)), pa_inbuf);
+        for (j = 0, fp = sys_soundin, fp2 = conversionbuf;
+            j < sys_inchannels; j++, fp2++)
+                for (k = 0, fp3 = fp2; k < DEFDACBLKSIZE;
+                    k++, fp++, fp3 += sys_inchannels)
+                        *fp = *fp3;
     }
 
-    if (sys_getrealtime() > timebefore + 0.002)
+#else /* FAKEBLOCKING */
+    timebefore = sys_getrealtime();
+        /* write output */
+    if (sys_outchannels)
     {
-        /* post("slept"); */
-        return (SENDDACS_SLEPT);
+        if (!pa_started)
+        {
+            memset(conversionbuf, 0,
+                sys_outchannels * DEFDACBLKSIZE * sizeof(float));
+            for (j = 0; j < pa_nbuffers-1; j++)
+                Pa_WriteStream(pa_stream, conversionbuf, DEFDACBLKSIZE);
+        }
+        for (j = 0, fp = sys_soundout, fp2 = conversionbuf;
+            j < sys_outchannels; j++, fp2++)
+                for (k = 0, fp3 = fp2; k < DEFDACBLKSIZE;
+                    k++, fp++, fp3 += sys_outchannels)
+                        *fp3 = *fp;
+        Pa_WriteStream(pa_stream, conversionbuf, DEFDACBLKSIZE);
     }
-    else return (SENDDACS_YES);
-}
-
 
-void pa_listdevs(void)     /* lifted from pa_devs.c in portaudio */
-{
-    int      i,j;
-    int      numDevices;
-    const    PaDeviceInfo *pdi;
-    PaError  err;
-    pa_init();
-    numDevices = Pa_GetDeviceCount();
-    if( numDevices < 0 )
+    if (sys_inchannels)
     {
-        fprintf(stderr, "ERROR: Pa_GetDeviceCount returned %d\n", numDevices );
-        err = numDevices;
-        goto error;
+        Pa_ReadStream(pa_stream, conversionbuf, DEFDACBLKSIZE);
+        for (j = 0, fp = sys_soundin, fp2 = conversionbuf;
+            j < sys_inchannels; j++, fp2++)
+                for (k = 0, fp3 = fp2; k < DEFDACBLKSIZE;
+                    k++, fp++, fp3 += sys_inchannels)
+                        *fp = *fp3;
     }
-    fprintf(stderr, "Audio Devices:\n");
-    for( i=0; i<numDevices; i++ )
+    if (sys_getrealtime() - timebefore > 0.002)
     {
-        pdi = Pa_GetDeviceInfo( i );
-        fprintf(stderr, "device %d:", i+1 );
-        fprintf(stderr, " %s;", pdi->name );
-        fprintf(stderr, "%d inputs, ", pdi->maxInputChannels  );
-        fprintf(stderr, "%d outputs", pdi->maxOutputChannels  );
-        if ( i == Pa_GetDefaultInputDevice() )
-            fprintf(stderr, " (Default Input)");
-        if ( i == Pa_GetDefaultOutputDevice() )
-            fprintf(stderr, " (Default Output)");
-        fprintf(stderr, "\n");
+        rtnval = SENDDACS_SLEPT;
     }
+#endif /* FAKEBLOCKING */
+    pa_started = 1;
 
-    fprintf(stderr, "\n");
-    return;
-
-error:
-    fprintf( stderr, "An error occured while using the portaudio stream\n" ); 
-    fprintf( stderr, "Error number: %d\n", err );
-    fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
-
+    memset(sys_soundout, 0, DEFDACBLKSIZE*sizeof(t_sample)*sys_outchannels);
+    return (rtnval);
 }
 
     /* scanning for devices */
@@ -416,16 +605,33 @@ void pa_getdevs(char *indevlist, int *nindevs,
         const PaDeviceInfo *pdi = Pa_GetDeviceInfo(i);
         if (pdi->maxInputChannels > 0 && nin < maxndev)
         {
-            sprintf(indevlist + nin * devdescsize, "(%d)%s",
-                pdi->hostApi,pdi->name);
-            /* strcpy(indevlist + nin * devdescsize, pdi->name); */
+                /* LATER figure out how to get API name correctly */
+            snprintf(indevlist + nin * devdescsize, devdescsize,
+#ifdef _WIN32
+     "%s:%s", (pdi->hostApi == 0 ? "MMIO" : (pdi->hostApi == 1 ? "ASIO" : "?")),
+#else
+#ifdef __APPLE__
+             "%s",
+#else
+            "(%d) %s", pdi->hostApi,
+#endif
+#endif
+                pdi->name);
             nin++;
         }
         if (pdi->maxOutputChannels > 0 && nout < maxndev)
         {
-            sprintf(outdevlist + nout * devdescsize, "(%d)%s",
-                pdi->hostApi,pdi->name);
-            /* strcpy(outdevlist + nout * devdescsize, pdi->name); */
+            snprintf(outdevlist + nout * devdescsize, devdescsize,
+#ifdef _WIN32
+     "%s:%s", (pdi->hostApi == 0 ? "MMIO" : (pdi->hostApi == 1 ? "ASIO" : "?")),
+#else
+#ifdef __APPLE__
+             "%s",
+#else
+            "(%d) %s", pdi->hostApi,
+#endif
+#endif
+                pdi->name);
             nout++;
         }
     }
diff --git a/pd/src/s_audio_pablio.c b/pd/src/s_audio_pablio.c
deleted file mode 100644
index 0873f269402d6a440f6ed65bf287f3caef79d1a4..0000000000000000000000000000000000000000
--- a/pd/src/s_audio_pablio.c
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
-
- * pablio.c
- * Portable Audio Blocking Input/Output utility.
- *
- * Author: Phil Burk, http://www.softsynth.com
- *
- * This program uses the PortAudio Portable Audio Library.
- * For more information see: http://www.audiomulch.com/portaudio/
- * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files
- * (the "Software"), to deal in the Software without restriction,
- * including without limitation the rights to use, copy, modify, merge,
- * publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * Any person wishing to distribute modifications to the Software is
- * requested to send the modifications to the original developer so that
- * they can be incorporated into the canonical version.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-
- /* changes by Miller Puckette to support Pd:  device selection, 
-    settable audio buffer size, and settable number of channels.
-    LATER also fix it to poll for input and output fifo fill points. */
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include "portaudio.h"
-#include "s_audio_paring.h"
-#include "s_audio_pablio.h"     /* MSP */
-#include <string.h>
-
-    /* MSP -- FRAMES_PER_BUFFER constant removed */
-static void NPa_Sleep(int n)    /* MSP wrapper to check we never stall... */
-{
-#if 0
-    fprintf(stderr, "sleep\n");
-#endif
-    Pa_Sleep(n);
-}
-
-/************************************************************************/
-/******** Prototypes ****************************************************/
-/************************************************************************/
-
-static int blockingIOCallback( const void *inputBuffer, void *outputBuffer, /*MSP */
-                               unsigned long framesPerBuffer,
-                               const PaStreamCallbackTimeInfo *outTime, 
-                               PaStreamCallbackFlags myflags, 
-                               void *userData );
-static PaError PABLIO_InitFIFO( sys_ringbuf *rbuf, long numFrames, long bytesPerFrame );
-static PaError PABLIO_TermFIFO( sys_ringbuf *rbuf );
-
-/************************************************************************/
-/******** Functions *****************************************************/
-/************************************************************************/
-
-/* Called from PortAudio.
- * Read and write data only if there is room in FIFOs.
- */
-static int blockingIOCallback( const void *inputBuffer, void *outputBuffer, /* MSP */
-                               unsigned long framesPerBuffer,
-                               const PaStreamCallbackTimeInfo *outTime, 
-                               PaStreamCallbackFlags myflags, 
-                               void *userData )
-{
-    PABLIO_Stream *data = (PABLIO_Stream*)userData;
-    (void) outTime;
-
-    /* This may get called with NULL inputBuffer during initial setup. */
-    if( inputBuffer != NULL )
-    {
-        sys_ringbuf_Write( &data->inFIFO, inputBuffer,
-            data->inbytesPerFrame * framesPerBuffer );
-    }
-    if( outputBuffer != NULL )
-    {
-        int i;
-        int numBytes = data->outbytesPerFrame * framesPerBuffer;
-        int numRead = sys_ringbuf_Read( &data->outFIFO, outputBuffer,
-            numBytes);
-        /* Zero out remainder of buffer if we run out of data. */
-        for( i=numRead; i<numBytes; i++ )
-        {
-            ((char *)outputBuffer)[i] = 0;
-        }
-    }
-
-    return 0;
-}
-
-/* Allocate buffer. */
-static PaError PABLIO_InitFIFO( sys_ringbuf *rbuf, long numFrames, long bytesPerFrame )
-{
-    long numBytes = numFrames * bytesPerFrame;
-    char *buffer = (char *) malloc( numBytes );
-    if( buffer == NULL ) return paInsufficientMemory;
-    memset( buffer, 0, numBytes );
-    return (PaError) sys_ringbuf_Init( rbuf, numBytes, buffer );
-}
-
-/* Free buffer. */
-static PaError PABLIO_TermFIFO( sys_ringbuf *rbuf )
-{
-    if( rbuf->buffer ) free( rbuf->buffer );
-    rbuf->buffer = NULL;
-    return paNoError;
-}
-
-/************************************************************
- * Write data to ring buffer.
- * Will not return until all the data has been written.
- */
-long WriteAudioStream( PABLIO_Stream *aStream, void *data, long numFrames )
-{
-    long bytesWritten;
-    char *p = (char *) data;
-    long numBytes = aStream->outbytesPerFrame * numFrames;
-    while( numBytes > 0)
-    {
-        bytesWritten = sys_ringbuf_Write( &aStream->outFIFO, p, numBytes );
-        numBytes -= bytesWritten;
-        p += bytesWritten;
-        if( numBytes > 0) NPa_Sleep(10); /* MSP */
-    }
-    return numFrames;
-}
-
-/************************************************************
- * Read data from ring buffer.
- * Will not return until all the data has been read.
- */
-long ReadAudioStream( PABLIO_Stream *aStream, void *data, long numFrames )
-{
-    long bytesRead;
-    char *p = (char *) data;
-    long numBytes = aStream->inbytesPerFrame * numFrames;
-    while( numBytes > 0)
-    {
-        bytesRead = sys_ringbuf_Read( &aStream->inFIFO, p, numBytes );
-        numBytes -= bytesRead;
-        p += bytesRead;
-        if( numBytes > 0) NPa_Sleep(10); /* MSP */
-    }
-    return numFrames;
-}
-
-/************************************************************
- * Return the number of frames that could be written to the stream without
- * having to wait.
- */
-long GetAudioStreamWriteable( PABLIO_Stream *aStream )
-{
-    int bytesEmpty = sys_ringbuf_GetWriteAvailable( &aStream->outFIFO );
-    return bytesEmpty / aStream->outbytesPerFrame;
-}
-
-/************************************************************
- * Return the number of frames that are available to be read from the
- * stream without having to wait.
- */
-long GetAudioStreamReadable( PABLIO_Stream *aStream )
-{
-    int bytesFull = sys_ringbuf_GetReadAvailable( &aStream->inFIFO );
-    return bytesFull / aStream->inbytesPerFrame;
-}
-
-/************************************************************/
-static unsigned long RoundUpToNextPowerOf2( unsigned long n )
-{
-    long numBits = 0;
-    if( ((n-1) & n) == 0) return n; /* Already Power of two. */
-    while( n > 0 )
-    {
-        n= n>>1;
-        numBits++;
-    }
-    return (1<<numBits);
-}
-
-/************************************************************
- * Opens a PortAudio stream with default characteristics.
- * Allocates PABLIO_Stream structure.
- *
- * flags parameter can be an ORed combination of:
- *    PABLIO_READ, PABLIO_WRITE, or PABLIO_READ_WRITE
- */
-PaError OpenAudioStream( PABLIO_Stream **rwblPtr, double sampleRate,
-                         PaSampleFormat format, int inchannels,
-                         int outchannels, int framesperbuf, int nbuffers,
-                         int indeviceno, int outdeviceno) /* MSP */
-{
-    long   bytesPerSample;
-    long   doRead = 0;
-    long   doWrite = 0;
-    PaError err;
-    PABLIO_Stream *aStream;
-    long   numFrames;
-    PaStreamParameters instreamparams, outstreamparams;  /* MSP */
-
-    /* fprintf(stderr,
-        "open %lf fmt %d flags %d ch: %d fperbuf: %d nbuf: %d devs: %d %d\n",
-           sampleRate, format, flags, nchannels,
-           framesperbuf, nbuffers, indeviceno, outdeviceno); */
-
-    if (indeviceno < 0)  /* MSP... */
-    {
-        indeviceno = Pa_GetDefaultInputDevice();
-        fprintf(stderr, "using default input device number: %d\n", indeviceno);
-    }
-    if (outdeviceno < 0)
-    {
-        outdeviceno = Pa_GetDefaultOutputDevice();
-        fprintf(stderr, "using default output device number: %d\n", outdeviceno);
-    }
-    /* fprintf(stderr, "nchan %d, flags %d, bufs %d, framesperbuf %d\n",
-            nchannels, flags, nbuffers, framesperbuf); */
-        /* ...MSP */
-
-    /* Allocate PABLIO_Stream structure for caller. */
-    aStream = (PABLIO_Stream *) malloc( sizeof(PABLIO_Stream) );
-    if( aStream == NULL ) return paInsufficientMemory;
-    memset( aStream, 0, sizeof(PABLIO_Stream) );
-
-    /* Determine size of a sample. */
-    bytesPerSample = Pa_GetSampleSize( format );
-    if( bytesPerSample < 0 )
-    {
-        err = (PaError) bytesPerSample;
-        goto error;
-    }
-    aStream->insamplesPerFrame = inchannels;  /* MSP */
-    aStream->inbytesPerFrame = bytesPerSample * aStream->insamplesPerFrame;
-    aStream->outsamplesPerFrame = outchannels;
-    aStream->outbytesPerFrame = bytesPerSample * aStream->outsamplesPerFrame;
-
-    /* Initialize PortAudio  */
-    err = Pa_Initialize();
-    if( err != paNoError ) goto error;
-
-    numFrames = nbuffers * framesperbuf; /* ...MSP */
-
-    instreamparams.device = indeviceno;   /* MSP... */
-    instreamparams.channelCount = inchannels;
-    instreamparams.sampleFormat = format;
-    instreamparams.suggestedLatency = nbuffers*framesperbuf/sampleRate;
-    instreamparams.hostApiSpecificStreamInfo = 0;
-    
-    outstreamparams.device = outdeviceno;
-    outstreamparams.channelCount = outchannels;
-    outstreamparams.sampleFormat = format;
-    outstreamparams.suggestedLatency = nbuffers*framesperbuf/sampleRate;
-    outstreamparams.hostApiSpecificStreamInfo = 0;  /* ... MSP */
-
-    numFrames = nbuffers * framesperbuf;
-    /* fprintf(stderr, "numFrames %d\n", numFrames); */
-    /* Initialize Ring Buffers */
-    doRead = (inchannels != 0);
-    doWrite = (outchannels != 0);
-    if(doRead)
-    {
-        err = PABLIO_InitFIFO( &aStream->inFIFO, numFrames,
-            aStream->inbytesPerFrame );
-        if( err != paNoError ) goto error;
-    }
-    if(doWrite)
-    {
-        long numBytes;
-        err = PABLIO_InitFIFO( &aStream->outFIFO, numFrames,
-            aStream->outbytesPerFrame );
-        if( err != paNoError ) goto error;
-        /* Make Write FIFO appear full initially. */
-        numBytes = sys_ringbuf_GetWriteAvailable( &aStream->outFIFO );
-        sys_ringbuf_AdvanceWriteIndex( &aStream->outFIFO, numBytes );
-    }
-
-    /* Open a PortAudio stream that we will use to communicate with the underlying
-     * audio drivers. */
-    err = Pa_OpenStream(
-              &aStream->stream,
-              (doRead ? &instreamparams : 0),  /* MSP */
-              (doWrite ? &outstreamparams : 0),  /* MSP */
-              sampleRate,
-              framesperbuf,  /* MSP */
-              paNoFlag,      /* MSP -- portaudio will clip for us */
-              blockingIOCallback,
-              aStream );
-    if( err != paNoError ) goto error;
-
-    err = Pa_StartStream( aStream->stream );
-    if( err != paNoError )      /* MSP */
-    {
-        fprintf(stderr, "Pa_StartStream failed; closing audio stream...\n");
-        CloseAudioStream( aStream );
-        goto error;
-    }
-
-    *rwblPtr = aStream;
-    return paNoError;
-
-error:
-    *rwblPtr = NULL;
-    return err;
-}
-
-/************************************************************/
-PaError CloseAudioStream( PABLIO_Stream *aStream )
-{
-    PaError err;
-    int bytesEmpty;
-    int byteSize = aStream->outFIFO.bufferSize;
-
-    /* If we are writing data, make sure we play everything written. */
-    if( byteSize > 0 )
-    {
-        bytesEmpty = sys_ringbuf_GetWriteAvailable( &aStream->outFIFO );
-        while( bytesEmpty < byteSize )
-        {
-            NPa_Sleep( 10 ); /* MSP */
-            bytesEmpty = sys_ringbuf_GetWriteAvailable( &aStream->outFIFO );
-        }
-    }
-
-    err = Pa_StopStream( aStream->stream );
-    if( err != paNoError ) goto error;
-    err = Pa_CloseStream( aStream->stream );
-    if( err != paNoError ) goto error;
-    Pa_Terminate();
-
-error:
-    PABLIO_TermFIFO( &aStream->inFIFO );
-    PABLIO_TermFIFO( &aStream->outFIFO );
-    free( aStream );
-    return err;
-}
diff --git a/pd/src/s_audio_pablio.h b/pd/src/s_audio_pablio.h
deleted file mode 100644
index f4d3261460a9562305ba9db4033445a99fc6abf9..0000000000000000000000000000000000000000
--- a/pd/src/s_audio_pablio.h
+++ /dev/null
@@ -1,111 +0,0 @@
-#ifndef _PABLIO_H
-#define _PABLIO_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif /* __cplusplus */
-
-/*
- * PABLIO.h
- * Portable Audio Blocking read/write utility.
- *
- * Author: Phil Burk, http://www.softsynth.com/portaudio/
- *
- * Include file for PABLIO, the Portable Audio Blocking I/O Library.
- * PABLIO is built on top of PortAudio, the Portable Audio Library.
- * For more information see: http://www.audiomulch.com/portaudio/
- * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files
- * (the "Software"), to deal in the Software without restriction,
- * including without limitation the rights to use, copy, modify, merge,
- * publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * Any person wishing to distribute modifications to the Software is
- * requested to send the modifications to the original developer so that
- * they can be incorporated into the canonical version.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include "portaudio.h"
-#include "s_audio_paring.h"
-#include <string.h>
-
-typedef struct
-{
-    sys_ringbuf   inFIFO;
-    sys_ringbuf   outFIFO;
-    PaStream *stream;
-    int          inbytesPerFrame;
-    int          insamplesPerFrame;
-    int          outbytesPerFrame;
-    int          outsamplesPerFrame;
-}
-PABLIO_Stream;
-
-/* Values for flags for OpenAudioStream(). */
-#define PABLIO_READ     (1<<0)
-#define PABLIO_WRITE    (1<<1)
-#define PABLIO_READ_WRITE    (PABLIO_READ|PABLIO_WRITE)
-#define PABLIO_MONO     (1<<2)
-#define PABLIO_STEREO   (1<<3)
-
-/************************************************************
- * Write data to ring buffer.
- * Will not return until all the data has been written.
- */
-long WriteAudioStream( PABLIO_Stream *aStream, void *data, long numFrames );
-
-/************************************************************
- * Read data from ring buffer.
- * Will not return until all the data has been read.
- */
-long ReadAudioStream( PABLIO_Stream *aStream, void *data, long numFrames );
-
-/************************************************************
- * Return the number of frames that could be written to the stream without
- * having to wait.
- */
-long GetAudioStreamWriteable( PABLIO_Stream *aStream );
-
-/************************************************************
- * Return the number of frames that are available to be read from the
- * stream without having to wait.
- */
-long GetAudioStreamReadable( PABLIO_Stream *aStream );
-
-/************************************************************
- * Opens a PortAudio stream with default characteristics.
- * Allocates PABLIO_Stream structure.
- *
- * flags parameter can be an ORed combination of:
- *    PABLIO_READ, PABLIO_WRITE, or PABLIO_READ_WRITE,
- */
-PaError OpenAudioStream( PABLIO_Stream **rwblPtr, double sampleRate,
-                         PaSampleFormat format, int inchannels,
-                         int outchannels, int framesperbuf, int nbuffers,
-                         int indeviceno, int outdeviceno); /* MSP */
-
-PaError CloseAudioStream( PABLIO_Stream *aStream );
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-#endif /* _PABLIO_H */
diff --git a/pd/src/s_audio_paring.c b/pd/src/s_audio_paring.c
index 6e645e45b91fe15bb29d5e143a6da4149695514c..02f6d88de1216f63b6fb4882e48a582f3fa31dcf 100644
--- a/pd/src/s_audio_paring.c
+++ b/pd/src/s_audio_paring.c
@@ -31,10 +31,10 @@
  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *
- */
-/*
  * modified 2002/07/13 by olaf.matthes@gmx.de to allow any number if channels
  *
+ * extensively hacked by msp@ucsd.edu for various reasons
+ *
  */
 
 #include <stdio.h>
@@ -43,40 +43,73 @@
 #include "s_audio_paring.h"
 #include <string.h>
 
+/* Clear buffer. Should only be called when buffer is NOT being read. */
+static void sys_ringbuf_Flush(PA_VOLATILE sys_ringbuf *rbuf,
+    PA_VOLATILE void *dataPtr, long nfill);
+
+/* Get address of region(s) to which we can write data.
+** If the region is contiguous, size2 will be zero.
+** If non-contiguous, size2 will be the size of second region.
+** Returns room available to be written or numBytes, whichever is smaller.
+*/
+static long sys_ringbuf_GetWriteRegions(PA_VOLATILE  sys_ringbuf *rbuf,
+    long numBytes, PA_VOLATILE void **dataPtr1, long *sizePtr1,
+    PA_VOLATILE void **dataPtr2, long *sizePtr2, PA_VOLATILE char *buffer);
+static long sys_ringbuf_AdvanceWriteIndex(PA_VOLATILE sys_ringbuf *rbuf,
+    long numBytes);
+
+/* Get address of region(s) from which we can read data.
+** If the region is contiguous, size2 will be zero.
+** If non-contiguous, size2 will be the size of second region.
+** Returns room available to be read or numBytes, whichever is smaller.
+*/
+static long sys_ringbuf_GetReadRegions(PA_VOLATILE sys_ringbuf *rbuf,
+    long numBytes, PA_VOLATILE void **dataPtr1, long *sizePtr1,
+    PA_VOLATILE void **dataPtr2, long *sizePtr2, PA_VOLATILE char *buffer);
+
+static long sys_ringbuf_AdvanceReadIndex(PA_VOLATILE sys_ringbuf *rbuf,
+    long numBytes );
+
 /***************************************************************************
  * Initialize FIFO.
  */
-long sys_ringbuf_Init( sys_ringbuf *rbuf, long numBytes, void *dataPtr )
+long sys_ringbuf_init(PA_VOLATILE sys_ringbuf *rbuf, long numBytes, 
+    PA_VOLATILE char *dataPtr, long nfill)
 {
     rbuf->bufferSize = numBytes;
-    rbuf->buffer = (char *)dataPtr;
-    sys_ringbuf_Flush( rbuf );
+    sys_ringbuf_Flush(rbuf, dataPtr,  nfill);
     return 0;
 }
 /***************************************************************************
 ** Return number of bytes available for reading. */
-long sys_ringbuf_GetReadAvailable( sys_ringbuf *rbuf )
+long sys_ringbuf_getreadavailable(PA_VOLATILE sys_ringbuf *rbuf)
 {
     long ret = rbuf->writeIndex - rbuf->readIndex;
     if (ret < 0)
         ret += 2 * rbuf->bufferSize;
     if (ret < 0 || ret > rbuf->bufferSize)
         fprintf(stderr,
-            "consistency check failed: sys_ringbuf_GetReadAvailable\n");
+            "consistency check failed: sys_ringbuf_getreadavailable\n");
     return ( ret );
 }
 /***************************************************************************
 ** Return number of bytes available for writing. */
-long sys_ringbuf_GetWriteAvailable( sys_ringbuf *rbuf )
+long sys_ringbuf_getwriteavailable(PA_VOLATILE sys_ringbuf *rbuf)
 {
-    return ( rbuf->bufferSize - sys_ringbuf_GetReadAvailable(rbuf));
+    return ( rbuf->bufferSize - sys_ringbuf_getreadavailable(rbuf));
 }
 
 /***************************************************************************
 ** Clear buffer. Should only be called when buffer is NOT being read. */
-void sys_ringbuf_Flush( sys_ringbuf *rbuf )
+static void sys_ringbuf_Flush(PA_VOLATILE sys_ringbuf *rbuf,
+    PA_VOLATILE void *dataPtr, long nfill)
 {
-    rbuf->writeIndex = rbuf->readIndex = 0;
+    PA_VOLATILE char *s;
+    long n;
+    rbuf->readIndex = 0;
+    rbuf->writeIndex = nfill;
+    for (n = nfill, s = dataPtr; n--; s++)
+        *s = 0;
 }
 
 /***************************************************************************
@@ -85,12 +118,12 @@ void sys_ringbuf_Flush( sys_ringbuf *rbuf )
 ** If non-contiguous, size2 will be the size of second region.
 ** Returns room available to be written or numBytes, whichever is smaller.
 */
-long sys_ringbuf_GetWriteRegions( sys_ringbuf *rbuf, long numBytes,
-                                 void **dataPtr1, long *sizePtr1,
-                                 void **dataPtr2, long *sizePtr2 )
+static long sys_ringbuf_GetWriteRegions(PA_VOLATILE  sys_ringbuf *rbuf,
+    long numBytes, PA_VOLATILE void **dataPtr1, long *sizePtr1,
+    PA_VOLATILE void **dataPtr2, long *sizePtr2, PA_VOLATILE char *buffer)
 {
     long   index;
-    long   available = sys_ringbuf_GetWriteAvailable( rbuf );
+    long   available = sys_ringbuf_getwriteavailable( rbuf );
     if( numBytes > available ) numBytes = available;
     /* Check to see if write is not contiguous. */
     index = rbuf->writeIndex;
@@ -100,14 +133,14 @@ long sys_ringbuf_GetWriteRegions( sys_ringbuf *rbuf, long numBytes,
     {
         /* Write data in two blocks that wrap the buffer. */
         long   firstHalf = rbuf->bufferSize - index;
-        *dataPtr1 = &rbuf->buffer[index];
+        *dataPtr1 = &buffer[index];
         *sizePtr1 = firstHalf;
-        *dataPtr2 = &rbuf->buffer[0];
+        *dataPtr2 = &buffer[0];
         *sizePtr2 = numBytes - firstHalf;
     }
     else
     {
-        *dataPtr1 = &rbuf->buffer[index];
+        *dataPtr1 = &buffer[index];
         *sizePtr1 = numBytes;
         *dataPtr2 = NULL;
         *sizePtr2 = 0;
@@ -118,7 +151,8 @@ long sys_ringbuf_GetWriteRegions( sys_ringbuf *rbuf, long numBytes,
 
 /***************************************************************************
 */
-long sys_ringbuf_AdvanceWriteIndex( sys_ringbuf *rbuf, long numBytes )
+static long sys_ringbuf_AdvanceWriteIndex(PA_VOLATILE sys_ringbuf *rbuf,
+    long numBytes)
 {
     long ret = (rbuf->writeIndex + numBytes);
     if ( ret >= 2 * rbuf->bufferSize)
@@ -132,12 +166,12 @@ long sys_ringbuf_AdvanceWriteIndex( sys_ringbuf *rbuf, long numBytes )
 ** If non-contiguous, size2 will be the size of second region.
 ** Returns room available to be written or numBytes, whichever is smaller.
 */
-long sys_ringbuf_GetReadRegions( sys_ringbuf *rbuf, long numBytes,
-                                void **dataPtr1, long *sizePtr1,
-                                void **dataPtr2, long *sizePtr2 )
+static long sys_ringbuf_GetReadRegions(PA_VOLATILE sys_ringbuf *rbuf,
+    long numBytes, PA_VOLATILE void **dataPtr1, long *sizePtr1,
+    PA_VOLATILE void **dataPtr2, long *sizePtr2, PA_VOLATILE char *buffer)
 {
     long   index;
-    long   available = sys_ringbuf_GetReadAvailable( rbuf );
+    long   available = sys_ringbuf_getreadavailable( rbuf );
     if( numBytes > available ) numBytes = available;
     /* Check to see if read is not contiguous. */
     index = rbuf->readIndex;
@@ -148,14 +182,14 @@ long sys_ringbuf_GetReadRegions( sys_ringbuf *rbuf, long numBytes,
     {
         /* Write data in two blocks that wrap the buffer. */
         long firstHalf = rbuf->bufferSize - index;
-        *dataPtr1 = &rbuf->buffer[index];
+        *dataPtr1 = &buffer[index];
         *sizePtr1 = firstHalf;
-        *dataPtr2 = &rbuf->buffer[0];
+        *dataPtr2 = &buffer[0];
         *sizePtr2 = numBytes - firstHalf;
     }
     else
     {
-        *dataPtr1 = &rbuf->buffer[index];
+        *dataPtr1 = &buffer[index];
         *sizePtr1 = numBytes;
         *dataPtr2 = NULL;
         *sizePtr2 = 0;
@@ -164,7 +198,8 @@ long sys_ringbuf_GetReadRegions( sys_ringbuf *rbuf, long numBytes,
 }
 /***************************************************************************
 */
-long sys_ringbuf_AdvanceReadIndex( sys_ringbuf *rbuf, long numBytes )
+static long sys_ringbuf_AdvanceReadIndex(PA_VOLATILE sys_ringbuf *rbuf,
+    long numBytes)
 {
     long ret = (rbuf->readIndex + numBytes);
     if( ret >= 2 * rbuf->bufferSize)
@@ -174,21 +209,23 @@ long sys_ringbuf_AdvanceReadIndex( sys_ringbuf *rbuf, long numBytes )
 
 /***************************************************************************
 ** Return bytes written. */
-long sys_ringbuf_Write( sys_ringbuf *rbuf, const void *data, long numBytes )
+long sys_ringbuf_write(PA_VOLATILE sys_ringbuf *rbuf, const void *data,
+    long numBytes, PA_VOLATILE char *buffer)
 {
     long size1, size2, numWritten;
-    void *data1, *data2;
-    numWritten = sys_ringbuf_GetWriteRegions( rbuf, numBytes, &data1, &size1, &data2, &size2 );
+    PA_VOLATILE void *data1, *data2;
+    numWritten = sys_ringbuf_GetWriteRegions( rbuf, numBytes, &data1, &size1,
+        &data2, &size2, buffer);
     if( size2 > 0 )
     {
 
-        memcpy( data1, data, size1 );
+        memcpy((void *)data1, data, size1 );
         data = ((char *)data) + size1;
-        memcpy( data2, data, size2 );
+        memcpy((void *)data2, data, size2 );
     }
     else
     {
-        memcpy( data1, data, size1 );
+        memcpy((void *)data1, data, size1 );
     }
     sys_ringbuf_AdvanceWriteIndex( rbuf, numWritten );
     return numWritten;
@@ -196,20 +233,22 @@ long sys_ringbuf_Write( sys_ringbuf *rbuf, const void *data, long numBytes )
 
 /***************************************************************************
 ** Return bytes read. */
-long sys_ringbuf_Read( sys_ringbuf *rbuf, void *data, long numBytes )
+long sys_ringbuf_read(PA_VOLATILE sys_ringbuf *rbuf, void *data, long numBytes,
+    PA_VOLATILE char *buffer)
 {
     long size1, size2, numRead;
-    void *data1, *data2;
-    numRead = sys_ringbuf_GetReadRegions( rbuf, numBytes, &data1, &size1, &data2, &size2 );
+    PA_VOLATILE void *data1, *data2;
+    numRead = sys_ringbuf_GetReadRegions( rbuf, numBytes, &data1, &size1,
+        &data2, &size2, buffer);
     if( size2 > 0 )
     {
-        memcpy( data, data1, size1 );
+        memcpy(data, (void *)data1, size1 );
         data = ((char *)data) + size1;
-        memcpy( data, data2, size2 );
+        memcpy(data, (void *)data2, size2 );
     }
     else
     {
-        memcpy( data, data1, size1 );
+        memcpy( data, (void *)data1, size1 );
     }
     sys_ringbuf_AdvanceReadIndex( rbuf, numRead );
     return numRead;
diff --git a/pd/src/s_audio_paring.h b/pd/src/s_audio_paring.h
index e5e5e6b294758d7c1d30a902721b3aa0d4f06a83..4154c22216dc23899e850570959a05132298241d 100644
--- a/pd/src/s_audio_paring.h
+++ b/pd/src/s_audio_paring.h
@@ -39,61 +39,35 @@ extern "C"
  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *
  */
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include "s_audio_paring.h"
-#include <string.h>
+
+/* If it's ever desired to use shared memory so that one process reads and
+another one writes to the same ring buffer, define this as 'volatile' : */
+#define PA_VOLATILE 
 
 typedef struct
 {
-    long   bufferSize; /* Number of bytes in FIFO. Power of 2. Set by sys_ringbuf_Init. */
-/* These are declared volatile because they are written by a different thread than the reader. */
-    volatile long   writeIndex; /* Index of next writable byte. Set by sys_ringbuf_AdvanceWriteIndex. */
-    volatile long   readIndex;  /* Index of next readable byte. Set by sys_ringbuf_AdvanceReadIndex. */
-    long   bigMask;    /* Used for wrapping indices with extra bit to distinguish full/empty. */
-    long   smallMask;  /* Used for fitting indices to buffer. */
-    char *buffer;
-}
-sys_ringbuf;
-/*
- * Initialize Ring Buffer.
- * numBytes must be power of 2, returns -1 if not.
- */
-long sys_ringbuf_Init( sys_ringbuf *rbuf, long numBytes, void *dataPtr );
+    long   bufferSize;              /* Number of bytes in FIFO.
+                                        Set by sys_ringbuf_init */
+    PA_VOLATILE long   writeIndex; /* Index of next writable byte.
+                                        Set by sys_ringbuf_AdvanceWriteIndex */
+    PA_VOLATILE long   readIndex;  /* Index of next readable byte.
+                                        Set by sys_ringbuf_AdvanceReadIndex */
+} sys_ringbuf;
 
-/* Clear buffer. Should only be called when buffer is NOT being read. */
-void sys_ringbuf_Flush( sys_ringbuf *rbuf );
+/* Initialize Ring Buffer. */
+long sys_ringbuf_init(PA_VOLATILE sys_ringbuf *rbuf, long numBytes,
+    PA_VOLATILE char *dataPtr, long nfill);
 
 /* Return number of bytes available for writing. */
-long sys_ringbuf_GetWriteAvailable( sys_ringbuf *rbuf );
+long sys_ringbuf_getwriteavailable(PA_VOLATILE sys_ringbuf *rbuf);
 /* Return number of bytes available for read. */
-long sys_ringbuf_GetReadAvailable( sys_ringbuf *rbuf );
+long sys_ringbuf_getreadavailable(PA_VOLATILE sys_ringbuf *rbuf);
 /* Return bytes written. */
-long sys_ringbuf_Write( sys_ringbuf *rbuf, const void *data, long numBytes );
+long sys_ringbuf_write(PA_VOLATILE sys_ringbuf *rbuf, const void *data,
+    long numBytes, PA_VOLATILE char *buffer);
 /* Return bytes read. */
-long sys_ringbuf_Read( sys_ringbuf *rbuf, void *data, long numBytes );
-
-/* Get address of region(s) to which we can write data.
-** If the region is contiguous, size2 will be zero.
-** If non-contiguous, size2 will be the size of second region.
-** Returns room available to be written or numBytes, whichever is smaller.
-*/
-long sys_ringbuf_GetWriteRegions( sys_ringbuf *rbuf, long numBytes,
-                                 void **dataPtr1, long *sizePtr1,
-                                 void **dataPtr2, long *sizePtr2 );
-long sys_ringbuf_AdvanceWriteIndex( sys_ringbuf *rbuf, long numBytes );
-
-/* Get address of region(s) from which we can read data.
-** If the region is contiguous, size2 will be zero.
-** If non-contiguous, size2 will be the size of second region.
-** Returns room available to be read or numBytes, whichever is smaller.
-*/
-long sys_ringbuf_GetReadRegions( sys_ringbuf *rbuf, long numBytes,
-                                void **dataPtr1, long *sizePtr1,
-                                void **dataPtr2, long *sizePtr2 );
-
-long sys_ringbuf_AdvanceReadIndex( sys_ringbuf *rbuf, long numBytes );
+long sys_ringbuf_read(PA_VOLATILE sys_ringbuf *rbuf, void *data, long numBytes,
+    PA_VOLATILE char *buffer);
 
 #ifdef __cplusplus
 }
diff --git a/pd/src/s_file.c b/pd/src/s_file.c
index 7c12da3b22291d3b5a441b8bc6f75bc00e4a49c3..1d086e4f1bdd81de28a64c1f672a0886986ed60e 100644
--- a/pd/src/s_file.c
+++ b/pd/src/s_file.c
@@ -373,6 +373,8 @@ 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, blocksize);
diff --git a/pd/src/s_stuff.h b/pd/src/s_stuff.h
index 3af586934da524f7909961f8ee50459c08af2e85..5a9153cedd012de5d4d21fc094371ada26f29282 100644
--- a/pd/src/s_stuff.h
+++ b/pd/src/s_stuff.h
@@ -261,7 +261,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);
@@ -290,7 +290,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);
@@ -309,6 +309,7 @@ void sys_set_audio_state(int onoff);
 void oss_set32bit( void);
 void linux_alsa_devname(char *devname);
 
+EXTERN int sys_audio_get_blocksize(void);
 EXTERN void sys_get_audio_params(
     int *pnaudioindev, int *paudioindev, int *chindev,
     int *pnaudiooutdev, int *paudiooutdev, int *choutdev,
diff --git a/pd/src/x_interface.c b/pd/src/x_interface.c
index 90f568706c933970d2449f66f91ae844eb181ece..a10cd8b17f0a1028804b3888f68331744060cee0 100644
--- a/pd/src/x_interface.c
+++ b/pd/src/x_interface.c
@@ -817,7 +817,7 @@ void pdinfo_audio_samplerate(t_pdinfo *x, t_symbol *s, int argc, t_atom *argv)
 void pdinfo_audio_blocksize(t_pdinfo *x, t_symbol *s, int argc, t_atom *argv)
 {
     t_atom at[1];
-    SETFLOAT(at, (t_float)sys_getblksize());
+    SETFLOAT(at, (t_float)sys_audio_get_blocksize());
     info_out((t_text *)x, s, 1, at);
 }