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))©vec_simd;
+ zeroblock = &zerovec_simd;
+ clipblock = &clip_perf_simd;
+ }
+ else
+ {
+ copyblock = ©vec_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))©vec_simd;
- zeroblock = &zerovec_simd;
- clipblock = &clip_perf_simd;
- }
- else {
- copyblock = ©vec_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 */