[PD-cvs] pd/src s_audio_asio.cpp,1.1.4.14,1.1.4.15

Tim Blechmann timblech at users.sourceforge.net
Wed Nov 24 00:08:58 CET 2004


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

Modified Files:
      Tag: devel_0_38
	s_audio_asio.cpp 
Log Message:
callback-based scheduling

Index: s_audio_asio.cpp
===================================================================
RCS file: /cvsroot/pure-data/pd/src/Attic/s_audio_asio.cpp,v
retrieving revision 1.1.4.14
retrieving revision 1.1.4.15
diff -C2 -d -r1.1.4.14 -r1.1.4.15
*** s_audio_asio.cpp	18 Nov 2004 22:50:44 -0000	1.1.4.14
--- s_audio_asio.cpp	23 Nov 2004 23:08:53 -0000	1.1.4.15
***************
*** 65,69 ****
  extern "C" int asio_send_dacs(void);
  
! /* asio callback prototypes */
  static void asio_bufferSwitch(long db_idx, ASIOBool directprocess);
  static void asio_sampleRateDidChange(ASIOSampleRate srate);
--- 65,69 ----
  extern "C" int asio_send_dacs(void);
  
! /* asio callback prototypes for traditional scheduling*/
  static void asio_bufferSwitch(long db_idx, ASIOBool directprocess);
  static void asio_sampleRateDidChange(ASIOSampleRate srate);
***************
*** 72,75 ****
--- 72,83 ----
  									ASIOBool directprocess);
  
+ /* asio callback prototypes for callback-based scheduling*/
+ static void asio_bufferSwitch_cb(long db_idx, ASIOBool directprocess);
+ static void asio_sampleRateDidChange_cb(ASIOSampleRate srate);
+ static long asio_messages_cb(long selector, long value, void* message, double* opt);
+ static ASIOTime *asio_bufferSwitchTimeInfo_cb(ASIOTime *params, long db_idx, 
+ 									ASIOBool directprocess);
+ 
+ 
  static void float32tofloat32(void* inbuffer, void* outbuffer, long frames);
  static void float32tofloat32_S(void* inbuffer, void* outbuffer, long frames);
***************
*** 103,106 ****
--- 111,116 ----
  static int asio_samplewidth(ASIOSampleType format);
  
+ 
+ 
  /* that's the sample width in bytes (per output channel) - 
   * it's only for silence when stopping the driver.... (please find a better solution)
***************
*** 137,141 ****
  static long asio_outputlatency;
  
! static long asio_bufsize;
  
  unsigned long sys_reftime;
--- 147,151 ----
  static long asio_outputlatency;
  
! static long asio_bufsize;                /* hardware buffer size */
  
  unsigned long sys_reftime;
***************
*** 158,161 ****
--- 168,189 ----
  #define MAXNDEV   20
  
+ /* from m_sched.c: */
+ extern "C" int sys_keepsched;
+ extern "C" int sys_callbackscheduler;
+ extern "C" double sys_time_per_dsp_tick;
+ extern "C" double sys_time;
+ 
+ 
+ /**************************************************************************/
+ /* some function pointers for eventual fast copying when SIMD is possible */
+ 
+ static void (*copyblock)(t_sample *dst,t_sample *src,int n);
+ static void (*zeroblock)(t_sample *dst,int n);
+ static t_int *(*clipblock)(t_int *w);
+ 
+ static void copyvec_nrm(t_sample *dst,t_sample *src,int n) { memcpy(dst,src,n*sizeof(t_sample)); }
+ static void zerovec_nrm(t_sample *dst,int n) { memset(dst,0,n*sizeof(t_sample)); }
+ 
+ /*************************************************************************/
  
  
***************
*** 176,179 ****
--- 204,208 ----
  	sprintf(asio_srate,"%d",srate);
  #endif
+ 
  	
  	/* check, if the driver is still running */
***************
*** 269,272 ****
--- 298,310 ----
  	asio_bufsize = asio_prefbufsize; 
  
+ #ifdef CALLBACK_SCHEDULER
+ 	if (asio_bufsize % 2 == 0)
+ 	{
+ 		/* use callback scheduler */
+ 		sys_keepsched = 0;
+ 		sys_callbackscheduler = 1;
+ 	}
+ #endif
+ 
  	/* set sample rate */
  	if(ASIOCanSampleRate( asio_srate ) != ASE_OK)
***************
*** 292,300 ****
  
  	/* set callbacks */
