[PD-cvs] pd/src s_audio_asio.cpp,NONE,1.1.2.1 s_stuff.h,1.1.1.1.2.6,1.1.1.1.2.7 s_audio.c,1.1.1.1.2.11,1.1.1.1.2.12 s_main.c,1.1.1.4.2.21,1.1.1.4.2.22 makefile.nt,1.1.1.3.2.4,1.1.1.3.2.5

Tim Blechmann timblech at users.sourceforge.net
Thu Nov 4 21:22:47 CET 2004


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

Modified Files:
      Tag: devel_0_37
	s_stuff.h s_audio.c s_main.c makefile.nt 
Added Files:
      Tag: devel_0_37
	s_audio_asio.cpp 
Log Message:
native asio support

Index: s_audio.c
===================================================================
RCS file: /cvsroot/pure-data/pd/src/s_audio.c,v
retrieving revision 1.1.1.1.2.11
retrieving revision 1.1.1.1.2.12
diff -C2 -d -r1.1.1.1.2.11 -r1.1.1.1.2.12
*** s_audio.c	9 Oct 2004 11:58:22 -0000	1.1.1.1.2.11
--- s_audio.c	4 Nov 2004 20:22:44 -0000	1.1.1.1.2.12
***************
*** 331,334 ****
--- 331,340 ----
  	else
  #endif
+ #ifdef USEAPI_ASIO
+ 	if (sys_audioapi == API_ASIO)
+ 	    asio_open_audio(naudioindev, audioindev, nchindev, chindev,
+     		    naudiooutdev, audiooutdev, nchoutdev, choutdev, rate);
+ 	else
+ #endif
      	    post("unknown audio API specified");
      }
***************
*** 371,374 ****
--- 377,385 ----
      else
  #endif
+ #ifdef USEAPI_ASIO
+     if (sys_audioapi == API_ASIO)
+     	asio_close_audio();
+     else
+ #endif
      	post("sys_close_audio: unknown API %d", sys_audioapi);
      sys_inchannels = sys_outchannels = 0;
***************
*** 436,439 ****
--- 447,455 ----
      else
  #endif
+ #ifdef USEAPI_ASIO
+     if (sys_audioapi == API_ASIO)
+     	return (asio_send_dacs());
+     else
+ #endif
      post("unknown API");    
      return (0);
***************
*** 528,531 ****
--- 544,555 ----
      else
  #endif
