[PD-cvs] pd/src s_audio_pa.c, 1.4.4.2, 1.4.4.3 s_audio.c, 1.5.4.12, 1.5.4.13 s_stuff.h, 1.5.4.5, 1.5.4.6

Tim Blechmann timblech at users.sourceforge.net
Wed May 11 16:32:11 CEST 2005


Update of /cvsroot/pure-data/pd/src
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv30038

Modified Files:
      Tag: devel_0_38
	s_audio_pa.c s_audio.c s_stuff.h 
Log Message:
callback based scheduling for portaudio v19

Index: s_audio_pa.c
===================================================================
RCS file: /cvsroot/pure-data/pd/src/s_audio_pa.c,v
retrieving revision 1.4.4.2
retrieving revision 1.4.4.3
diff -C2 -d -r1.4.4.2 -r1.4.4.3
*** s_audio_pa.c	26 Nov 2004 10:03:41 -0000	1.4.4.2
--- s_audio_pa.c	11 May 2005 14:32:07 -0000	1.4.4.3
***************
*** 4,10 ****
  
  /* 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. */
  
  
  #include "m_pd.h"
--- 4,11 ----
  
  /* 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. */
  
+ /* tb: requires portaudio >= V19 */
  
  #include "m_pd.h"
***************
*** 13,66 ****
  #include <stdlib.h>
  #include <portaudio.h>
! #include "s_audio_pablio.h"
  
  #ifdef MSW
! /* jmz thinks that we have to include:
!  * on Windows: <malloc.h> (probably this is already included?)
!  * on linux: <alloca.h> (might be true for osX too, no way to check right now...)
!  */
! # include <malloc.h>
! #else
! # include <alloca.h>
  #endif
  
!     /* 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 int pa_inchans, pa_outchans;
! static float *pa_soundin, *pa_soundout;
  
! #define MAX_PA_CHANS 32
  
! #ifndef PA19
! #define Pa_GetDeviceCount Pa_CountDevices
! #endif
  
  int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin,
!     t_sample *soundout, int framesperbuf, int nbuffers,
!     int indeviceno, int outdeviceno)
  {
      PaError err;
-     static int initialized;
      int j, devno, pa_indev = 0, pa_outdev = 0;
  
!     if (!initialized)
!     {
!         /* Initialize PortAudio  */
!         int err = Pa_Initialize();
!         if ( err != paNoError ) 
!         {
!             fprintf( stderr,
!                 "Error number %d occured initializing portaudio\n",
!                 err); 
!             fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
!             return (1);
!         }
!         initialized = 1;
!     }
      /* post("in %d out %d rate %d device %d", inchans, outchans, rate, deviceno); */
      if (inchans > MAX_PA_CHANS)
--- 14,69 ----
  #include <stdlib.h>
  #include <portaudio.h>
! #include <errno.h>
  
  #ifdef MSW
! #include "pthread.h" /* for ETIMEDOUT */
  #endif
  
! #define MAX_PA_CHANS 32
  
! #define PA19
! /* portaudio's blocking api is not working, yet: */
! /* #define PABLOCKING */ 
  
  static int pa_inchans, pa_outchans;
! static float *pa_soundin[MAX_PA_CHANS], *pa_soundout[MAX_PA_CHANS];
  
! static PaStream *pa_stream;
! static PaStreamCallback *pa_callback = NULL;
  
! int process (const void *input, void *output, unsigned long frameCount, 
! 			 const PaStreamCallbackTimeInfo* timeInfo, 
! 			 PaStreamCallbackFlags statusFlags, void *userData);
  
  int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin,