! 	asio_callbacks.bufferSwitch = &asio_bufferSwitch;
! 	asio_callbacks.sampleRateDidChange = &asio_sampleRateDidChange;
! 	asio_callbacks.asioMessage = &asio_messages;
! 	asio_callbacks.bufferSwitchTimeInfo = &asio_bufferSwitchTimeInfo;
! 
  
  	/* prepare, create and set up buffers */
--- 330,349 ----
  
  	/* set callbacks */
! 	if(sys_callbackscheduler)
! 	{
! 		asio_callbacks.bufferSwitch = &asio_bufferSwitch_cb;
! 		asio_callbacks.sampleRateDidChange = &asio_sampleRateDidChange_cb;
! 		asio_callbacks.asioMessage = &asio_messages_cb;
! 		asio_callbacks.bufferSwitchTimeInfo = &asio_bufferSwitchTimeInfo_cb;
! 	}
! 	else
! 	{
! 		asio_callbacks.bufferSwitch = &asio_bufferSwitch;
! 		asio_callbacks.sampleRateDidChange = &asio_sampleRateDidChange;
! 		asio_callbacks.asioMessage = &asio_messages;
! 		asio_callbacks.bufferSwitchTimeInfo = &asio_bufferSwitchTimeInfo;
! 	}
! 		
! 	
  
  	/* prepare, create and set up buffers */
***************
*** 321,330 ****
  			asio_bufferinfo[i].isInput = ASIOTrue;
  			asio_bufferinfo[i].channelNum = i - sys_outchannels;
  		}
  	}
  	
  	status = ASIOCreateBuffers(asio_bufferinfo, sys_inchannels + sys_outchannels,
! 						  asio_bufsize, &asio_callbacks);
! 
  	if(status != ASE_OK)
  	{
--- 370,380 ----
  			asio_bufferinfo[i].isInput = ASIOTrue;
  			asio_bufferinfo[i].channelNum = i - sys_outchannels;
+ 			asio_bufferinfo[i].buffers[0] = asio_bufferinfo[i].buffers[1] = 0;
  		}
  	}
  	
  	status = ASIOCreateBuffers(asio_bufferinfo, sys_inchannels + sys_outchannels,
! 							   asio_bufsize, &asio_callbacks);
! 	
  	if(status != ASE_OK)
  	{
***************
*** 361,396 ****
  
  
! 	/* calculate ringbuffer length */
! 	/* a strange way to find the least common multiple, 
! 	 * but works, since sys_dacblocksize (expt 2 x)        */
! 
! 	asio_ringbuffer_length = asio_bufsize * sys_dacblocksize;
! 	while ( !(asio_ringbuffer_length % sys_dacblocksize) && 
! 			!(asio_ringbuffer_length % asio_bufsize))
! 	{
! 		asio_ringbuffer_length /= 2;
! 	}
! 	asio_ringbuffer_length *= 2;
! 
  #ifdef ASIODEBUG
! 	post("ASIO: ringbuffer size: %d",asio_ringbuffer_length);
  #endif
! 	
! 	
! 	/* allocate ringbuffer */
! 	asio_ringbuffer = (t_sample**) getbytes (channels * sizeof (t_sample*));
! 	for (i = 0; i != channels; ++i)
! 	{	
! 		asio_ringbuffer[i] = (t_sample*)getalignedbytes(asio_ringbuffer_length * sizeof (t_sample));
! 		if (!asio_ringbuffer[i])
! 			error("ASIO: couldn't allocate ASIO ringbuffer");
! 		memset(asio_ringbuffer[i], 0, asio_ringbuffer_length * sizeof (t_sample));
  	}
  	
- 	/* initialize ringbuffer pointers */
- 	asio_ringbuffer_inoffset = asio_ringbuffer_outoffset = 0;
- 
      if(ASIOStart() != ASE_OK) goto bailout;
  
  	post("ASIO: started");
      return;
--- 411,463 ----
  
  
! 	/* we need a ringbuffer if we use the traditional scheduler */
! 	if (!sys_callbackscheduler)
! 	{	
! 		/* a strange way to find the least common multiple, 
! 		 * but works, since sys_dacblocksize (expt 2 x)        */
! 		asio_ringbuffer_length = asio_bufsize * sys_dacblocksize;
! 		while ( !(asio_ringbuffer_length % sys_dacblocksize) && 
! 				!(asio_ringbuffer_length % asio_bufsize))
! 		{
! 			asio_ringbuffer_length /= 2;
! 		}
! 		asio_ringbuffer_length *= 2;
! 		
  #ifdef ASIODEBUG
! 		post("ASIO: ringbuffer size: %d",asio_ringbuffer_length);
  #endif
! 		
! 		/* allocate ringbuffer */
! 		asio_ringbuffer = (t_sample**) getbytes (channels * sizeof (t_sample*));
! 		for (i = 0; i != channels; ++i)
! 		{	
! 			asio_ringbuffer[i] = (t_sample*)getalignedbytes(asio_ringbuffer_length * sizeof (t_sample));
! 			if (!asio_ringbuffer[i])
! 				error("ASIO: couldn't allocate ASIO ringbuffer");
! 			memset(asio_ringbuffer[i], 0, asio_ringbuffer_length * sizeof (t_sample));
! 		}
! 		
! 		/* initialize ringbuffer pointers */
! 		asio_ringbuffer_inoffset = asio_ringbuffer_outoffset = 0;
  	}
  	
      if(ASIOStart() != ASE_OK) goto bailout;
  
+ 
+ 	/* set block copy/zero/clip functions */
+     if(SIMD_CHKCNT(sys_dacblocksize) && simd_runtime_check()) 
+ 	{
+         // urgh... ugly cast
+         copyblock = (void (*)(t_sample *,t_sample *,int))&copyvec_simd;
+         zeroblock = &zerovec_simd;
+         clipblock = &clip_perf_simd;
+     }
+     else 
+ 	{
+         copyblock = &copyvec_nrm;
+         zeroblock = &zerovec_nrm;
+         clipblock = &clip_perform;
+     }
+ 
  	post("ASIO: started");
      return;
***************
*** 495,498 ****
--- 562,571 ----
  		freebytes(asio_driver, sizeof (ASIODriverInfo));
  		asio_driver = NULL;
+ 		
+ 		/* leave the scheduler and return to traditional mode */
+ 		if (sys_callbackscheduler)
+ 		{
+ 			sys_callbackscheduler = sys_keepsched = 0;
+ 		}
  	}
  }