+ #ifdef USEAPI_ASIO
+     if (sys_audioapi == API_ASIO)
+     {
+     	asio_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti,
+ 	    maxndev, devdescsize);
+     }
+     else
+ #endif
      {
      	    /* this shouldn't happen once all the above get filled in. */
***************
*** 811,814 ****
--- 835,841 ----
      sprintf(buf + strlen(buf), "{OSS %d} ", API_OSS); n++;
  #endif
+ #ifdef USEAPI_ASIO
+     sprintf(buf + strlen(buf), "{ASIO %d} ", API_ASIO); n++;
+ #endif
  #ifdef USEAPI_MMIO
      sprintf(buf + strlen(buf), "{\"standard (MMIO)\" %d} ", API_MMIO); n++;

--- NEW FILE: s_audio_asio.cpp ---
/* Copyright (c) 2004, Tim Blechmann and others
 * For information on usage and redistribution, and for a DISCLAIMER OF ALL
 * WARRANTIES, see the file, "LICENSE.txt" in this distribution.  */

/* native ASIO interface for windows and mac osx 
 * adapted from hostsample.cpp (ASIO SDK)
 */

#ifdef USEAPI_ASIO

#ifdef MSW
#include "windows.h" /* for application window handle */
#define IEEE754_64FLOAT 1
#endif

#include "m_pd.h"
extern "C" {
#include "s_stuff.h"
}
#include "asio.h"     /* steinberg's header file */
#include "asiodrivers.h" /* ASIODrivers class */
#include "asiosys.h"
#include "pthread.h"
#include "stdio.h" /* for sprintf */

#define ASIODEBUG

/* public function prototypes */
extern "C" void asio_open_audio(int naudioindev, int *audioindev, int nchindev, 
					 int *chindev, int naudiooutdev, int *audiooutdev,
					 int nchoutdev, int *choutdev, int srate);
extern "C" void asio_close_audio(void);
extern "C" void asio_getdevs(char *indevlist, int *nindevs,
				  char *outdevlist, int *noutdevs, int *canmulti, 
				  int maxndev, int devdescsize);
extern "C" int asio_send_dacs(void);

/* asio callback prototypes */
void asio_bufferSwitch(long db_idx, ASIOBool directprocess);
void asio_sampleRateDidChange(ASIOSampleRate srate);
long asio_messages(long selector, long value, void* message, double* opt);
ASIOTime *asio_bufferSwitchTimeInfo(ASIOTime *params, long db_idx, 
									ASIOBool directprocess);

/* sample converting helper functions:
 * - global send / receive functions
 * - sample conversion functions (adapted from ASIOConvertSamples.cpp */
void asio_convert_and_send (t_sample* source, void* dest, 
							ASIOSampleType format, long asio_bufsize);
void asio_convert_and_receive (void* source, t_sample* dest, 
							   ASIOSampleType format, long asio_bufsize);
void float32toInt16(float* inbuffer, void* outbuffer, long frames);
void Int16tofloat32(void* inbuffer, float* outbuffer, long frames);
void float32toInt32(float* inbuffer, void* outbuffer, long frames);
void Int32tofloat32(void* inbuffer, float* outbuffer, long frames);

/* some local helper functions */
inline void prepare_asio_drivernames(void);

/* system dependent helper functions */
static unsigned long get_sys_reference_time(void);

/* global storage */
ASIODriverInfo * asio_driver = NULL;
ASIOBufferInfo * asio_bufferinfo;
ASIOChannelInfo* asio_channelinfo;
AsioTimeInfo   * asio_timerinfo;
ASIOCallbacks    asio_callbacks;
extern AsioDrivers * asioDrivers; /* declared in asiodrivers.cpp */

char ** asio_drivernames = NULL;

ASIOSampleRate asio_srate;
long asio_inchannels;
long asio_outchannels;

long asio_minbufsize;
long asio_maxbufsize;
long asio_prefbufsize;
long asio_granularity;
unsigned char asio_useoutputready;
long asio_inputlatency;
long asio_outputlatency;

long asio_bufsize;

unsigned long sys_reftime;

/* ringbuffer stuff */
t_sample ** asio_ringbuffer;                   /* ringbuffers */
static int asio_ringbuffer_inoffset;     /* ringbuffer(in) pointer offset for dac */
static int asio_ringbuffer_outoffset;    /* ringbuffer(out) pointer offset */
static int asio_ringbuffer_length;       /* latency - hardware latency in samples*/

/* i hope we can remove this to use callback based dsp scheduling */
static pthread_mutex_t asio_ringbuf_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t asio_ringbuf_cond = PTHREAD_COND_INITIALIZER;

/* definitions from s_audio.c ... it should be save to use them */
#define DEVDESCSIZE   80
#define MAXNDEV   20

/* open asio interface */
/* todo: some more error messages */
void asio_open_audio(int naudioindev, int *audioindev, int nchindev, 
					 int *chindev, int naudiooutdev, int *audiooutdev,
					 int nchoutdev, int *choutdev, int srate)
{
	ASIOError status;
	ASIOBufferInfo * buffers;
	int i;
	int channels;

#ifdef IEEE754_64FLOAT
	asio_srate=(ASIOSampleRate)srate;
#else
	sprintf(asio_srate,"%d",srate);
#endif
	

	/* check, if we use the first asio device */
	prepare_asio_drivernames();
	
	/* load the driver  */
	if (!asioDrivers)
		asioDrivers = new AsioDrivers();
	
	/* check, if the driver is still running */
	if (asio_driver)
		asio_close_audio();

	asioDrivers->getDriverNames(asio_drivernames,MAXNDEV);

	asioDrivers->loadDriver(asio_drivernames[*audioindev]);



	/* initialize ASIO */
	asio_driver = (ASIODriverInfo*) getbytes (sizeof(ASIODriverInfo));
	asio_driver->asioVersion = 2; /* i hope we are compatible with asio 2 */
	
#ifdef MSW
	asio_driver->sysRef = GetDesktopWindow();
#else
	asio_driver->sysRef = 0;
#endif
	
	status = ASIOInit(asio_driver);
	
#ifdef ASIODEBUG
	post("sysRef: %x", asio_driver->sysRef);
	post("asioversion: %d", asio_driver->asioVersion);
	post("driverversion: %d", asio_driver->driverVersion);
	post("name: %s", asio_driver->name);
	post("error: %s", asio_driver->errorMessage);
#endif

	switch (status)
	{
	case ASE_NotPresent:
		error("ASIO: ASE_NotPresent");
		freebytes(asio_driver, sizeof (ASIODriverInfo));
		asio_driver = NULL;
		return;
 	case ASE_NoMemory:
		error("ASIO: ASE_NoMemory");
		freebytes(asio_driver, sizeof (ASIODriverInfo));
		asio_driver = NULL;
		return;
 	case ASE_HWMalfunction:
		error("ASIO: ASE_HWMalfunction");
		freebytes(asio_driver, sizeof (ASIODriverInfo));
		asio_driver = NULL;
		return;
	}
	post("ASIO initialized successfully");
	


	/* query driver */
	ASIOGetChannels(&asio_inchannels, &asio_outchannels);
	post ("ASIOGetChannels\tinputs: %d, outputs: %d", asio_inchannels,
		  asio_outchannels);

	/* tb: todo: channel count hardcoded to asio hardware */
	sys_inchannels = *chindev <= asio_inchannels ? *chindev : asio_inchannels;
	sys_outchannels = *choutdev <= asio_outchannels ? *choutdev : asio_outchannels;
	channels = sys_inchannels + sys_outchannels;
	

	ASIOGetBufferSize(&asio_minbufsize, &asio_maxbufsize, &asio_prefbufsize,
					  &asio_granularity);
	post ("ASIOGetBufferSize\tmin: %d, max: %d, preferred: %d, granularity: "
		  "%d", asio_minbufsize, asio_maxbufsize, asio_prefbufsize,
		  asio_granularity);

	/* todo: buffer size hardcoded to asio hardware */
	asio_bufsize = asio_prefbufsize; 

	/* set sample rate */
	if (ASIOCanSampleRate( asio_srate ) != ASE_OK)
	{
		error ("Samplerate not supported, using default");
#ifdef IEEE754_64FLOAT
		asio_srate = (ASIOSampleRate)44100.0;
#else
		sprintf(&asio_srate,"%d",44100);
#endif
		srate=44100;
	}
	ASIOSetSampleRate( asio_srate );
	post ("ASIOSetSampleRate\t %d", srate);
	
	if (ASIOOutputReady() == ASE_OK)
		asio_useoutputready = 1;
	else
		asio_useoutputready = 0;


	/* 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 */
	asio_bufferinfo  = (ASIOBufferInfo*) getbytes (channels * sizeof (ASIOBufferInfo));
	asio_channelinfo = (ASIOChannelInfo*)  getbytes(channels * sizeof (ASIOChannelInfo));
	if (!(asio_bufferinfo && asio_channelinfo))
	{
		error("ASIO: couldn't allocate buffer or channel info");
		if (asio_bufferinfo)
			freebytes(asio_bufferinfo, channels * sizeof (ASIOBufferInfo));
		if (asio_channelinfo)
			freebytes(asio_channelinfo, channels * sizeof (ASIOChannelInfo));
		return;
	}

	for (i = 0; i != sys_inchannels + sys_outchannels; ++i)
	{
		if (i < sys_outchannels)
		{
			asio_bufferinfo[i].isInput = ASIOFalse;
			asio_bufferinfo[i].channelNum = i;
			asio_bufferinfo[i].buffers[0] = asio_bufferinfo[i].buffers[1] = 0;
		}
		else
		{
			asio_bufferinfo[i].isInput = ASIOTrue;
			asio_bufferinfo[i].channelNum = i - sys_outchannels;
		}
	}
	
	if (ASIOCreateBuffers(asio_bufferinfo, sys_inchannels + sys_outchannels,
						  asio_bufsize, &asio_callbacks)	
		== ASE_OK)
	{
		post("ASIO: buffers allocated");
	}
	else
	{
		error("ASIO: couldn't allocate buffers");
		return;
	}

	for (i = 0; i != sys_inchannels + sys_outchannels; ++i)
	{
		asio_channelinfo[i].channel = asio_bufferinfo[i].channelNum;
		asio_channelinfo[i].isInput = asio_bufferinfo[i].isInput;
		ASIOGetChannelInfo(&asio_channelinfo[i]);
	}


	/* get latencies */
	ASIOGetLatencies(&asio_inputlatency, &asio_outputlatency);
#ifdef ASIODEBUG
	post("ASIO: input latency: %d, output latency: %d",asio_inputlatency, 
		 asio_outputlatency);
#endif


	/* calculate ringbuffer length */
	asio_ringbuffer_length = asio_bufsize * DEFDACBLKSIZE;
	
	/* a strange way to find the least common multiple, 
	 * but works, since DEFDACBLKSIZE (expt 2 x)        */
	while ( !(asio_ringbuffer_length % DEFDACBLKSIZE) && 
			!(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*)getbytes(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 stuff */
	asio_ringbuffer_inoffset = asio_ringbuffer_outoffset = 0;

	if (ASIOStart() == ASE_OK)
	{
		post("ASIO: started");
	}
	else
		post("ASIO: couldn't start");
	
	return;
}



/* stop asio, free buffers and close asio interface */
void asio_close_audio(void)
{
	ASIOError status;
	int channels = asio_inchannels + asio_outchannels;
	int i;

	pthread_cond_broadcast(&asio_ringbuf_cond);

	ASIOStop();

	if (asio_driver)
	{
		for (i = 0; i != channels; i++)
			freebytes(asio_ringbuffer[i], asio_ringbuffer_length * sizeof (t_sample));
		freebytes(asio_ringbuffer, channels * sizeof (t_sample *));
		freebytes(asio_bufferinfo, channels * sizeof (ASIOBufferInfo));
		freebytes(asio_channelinfo, channels * sizeof (ASIOChannelInfo));
		ASIODisposeBuffers();
		
		asio_ringbuffer = NULL;
		asio_bufferinfo = NULL;
		asio_channelinfo = NULL;
		
		ASIOExit();
		freebytes(asio_driver, sizeof (ASIODriverInfo));
		asio_driver = NULL;
	}
	return;
}


void asio_getdevs(char *indevlist, int *nindevs,
				  char *outdevlist, int *noutdevs, int *canmulti, 
				  int maxndev, int devdescsize)
{
	prepare_asio_drivernames();

	*canmulti = 0; /* we will only support one asio device */
	*nindevs = *noutdevs = (int)asioDrivers->getDriverNames(asio_drivernames,
															maxndev);
	
	for(int i = 0; i!= *nindevs; ++i)
	{
		sprintf(indevlist  + i * devdescsize, "%s", asio_drivernames[i]);
		sprintf(outdevlist + i * devdescsize, "%s", asio_drivernames[i]);
	}
}



/* called on every dac~ send
 * todo: 
 * - use vectorized functions 
 * - function pointer to avoid segfaults */      
int asio_send_dacs(void)
{
	t_sample * sp; /* sample pointer */
	int i, j;
	int timenow;
	int timeref = sys_getrealtime();
#ifdef ASIODEBUG
	if (!asio_driver)
	{
		error("ASIO not running");
		return SENDDACS_NO;
	}
#endif



	/* send sound to ringbuffer */
	sp = sys_soundout;
	for (i = 0; i < sys_outchannels; i++)
	{
		memcpy(asio_ringbuffer[i] + asio_ringbuffer_inoffset, sp,
			   DEFDACBLKSIZE*sizeof(t_sample));
		memset(sp, 0, DEFDACBLKSIZE*sizeof(t_sample));
		sp+=DEFDACBLKSIZE;
	}
	
	/* get sound from ringbuffer */
	sp = sys_soundin;
	for (j = 0; j < sys_inchannels; j++)
 	{
		memcpy(sp, asio_ringbuffer[i+j] + asio_ringbuffer_inoffset,
			   DEFDACBLKSIZE*sizeof(t_sample));
		sp+=DEFDACBLKSIZE;
	}
	
	asio_ringbuffer_inoffset += DEFDACBLKSIZE;

	
	if (asio_ringbuffer_inoffset >= asio_ringbuffer_outoffset + asio_bufsize)
	{
		pthread_cond_wait(&asio_ringbuf_cond, &asio_ringbuf_mutex);
		if (asio_ringbuffer_inoffset == asio_ringbuffer_length)
		{
			asio_ringbuffer_outoffset = 0;
			asio_ringbuffer_inoffset = 0;
		}
		else
			asio_ringbuffer_outoffset += asio_bufsize;
	}
	
	if ((timenow = sys_getrealtime()) - timeref > 0.002)
	{
		return SENDDACS_SLEPT;
	}
	return SENDDACS_YES;
}


/* buffer switch callback */
void asio_bufferSwitch(long db_idx, ASIOBool directprocess)
{
	ASIOTime time;
	memset (&time, 0, sizeof (time));
	/* todo: do we need to syncronize with other media ??? */
	asio_bufferSwitchTimeInfo(&time, db_idx, directprocess);
}

/* sample rate change callback */
void asio_sampleRateDidChange(ASIOSampleRate srate)
{
	asio_srate = srate;
#ifdef ASIODEBUG
	post("sample rate changed");
#endif
}

/* asio messaging callback */
long asio_messages(long selector, long value, void* message, double* opt)
{
	/* todo */
	return 0L;
}

ASIOTime *asio_bufferSwitchTimeInfo(ASIOTime *params, long db_idx, 
									ASIOBool directprocess)
{
	long i, j;	



	// todo: store the timeInfo for later use


	/* todo: i'm not sure if we'll have to synchronize with other media ...
	 * probably yes ... */
		
	/* 	sys_reftime = get_sys_reference_time(); */

	/* perform the processing 
	 * todo: improve input latency
	 */
	for (i = 0; i < asio_outchannels + asio_inchannels; i++)
	{
		if (asio_bufferinfo[i].isInput != ASIOTrue)
		{
			asio_convert_and_send(asio_ringbuffer[i]+asio_ringbuffer_outoffset,
								  (void*) asio_bufferinfo[i].buffers[db_idx],
								  asio_channelinfo[i].type, asio_bufsize);
		}
		else /* these are the input channels */
		{
			asio_convert_and_receive((void*)asio_bufferinfo[i].buffers[db_idx],
									 asio_ringbuffer[i]+asio_ringbuffer_outoffset,
									 asio_channelinfo[i].type, asio_bufsize);
		}
			
	}
	pthread_cond_broadcast(&asio_ringbuf_cond);

	if(asio_useoutputready)
		ASIOOutputReady();
	


	return 0L; /* time info!!! */
}


/* get system reference time on both platforms */
static unsigned long get_sys_reference_time()
{	
#if WINDOWS
	return timeGetTime();
#elif MAC
	static const double twoRaisedTo32 = 4294967296.;
	UnsignedWide ys;
	Microseconds(&ys);
	double r = ((double)ys.hi * twoRaisedTo32 + (double)ys.lo);
	return (unsigned long)(r / 1000.);
#endif
}

/* sample converting helper functions */
void asio_convert_and_send(t_sample* source, void* dest, ASIOSampleType format, long bufsize)
{

#ifdef ASIODEBUG
/* 	post("ASIO: Sample Type %d", format); */
#endif
	switch (format)
	{
	case ASIOSTInt16LSB:
		/* e.g. m audio quattro */
		float32toInt16(source, dest, bufsize);		
		break;
	case ASIOSTFloat32LSB:		// IEEE 754 32 bit float, as found on Intel x86 architecture
		memcpy (dest, source, bufsize * sizeof (float)); /* check */
		break;
	case ASIOSTInt24LSB:		// used for 20 bits as well
		float32toInt24(source, dest, bufsize);		

	case ASIOSTInt32LSB:
		float32toInt32(source, dest, bufsize);		

	case ASIOSTFloat64LSB: 		// IEEE 754 64 bit double float, as found on Intel x86 architecture

		// these are used for 32 bit data buffer, with different alignment of the data inside
		// 32 bit PCI bus systems can more easily used with these
	case ASIOSTInt32LSB16:		// 32 bit data with 18 bit alignment
	case ASIOSTInt32LSB18:		// 32 bit data with 18 bit alignment
	case ASIOSTInt32LSB20:		// 32 bit data with 20 bit alignment
	case ASIOSTInt32LSB24:		// 32 bit data with 24 bit alignment

	case ASIOSTInt16MSB:

	case ASIOSTInt24MSB:		// used for 20 bits as well

	case ASIOSTInt32MSB:

	case ASIOSTFloat32MSB:		// IEEE 754 32 bit float, as found on Intel x86 architecture

	case ASIOSTFloat64MSB: 		// IEEE 754 64 bit double float, as found on Intel x86 architecture
		// these are used for 32 bit data buffer, with different alignment of the data inside
		// 32 bit PCI bus systems can more easily used with these
	case ASIOSTInt32MSB16:		// 32 bit data with 18 bit alignment
	case ASIOSTInt32MSB18:		// 32 bit data with 18 bit alignment
	case ASIOSTInt32MSB20:		// 32 bit data with 20 bit alignment
	case ASIOSTInt32MSB24:		// 32 bit data with 24 bit alignment
		post("Sample Type %d not supported, yet");
	}
}

void asio_convert_and_receive (void* source, t_sample* dest, ASIOSampleType format, long bufsize)
{
#ifdef ASIODEBUG
/* 	post("ASIO: Sample Type %d", format); */
#endif

	switch (format)
	{
	case ASIOSTInt16LSB:
		Int16tofloat32(source, dest, bufsize);		
		break;
	case ASIOSTFloat32LSB:		// IEEE 754 32 bit float, as found on Intel x86 architecture
		memcpy (dest, source, bufsize * sizeof (float)); /* check */
		break;
	case ASIOSTInt24LSB:		// used for 20 bits as well
		Int24tofloat32(source, dest, bufsize);		
		break;
	case ASIOSTInt32LSB:
		Int32tofloat32(source, dest, bufsize);		
		break

	case ASIOSTFloat64LSB: 		// IEEE 754 64 bit double float, as found on Intel x86 architecture

		// these are used for 32 bit data buffer, with different alignment of the data inside
		// 32 bit PCI bus systems can more easily used with these
	case ASIOSTInt32LSB16:		// 32 bit data with 18 bit alignment
	case ASIOSTInt32LSB18:		// 32 bit data with 18 bit alignment
	case ASIOSTInt32LSB20:		// 32 bit data with 20 bit alignment
	case ASIOSTInt32LSB24:		// 32 bit data with 24 bit alignment

	case ASIOSTInt16MSB:
	case ASIOSTInt24MSB:		// used for 20 bits as well
	case ASIOSTInt32MSB:
	case ASIOSTFloat32MSB:		// IEEE 754 32 bit float, as found on Intel x86 architecture
	case ASIOSTFloat64MSB: 		// IEEE 754 64 bit double float, as found on Intel x86 architecture

		// these are used for 32 bit data buffer, with different alignment of the data inside
		// 32 bit PCI bus systems can more easily used with these
	case ASIOSTInt32MSB16:		// 32 bit data with 18 bit alignment
	case ASIOSTInt32MSB18:		// 32 bit data with 18 bit alignment
	case ASIOSTInt32MSB20:		// 32 bit data with 20 bit alignment
	case ASIOSTInt32MSB24:		// 32 bit data with 24 bit alignment
		post("Sample Type %d not supported, yet");
	}

}

/* sample conversion functions */

#define SCALE_INT16 32767.f       /* (- (expt 2 15) 1) */
#define SCALE_INT32 8388607.f     /* (- (expt 2 23) 1) */
#define SCALE_INT32 2147483647.f  /* (- (expt 2 31) 1) */

void float32toInt16(float* inbuffer, void* outbuffer, long frames)
{
	short* out = (short*)outbuffer;
	while (frames--)
	{
		*out++ = (short)(*inbuffer++ * SCALE_INT16);
	}
}

void Int16tofloat32(void* inbuffer, float* outbuffer, long frames)
{
	short* in = (short*)inbuffer;
	while (frames--)
	{
		*outbuffer++ = (float)(*in++ * (1.f / SCALE_INT16));
	}
}

void float32toInt24(float* inbuffer, void* outbuffer, long frames)
{
	long* out = (int*)outbuffer;
	while (frames--)
	{
		*out++ = (int)(*inbuffer * SCALE_INT24);
	}
}

void Int32tofloat24(void* inbuffer, float* outbuffer, long frames)
{
	long* in = (int*)inbuffer;
	while (frames--)
	{
		*outbuffer++ = (float)(*in++ * (1.f / SCALE_INT24));
	}
}

void float32toInt32(float* inbuffer, void* outbuffer, long frames)
{
	long* out = (long*)outbuffer;
	while (frames--)
	{
		*out++ = (long)(*inbuffer * SCALE_INT32);
	}
}

void Int32tofloat32(void* inbuffer, float* outbuffer, long frames)
{
	long* in = (long*)inbuffer;
	while (frames--)
	{
		*outbuffer++ = (float)(*in++ * (1.f / SCALE_INT32));
	}
}

/* some local helper functions */
inline void prepare_asio_drivernames(void)
{
	if (asio_drivernames == NULL)
	{
		asio_drivernames = (char**)getbytes(MAXNDEV * sizeof(char*));
		for (int i = 0; i!= MAXNDEV; ++i)
		{
			asio_drivernames[i] = (char*)getbytes (32 * sizeof(char));
		}
	}
	return;
}


#endif /* USEAPI_ASIO */

Index: s_stuff.h
===================================================================
RCS file: /cvsroot/pure-data/pd/src/s_stuff.h,v
retrieving revision 1.1.1.1.2.6
retrieving revision 1.1.1.1.2.7
diff -C2 -d -r1.1.1.1.2.6 -r1.1.1.1.2.7
*** s_stuff.h	7 Oct 2004 23:11:56 -0000	1.1.1.1.2.6
--- s_stuff.h	4 Nov 2004 20:22:44 -0000	1.1.1.1.2.7
***************
*** 132,135 ****
--- 132,136 ----
  #define API_PORTAUDIO 4
  #define API_JACK 5
+ #define API_ASIO 6
  
  #ifdef __linux__
***************
*** 138,143 ****
  #endif
  #if defined(MSW) || defined(__CYGWIN__)
! #define API_DEFAULT API_MMIO
! #define API_DEFSTRING "MMIO"
  #endif
  #ifdef MACOSX
--- 139,144 ----
  #endif
  #if defined(MSW) || defined(__CYGWIN__)
! #define API_DEFAULT API_ASIO
! #define API_DEFSTRING "ASIO"
  #endif
  #ifdef MACOSX
***************
*** 209,212 ****
--- 210,222 ----
      	int maxndev, int devdescsize);
  
+ void asio_open_audio(int naudioindev, int *audioindev, int nchindev, 
+ 					 int *chindev, int naudiooutdev, int *audiooutdev,
+ 					 int nchoutdev, int *choutdev, int srate);
+ void asio_close_audio(void);
+ void asio_getdevs(char *indevlist, int *nindevs,
+ 				  char *outdevlist, int *noutdevs, int *canmulti, 
+ 				  int maxndev, int devdescsize);
+ int asio_send_dacs(void);
+ 
  void sys_listmididevs(void);
  void sys_set_audio_api(int whichapi);

Index: s_main.c
===================================================================
RCS file: /cvsroot/pure-data/pd/src/s_main.c,v
retrieving revision 1.1.1.4.2.21
retrieving revision 1.1.1.4.2.22
diff -C2 -d -r1.1.1.4.2.21 -r1.1.1.4.2.22
*** s_main.c	23 Oct 2004 10:22:08 -0000	1.1.1.4.2.21
--- s_main.c	4 Nov 2004 20:22:44 -0000	1.1.1.4.2.22
***************
*** 309,312 ****
--- 309,313 ----
  #ifdef DAZ
  #include <xmmintrin.h>
+ 	;
  #define _MM_DENORM_ZERO_ON    0x0040
      _mm_setcsr(_MM_FLUSH_ZERO_ON | _MM_MASK_UNDERFLOW | _mm_getcsr());
***************
*** 356,359 ****
--- 357,364 ----
  #endif
  
+ #ifdef USEAPI_ASIO
+ 	"-asio_native     -- use native ASIO API\n",
+ #endif
+ 
  #ifdef USEAPI_PORTAUDIO
  #ifdef MSW
***************
*** 661,664 ****
--- 666,677 ----
      	}
  #endif
+ #ifdef USEAPI_ASIO
+     	else if (!strcmp(*argv, "-asio_native"))
+     	{
+     	    sys_set_audio_api(API_ASIO);
+ 			sys_mmio = 0;
+     	    argc--; argv++;
+     	}
+ #endif
  #ifdef USEAPI_MMIO
      	else if (!strcmp(*argv, "-mmio"))

Index: makefile.nt
===================================================================
RCS file: /cvsroot/pure-data/pd/src/makefile.nt,v
retrieving revision 1.1.1.3.2.4
retrieving revision 1.1.1.3.2.5
diff -C2 -d -r1.1.1.3.2.4 -r1.1.1.3.2.5
*** makefile.nt	29 Oct 2004 07:32:02 -0000	1.1.1.3.2.4
--- makefile.nt	4 Nov 2004 20:22:44 -0000	1.1.1.3.2.5
***************
*** 82,86 ****
  !else
  # the trailing slash is important!!
! LDIR = $(VC)\lib\  
  !endif
  
--- 82,86 ----
  !else
  # the trailing slash is important!!
! LDIR = $(VC)\lib\
  !endif
  
***************
*** 140,143 ****
--- 140,149 ----
  	cl /c $(ALLCF) /Tc$*.c
  
+ ASIOBJ: 
+ 	cl /c $(ALLCF) $(ASIOINC) s_audio_asio.cpp
+ 	cl /c $(ALLCF) $(ASIOINC) asio/asio.cpp 
+ 	cl /c $(ALLCF) $(ASIOINC) asio/pc/asiolist.cpp 
+ 	cl /c $(ALLCF) $(ASIOINC) asio/asiodrivers.cpp
+ 
  pd: ..\bin\pd.exe
  
***************
*** 148,152 ****
  	    ..\bin\pd.lib $(LIBS)
  
! ..\bin\pd.dll ..\bin\pd.lib: $(OBJC) $(OBJASIO)
  	link $(LFLAGS) /dll /export:sys_main /out:..\bin\pd.dll $(OBJC) \
  	    $(OBJASIO) $(LIBS)
--- 154,158 ----
  	    ..\bin\pd.lib $(LIBS)
  
! ..\bin\pd.dll ..\bin\pd.lib: $(OBJC) ASIOBJ
  	link $(LFLAGS) /dll /export:sys_main /out:..\bin\pd.dll $(OBJC) \
  	    $(OBJASIO) $(LIBS)





More information about the Pd-cvs mailing list