!     t_sample *soundout, int advance, 
!     int indeviceno, int outdeviceno, int schedmode)
  {
      PaError err;
      int j, devno, pa_indev = 0, pa_outdev = 0;
  
! #ifndef PABLOCKING
! 	schedmode = 1;
! #endif
! 
! 	if (schedmode == 1)
! 		pa_callback = process;
! 	else
! 		pa_callback = NULL;
! 	
! 	sys_keepsched = 0;
! 	sys_callbackscheduler = schedmode;
! 
! 	/* Initialize PortAudio  */
! 	err = Pa_Initialize();
! 	if ( err != paNoError )
! 	{
! 		fprintf( stderr,
! 				 "Error number %d occured initializing portaudio\n",
! 				 err);
! 		fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
! 		return (1);
! 	}
! 
      /* post("in %d out %d rate %d device %d", inchans, outchans, rate, deviceno); */
      if (inchans > MAX_PA_CHANS)
***************
*** 90,94 ****
              }
          }
!     }   
      
      if (outchans > 0)
--- 93,97 ----
              }
          }
!     }
      
      if (outchans > 0)
***************
*** 107,111 ****
              }
          }
!     }   
  
      if (sys_verbose)
--- 110,114 ----
              }
          }
!     }
  
      if (sys_verbose)
***************
*** 113,128 ****
          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);
      }
      if (inchans || outchans)
!     	err = OpenAudioStream( &pa_stream, rate, paFloat32,
!             inchans, outchans, framesperbuf, nbuffers,
!             	pa_indev, pa_outdev);
!     else err = 0;
!     if ( err != paNoError ) 
      {
!         fprintf( stderr, "Error number %d occured opening portaudio stream\n",
!             err); 
!         fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
          Pa_Terminate();
          sys_inchannels = sys_outchannels = 0;
--- 116,155 ----
          post("input device %d, channels %d", pa_indev, inchans);
          post("output device %d, channels %d", pa_outdev, outchans);
!         post("latency advance %d", advance);
      }
      if (inchans || outchans)