***************
*** 516,549 ****
  }
  
- /**************************************************************************/
- /* some function pointers for eventual fast copying when SIMD is possible */
- 
- static void copyvec_nrm(t_sample *dst,t_sample *src,int n) { memcpy(dst,src,n*sizeof(t_sample)); }
- static void zerovec_nrm(t_sample *dst,int n) { memset(dst,0,n*sizeof(t_sample)); }
- 
- /*************************************************************************/
- 
  /* called on every dac~ send */      
  int asio_send_dacs(void)
  {
-     /* set block copy/zero/clip functions */
-     void (*copyblock)(t_sample *dst,t_sample *src,int n);
-     void (*zeroblock)(t_sample *dst,int n);
-     t_int *(*clipblock)(t_int *w);
- 
-     if(SIMD_CHKCNT(sys_dacblocksize)) {
-         // urgh... ugly cast
-         copyblock = (void (*)(t_sample *,t_sample *,int))&copyvec_simd;
-         zeroblock = &zerovec_simd;
-         clipblock = &clip_perf_simd;
-     }
-     else {
-         copyblock = &copyvec_nrm;
-         zeroblock = &zerovec_nrm;
-         clipblock = &clip_perform;
-     }
- 
-     /*************************************/
- 
  	t_sample * sp; /* sample pointer */
  	int i, j;
--- 589,595 ----
***************
*** 564,569 ****
      for (i = 0; i < sys_outchannels; i++)
  	{
- 		/* clipping here, we are sure, we can use simd instructions */
-         /* TG: are we? can sys_dacblocksize be < 16, with onset and size then not SIMD-able? */
  		t_float lo = -1.f;
  		t_float hi = 1.f;
--- 610,613 ----
***************
*** 710,715 ****
  									ASIOBool directprocess)
  {
- 	long i, j;	
- 
  	/* todo: i'm not sure if we'll have to synchronize with other media ...
  	 * probably yes ... */
--- 754,757 ----
***************
*** 719,723 ****
  	/* perform the processing */ 
  
! 	for (i = 0; i < sys_outchannels + sys_inchannels; i++)
  	{
          if(asio_converter[i])
--- 761,765 ----
  	/* perform the processing */ 
  
! 	for (long i = 0; i < sys_outchannels + sys_inchannels; i++)
  	{
          if(asio_converter[i])
***************
*** 1014,1018 ****
  	while (frames--)
  	{
!         float o = *(in++) * SCALE_INT24 + triangulardither() * DITHER_SCALE;
  #ifdef __GNUC__
  		__int32 intg = (__int32)lrintf(o);
--- 1056,1060 ----
  	while (frames--)
  	{
!         float o = *(in++) * SCALE_INT24;
  #ifdef __GNUC__
  		__int32 intg = (__int32)lrintf(o);
***************
*** 1101,1105 ****
  	while (frames--)
  	{
!         float o = (float)*(in++) * SCALE_INT24 + triangulardither() * DITHER_SCALE;
  #ifdef __GNUC__
  		__int32 reverse = (__int32)lrintf(o);
--- 1143,1147 ----
  	while (frames--)
  	{
!         float o = (float)*(in++) * SCALE_INT24;
  #ifdef __GNUC__
  		__int32 reverse = (__int32)lrintf(o);
***************
*** 1179,1182 ****
--- 1221,1313 ----
  
  
+ 
+ /* callback-based scheduling callbacks: */
+ 
+ /* buffer switch callback */
+ static void asio_bufferSwitch_cb(long db_idx, ASIOBool directprocess)
+ {
+ 	ASIOTime time;
+ 	memset (&time, 0, sizeof (time));
+ 	/* todo: do we need to syncronize with other media ??? */
+ 	asio_bufferSwitchTimeInfo_cb(&time, db_idx, directprocess);
+ }
+ 
+ /* sample rate change callback */
+ static void asio_sampleRateDidChange_cb(ASIOSampleRate srate)
+ {
+ 	asio_sampleRateDidChange(srate);
+ }
+ 
+ /* asio messaging callback */
+ static long asio_messages_cb(long selector, long value, void* message, double* opt)
+ {
+ 	return asio_messages(selector, value, message, opt);
+ }
+ 
+ static ASIOTime *asio_bufferSwitchTimeInfo_cb(ASIOTime *params, long db_idx, 
+ 									ASIOBool directprocess)
+ {
+ 	/* todo: i'm not sure if we'll have to synchronize with other media ...
+ 	 * probably yes ... */
+ 		
+ 	/* perform the processing */ 
+ 	
+ 	sys_lock();
+ 	
+ 	for (int j = 0; j < asio_bufsize; j += sys_dacblocksize)
+ 	{
+ 		/* get sounds from input channels */
+ 		for (long i = 0; i < sys_outchannels + sys_inchannels; i++)
+ 		{
+ 			t_sample * sp = sys_soundin;
+ 			
+ 			if(asio_converter[i])
+ 				if (asio_bufferinfo[i].isInput == ASIOTrue)
+ 				{
+ 					asio_converter[i](asio_bufferinfo[i].buffers[db_idx],
+ 									  sp, sys_dacblocksize);
+ 					sp += sys_dacblocksize;
+ 				}
+ 			
+ 		}
+ 		
+ 		/* run dsp */
+ 		sched_tick(sys_time + sys_time_per_dsp_tick);
+ 		
+ 		/* send sound to hardware */
+ 		for (long i = 0; i < sys_outchannels + sys_inchannels; i++)
+ 		{
+ 			t_sample * sp = sys_soundout;
+ 			
+ 			/* clip */
+ 			t_float lo = -1.f;
+ 			t_float hi = 1.f;
+ 			t_int clipargs[6];
+ 			clipargs[1] = clipargs[2] = (t_int)sp;
+ 			clipargs[3] = (t_int)&lo;
+ 			clipargs[4] = (t_int)&hi;
+ 			clipargs[5] = (t_int)sys_dacblocksize;
+ 			clipblock(clipargs);
+ 			
+ 			/* send */
+ 			if(asio_converter[i])
+ 				if (asio_bufferinfo[i].isInput != ASIOTrue)
+ 				{
+ 					asio_converter[i](sp, asio_bufferinfo[i].buffers[db_idx],
+ 									  sys_dacblocksize);
+ 					sp += sys_dacblocksize;
+ 				}
+ 		}
+ 	}
+ 	sys_unlock();
+ 
+ 	if(asio_useoutputready)
+ 		ASIOOutputReady();
+ 
+     return 0L; /* time info!!! */
+ }
+ 
+ 
+ 
  #endif /* USEAPI_ASIO */
  





More information about the Pd-cvs mailing list