! 	{
! 		PaStreamParameters inputParameters, outputParameters;
! 		
! 		/* initialize input */
! 		inputParameters.device = pa_indev ;
! 		inputParameters.channelCount = inchans;
! 		inputParameters.sampleFormat = paFloat32 | paNonInterleaved;
! 		inputParameters.suggestedLatency = advance * 0.001;
! 		inputParameters.hostApiSpecificStreamInfo = NULL;
! 
! 		/* initialize output */
! 		outputParameters.device = pa_outdev;
! 		outputParameters.channelCount = outchans;
! 		outputParameters.sampleFormat = paFloat32 | paNonInterleaved;
! 		outputParameters.suggestedLatency = advance * 0.001;
! 		outputParameters.hostApiSpecificStreamInfo = NULL;
! 
! 		/* report to portaudio */
! 		err = Pa_OpenStream(&pa_stream, (inchans ? &inputParameters : 0),
! 							(outchans ? &outputParameters : 0), 
! 							rate, 
! 							sys_dacblocksize,
! 							paClipOff, /* tb: we should be faster ;-) */
! 							pa_callback, NULL);
! 	}
! 	else
! 		err = 0;
! 	
!     if ( err != paNoError )
      {
!         post("Error number %d occured opening portaudio stream\n",
!             err);
!         post("Error message: %s\n", Pa_GetErrorText( err ) );
          Pa_Terminate();
          sys_inchannels = sys_outchannels = 0;
***************
*** 133,228 ****
      pa_inchans = inchans;
      pa_outchans = outchans;
!     pa_soundin = soundin;
!     pa_soundout = soundout;
      return (0);
  }
  
  void pa_close_audio( void)
  {
      if (pa_inchans || pa_outchans)
!         CloseAudioStream( pa_stream );
      pa_inchans = pa_outchans = 0;
  }
  
  int pa_send_dacs(void)
  {
!     float *samples, *fp1, *fp2;
!     int i, j;
!     double timebefore;
  
!     samples=(float*)alloca(sizeof(float) * MAX_PA_CHANS * sys_dacblocksize);
!     
!     timebefore = sys_getrealtime();
!     if ((pa_inchans && GetAudioStreamReadable(pa_stream) < sys_dacblocksize) ||
!         (pa_outchans && GetAudioStreamWriteable(pa_stream) < sys_dacblocksize))
!     {
!         if (pa_inchans && pa_outchans)
!         {
!             int synced = 0;
!             while (GetAudioStreamWriteable(pa_stream) > 2*sys_dacblocksize)
!             {
!                 for (j = 0; j < pa_outchans; j++)
!                     for (i = 0, fp2 = samples + j; i < sys_dacblocksize; i++,
!                         fp2 += pa_outchans)
!                 {
!                     *fp2 = 0;
!                 }
!                 synced = 1;
!                 WriteAudioStream(pa_stream, samples, sys_dacblocksize);
!             }
!             while (GetAudioStreamReadable(pa_stream) > 2*sys_dacblocksize)
!             {
!                 synced = 1;
!                 ReadAudioStream(pa_stream, samples, sys_dacblocksize);
!             }
!             /* if (synced)
!                 post("sync"); */
!         }
!         return (SENDDACS_NO);
!     }
!     if (pa_inchans)
!     {
!         ReadAudioStream(pa_stream, samples, sys_dacblocksize);
!         for (j = 0, fp1 = pa_soundin; j < pa_inchans; j++, fp1 += sys_dacblocksize)
!             for (i = 0, fp2 = samples + j; i < sys_dacblocksize; i++,
!                 fp2 += pa_inchans)
!         {
!             fp1[i] = *fp2;
!         }
!     }
! #if 0 
!         {
!                 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--;
!         }
! #endif
!     if (pa_outchans)
!     {
!         for (j = 0, fp1 = pa_soundout; j < pa_outchans; j++,
!             fp1 += sys_dacblocksize)
!                 for (i = 0, fp2 = samples + j; i < sys_dacblocksize; i++,
!                     fp2 += pa_outchans)
!         {
!             *fp2 = fp1[i];
!             fp1[i] = 0;
!         }
!         WriteAudioStream(pa_stream, samples, sys_dacblocksize);
!     }
  
!     if (sys_getrealtime() > timebefore + 0.002)
!     {
!         /* post("slept"); */
!         return (SENDDACS_SLEPT);
!     }
!     else return (SENDDACS_YES);
  }
  
  
  void pa_listdevs(void)     /* lifted from pa_devs.c in portaudio */
  {
--- 160,331 ----
      pa_inchans = inchans;
      pa_outchans = outchans;
! 	
! 	err =  Pa_StartStream(pa_stream);
!     if ( err != paNoError )
!     {
!         post("Error number %d occured starting portaudio stream\n",
!             err);
!         post("Error message: %s\n", Pa_GetErrorText(err));
!         Pa_Terminate();
!         sys_inchannels = sys_outchannels = 0;
!         return (1);
!     }
! 	
! 	post("successfully started");
! 	
! 	for (j = 0; j != MAX_PA_CHANS; ++j)
! 	{
! 		if (j < inchans)
! 			pa_soundin[j] = sys_soundin + j * sys_dacblocksize;
! 		else
! 			pa_soundin[j] = 0;
! 
! 		if (j < outchans)
! 			pa_soundout[j] = sys_soundout + j * sys_dacblocksize;
! 		else
! 			pa_soundout[j] = 0;
! 	}
! 
      return (0);
  }
  
+ 
+ void sys_peakmeters(void);
+ extern int sys_meters;          /* true if we're metering */
+ 
+ int process (const void *input, void *output, unsigned long frameCount, 
+ 			 const PaStreamCallbackTimeInfo* timeInfo, 
+ 			 PaStreamCallbackFlags statusFlags, void *userData)
+ {
+ 	int i,j;
+ 	int timeout = (float)frameCount / (float) sys_dacsr * 1e6;
+ 
+ 	if (sys_timedlock(timeout) == ETIMEDOUT)
+ 		/* we're late */
+ 		return 0;
+ 
+ #if 0	
+ 	for (i = 0; i < frameCount / sys_dacblocksize; ++i)
+ 	{
+ 		for (j = 0; j < sys_inchannels; j++)
+ 		{
+ 			t_sample * in = ((t_sample**)input)[j];
+ 			copyvec(sys_soundin + j * sys_dacblocksize,
+ 					in + i * sys_dacblocksize,
+ 					sys_dacblocksize);
+ 		}
+ 
+ 		sched_tick(sys_time + sys_time_per_dsp_tick);
+ 
+ 		for (j = 0; j < sys_outchannels;  j++) 
+ 		{
+ 			t_sample * out = ((t_sample**)output)[j];
+ 			copyvec(out + i * sys_dacblocksize,
+ 					sys_soundout + j * sys_dacblocksize,
+ 					sys_dacblocksize);
+ 		}
+ 		/* update peak meters */
+ 		if (sys_meters)
+ 			sys_peakmeters();
+ 	
+ 		/* clear the output buffer */
+ 		zerovec_simd(sys_soundout, pa_outchans * sys_dacblocksize);
+ 	}
+ #else
+ 	for (j = 0; j < sys_inchannels; j++)
+ 	{
+ 		t_sample * in = ((t_sample**)input)[j];
+ 		copyvec(sys_soundin + j * sys_dacblocksize,
+ 				in,
+ 				sys_dacblocksize);
+ 	}
+ 
+ 	sched_tick(sys_time + sys_time_per_dsp_tick);
+ 	
+ 	for (j = 0; j < sys_outchannels;  j++) 
+ 	{
+ 		t_sample * out = ((t_sample**)output)[j];
+ 		copyvec(out,
+ 				sys_soundout + j * sys_dacblocksize,
+ 				sys_dacblocksize);
+ 	}
+ 	/* update peak meters */
+ 	if (sys_meters)
+ 		sys_peakmeters();
+ 	
+ 	/* clear the output buffer */
+ 		zerovec_simd(sys_soundout, pa_outchans * sys_dacblocksize);
+ 		
+ #endif
+ 	sys_unlock();
+ 
+ 	return 0;
+ 	
+ }
+ 
  void pa_close_audio( void)
  {
+ 	post("closing portaudio");
      if (pa_inchans || pa_outchans)
! 	{
! 		Pa_StopStream(pa_stream);
! 		Pa_CloseStream(pa_stream);
! 	}
! 	post("portaudio closed");
      pa_inchans = pa_outchans = 0;
  }
  
+ 
+ /* for blocked IO */
  int pa_send_dacs(void)
  {
! #ifdef PABLOCKING /* tb: blocking IO isn't really working for v19 yet */
!     double timenow, timebefore;
! 	
! 	if ( (pa_inchans && Pa_GetStreamReadAvailable(pa_stream) 
! 		  < sys_dacblocksize*0.8) &&
! 		 (pa_outchans && Pa_GetStreamWriteAvailable(pa_stream) 
! 		  < sys_dacblocksize*0.8))
! 	{
! 		/* we can't transfer data ... wait in the scheduler */
! 		return SENDDACS_NO;
! 	}
! 	
! 	timebefore = sys_getrealtime();
  
! 	if (pa_outchans)
! 		Pa_WriteStream(pa_stream, pa_soundout, sys_dacblocksize);
! 	if (pa_inchans)
! 		Pa_ReadStream(pa_stream, pa_soundin,  sys_dacblocksize);
! 	zerovec(sys_soundout, pa_inchans * sys_dacblocksize);
  
! 	while ( (pa_inchans && Pa_GetStreamReadAvailable(pa_stream) 
! 			 < sys_dacblocksize*0.8) &&
! 			(pa_outchans && Pa_GetStreamWriteAvailable(pa_stream) 
! 			 < sys_dacblocksize*0.8))
! 	{
! 		if (pa_outchans)
! 			Pa_WriteStream(pa_stream, pa_soundout, sys_dacblocksize);
! 		if (pa_inchans)
! 			Pa_ReadStream(pa_stream, pa_soundin,  sys_dacblocksize);
! 		zerovec(sys_soundout, pa_inchans * sys_dacblocksize);
! 
! 		sched_tick(sys_time + sys_time_per_dsp_tick);
! 	}
! 
! 	if ((timenow = sys_getrealtime()) - timebefore > sys_sleepgrain * 1e-6)
! 	{
! 		return SENDDACS_SLEPT;
! 	}
! 	else
! 		return SENDDACS_YES;
! #else
! 	/* we should never reach this point */
! 	return 0;
! #endif
  }
  
  
+ 
  void pa_listdevs(void)     /* lifted from pa_devs.c in portaudio */
  {
***************
*** 242,247 ****
      for( i=0; i<numDevices; i++ )
      {
!         pdi = Pa_GetDeviceInfo( i );
!         fprintf(stderr, "device %d:", i+1 );
          fprintf(stderr, " %s;", pdi->name );
          fprintf(stderr, "%d inputs, ", pdi->maxInputChannels  );
--- 345,351 ----
      for( i=0; i<numDevices; i++ )
      {
! 		PaDeviceInfo * pdi = Pa_GetDeviceInfo( i );
!         post ("device %s", pdi->name);
! 		fprintf(stderr, "device %d:", i+1 );
          fprintf(stderr, " %s;", pdi->name );
          fprintf(stderr, "%d inputs, ", pdi->maxInputChannels  );
***************
*** 265,269 ****
  
  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 ) );
--- 369,373 ----
  
  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 ) );
***************
*** 271,275 ****
  }
  
!     /* scanning for devices */
  void pa_getdevs(char *indevlist, int *nindevs,
      char *outdevlist, int *noutdevs, int *canmulti, 
--- 375,380 ----
  }
  
! 
! /* scanning for devices */
  void pa_getdevs(char *indevlist, int *nindevs,
      char *outdevlist, int *noutdevs, int *canmulti, 

Index: s_audio.c
===================================================================
RCS file: /cvsroot/pure-data/pd/src/s_audio.c,v
retrieving revision 1.5.4.12
retrieving revision 1.5.4.13
diff -C2 -d -r1.5.4.12 -r1.5.4.13
*** s_audio.c	10 May 2005 11:16:03 -0000	1.5.4.12
--- s_audio.c	11 May 2005 14:32:08 -0000	1.5.4.13
***************
*** 332,338 ****
              int blksize = (sys_blocksize ? sys_blocksize : 64);
              pa_open_audio(inchans, outchans, rate, sys_soundin, sys_soundout,
!                 blksize, sys_advance_samples/blksize,
!                     (naudiooutdev > 0 ? audioindev[0] : 0),
!                         (naudiooutdev > 0 ? audiooutdev[0] : 0));
          }
  else
--- 332,339 ----
              int blksize = (sys_blocksize ? sys_blocksize : 64);
              pa_open_audio(inchans, outchans, rate, sys_soundin, sys_soundout,
! 						  advance, 
! 						  (naudiooutdev > 0 ? audioindev[0] : 0),
! 						  (naudiooutdev > 0 ? audiooutdev[0] : 0),
! 						  schedmode);
          }
  else

Index: s_stuff.h
===================================================================
RCS file: /cvsroot/pure-data/pd/src/s_stuff.h,v
retrieving revision 1.5.4.5
retrieving revision 1.5.4.6
diff -C2 -d -r1.5.4.5 -r1.5.4.6
*** s_stuff.h	8 Apr 2005 12:45:25 -0000	1.5.4.5
--- s_stuff.h	11 May 2005 14:32:09 -0000	1.5.4.6
***************
*** 202,207 ****
  
  int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin,
!     t_sample *soundout, int framesperbuf, int nbuffers,
!     int indeviceno, int outdeviceno);
  void pa_close_audio(void);
  int pa_send_dacs(void);
--- 202,207 ----
  
  int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin,
!     t_sample *soundout, int advance, 
!     int indeviceno, int outdeviceno, int schedmode)
  void pa_close_audio(void);
  int pa_send_dacs(void);





More information about the Pd-cvs mailing list