summaryrefslogtreecommitdiff
path: root/tests/asio
diff options
context:
space:
mode:
authorGary Scavone <gary@music.mcgill.ca>2013-10-09 23:44:33 +0200
committerStephen Sinclair <sinclair@music.mcgill.ca>2013-10-10 01:08:39 +0200
commita3d2ee35944db4dd0a3a342bb7f2df69f229f45d (patch)
tree1a1199a30b0db8a0306dceef0c15c9f9e3e72629 /tests/asio
parent8eb71e693530726068addf6b8088aea0fd340f2a (diff)
Version 2.1
Diffstat (limited to 'tests/asio')
-rw-r--r--tests/asio/Debug/.placeholder0
-rw-r--r--tests/asio/Release/.placeholder0
-rw-r--r--tests/asio/asio.cpp257
-rw-r--r--tests/asio/asio.h955
-rw-r--r--tests/asio/asiodrivers.cpp186
-rw-r--r--tests/asio/asiodrivers.h41
-rw-r--r--tests/asio/asiodrvr.h76
-rw-r--r--tests/asio/asiolist.cpp268
-rw-r--r--tests/asio/asiolist.h46
-rw-r--r--tests/asio/asiosys.h82
-rwxr-xr-xtests/asio/call_inout.dsp148
-rwxr-xr-xtests/asio/call_saw.dsp148
-rw-r--r--tests/asio/ginclude.h38
-rw-r--r--tests/asio/iasiodrv.h37
-rwxr-xr-xtests/asio/in_out.dsp148
-rwxr-xr-xtests/asio/info.dsp148
-rwxr-xr-xtests/asio/play_raw.dsp148
-rwxr-xr-xtests/asio/play_saw.dsp148
-rwxr-xr-xtests/asio/record_raw.dsp148
-rwxr-xr-xtests/asio/rtaudio.dsw101
20 files changed, 3123 insertions, 0 deletions
diff --git a/tests/asio/Debug/.placeholder b/tests/asio/Debug/.placeholder
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/asio/Debug/.placeholder
diff --git a/tests/asio/Release/.placeholder b/tests/asio/Release/.placeholder
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/asio/Release/.placeholder
diff --git a/tests/asio/asio.cpp b/tests/asio/asio.cpp
new file mode 100644
index 0000000..b241663
--- /dev/null
+++ b/tests/asio/asio.cpp
@@ -0,0 +1,257 @@
+/*
+ Steinberg Audio Stream I/O API
+ (c) 1996, Steinberg Soft- und Hardware GmbH
+
+ asio.cpp
+
+ asio functions entries which translate the
+ asio interface to the asiodrvr class methods
+*/
+
+#include <string.h>
+#include "asiosys.h" // platform definition
+#include "asio.h"
+
+#if MAC
+#include "asiodrvr.h"
+
+#pragma export on
+
+AsioDriver *theAsioDriver = 0;
+
+extern "C"
+{
+
+long main()
+{
+ return 'ASIO';
+}
+
+#elif WINDOWS
+
+#include "windows.h"
+#include "iasiodrv.h"
+#include "asiodrivers.h"
+
+IASIO *theAsioDriver = 0;
+extern AsioDrivers *asioDrivers;
+
+#elif SGI || SUN || BEOS || LINUX
+#include "asiodrvr.h"
+static AsioDriver *theAsioDriver = 0;
+#endif
+
+//-----------------------------------------------------------------------------------------------------
+ASIOError ASIOInit(ASIODriverInfo *info)
+{
+#if MAC || SGI || SUN || BEOS || LINUX
+ if(theAsioDriver)
+ {
+ delete theAsioDriver;
+ theAsioDriver = 0;
+ }
+ info->driverVersion = 0;
+ strcpy(info->name, "No ASIO Driver");
+ theAsioDriver = getDriver();
+ if(!theAsioDriver)
+ {
+ strcpy(info->errorMessage, "Not enough memory for the ASIO driver!");
+ return ASE_NotPresent;
+ }
+ if(!theAsioDriver->init(info->sysRef))
+ {
+ theAsioDriver->getErrorMessage(info->errorMessage);
+ delete theAsioDriver;
+ theAsioDriver = 0;
+ return ASE_NotPresent;
+ }
+ strcpy(info->errorMessage, "No ASIO Driver Error");
+ theAsioDriver->getDriverName(info->name);
+ info->driverVersion = theAsioDriver->getDriverVersion();
+ return ASE_OK;
+
+#else
+
+ info->driverVersion = 0;
+ strcpy(info->name, "No ASIO Driver");
+ if(theAsioDriver) // must be loaded!
+ {
+ if(!theAsioDriver->init(info->sysRef))
+ {
+ theAsioDriver->getErrorMessage(info->errorMessage);
+ theAsioDriver = 0;
+ return ASE_NotPresent;
+ }
+
+ strcpy(info->errorMessage, "No ASIO Driver Error");
+ theAsioDriver->getDriverName(info->name);
+ info->driverVersion = theAsioDriver->getDriverVersion();
+ return ASE_OK;
+ }
+ return ASE_NotPresent;
+
+#endif // !MAC
+}
+
+ASIOError ASIOExit(void)
+{
+ if(theAsioDriver)
+ {
+#if WINDOWS
+ asioDrivers->removeCurrentDriver();
+#else
+ delete theAsioDriver;
+#endif
+ }
+ theAsioDriver = 0;
+ return ASE_OK;
+}
+
+ASIOError ASIOStart(void)
+{
+ if(!theAsioDriver)
+ return ASE_NotPresent;
+ return theAsioDriver->start();
+}
+
+ASIOError ASIOStop(void)
+{
+ if(!theAsioDriver)
+ return ASE_NotPresent;
+ return theAsioDriver->stop();
+}
+
+ASIOError ASIOGetChannels(long *numInputChannels, long *numOutputChannels)
+{
+ if(!theAsioDriver)
+ {
+ *numInputChannels = *numOutputChannels = 0;
+ return ASE_NotPresent;
+ }
+ return theAsioDriver->getChannels(numInputChannels, numOutputChannels);
+}
+
+ASIOError ASIOGetLatencies(long *inputLatency, long *outputLatency)
+{
+ if(!theAsioDriver)
+ {
+ *inputLatency = *outputLatency = 0;
+ return ASE_NotPresent;
+ }
+ return theAsioDriver->getLatencies(inputLatency, outputLatency);
+}
+
+ASIOError ASIOGetBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity)
+{
+ if(!theAsioDriver)
+ {
+ *minSize = *maxSize = *preferredSize = *granularity = 0;
+ return ASE_NotPresent;
+ }
+ return theAsioDriver->getBufferSize(minSize, maxSize, preferredSize, granularity);
+}
+
+ASIOError ASIOCanSampleRate(ASIOSampleRate sampleRate)
+{
+ if(!theAsioDriver)
+ return ASE_NotPresent;
+ return theAsioDriver->canSampleRate(sampleRate);
+}
+
+ASIOError ASIOGetSampleRate(ASIOSampleRate *currentRate)
+{
+ if(!theAsioDriver)
+ return ASE_NotPresent;
+ return theAsioDriver->getSampleRate(currentRate);
+}
+
+ASIOError ASIOSetSampleRate(ASIOSampleRate sampleRate)
+{
+ if(!theAsioDriver)
+ return ASE_NotPresent;
+ return theAsioDriver->setSampleRate(sampleRate);
+}
+
+ASIOError ASIOGetClockSources(ASIOClockSource *clocks, long *numSources)
+{
+ if(!theAsioDriver)
+ {
+ *numSources = 0;
+ return ASE_NotPresent;
+ }
+ return theAsioDriver->getClockSources(clocks, numSources);
+}
+
+ASIOError ASIOSetClockSource(long reference)
+{
+ if(!theAsioDriver)
+ return ASE_NotPresent;
+ return theAsioDriver->setClockSource(reference);
+}
+
+ASIOError ASIOGetSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp)
+{
+ if(!theAsioDriver)
+ return ASE_NotPresent;
+ return theAsioDriver->getSamplePosition(sPos, tStamp);
+}
+
+ASIOError ASIOGetChannelInfo(ASIOChannelInfo *info)
+{
+ if(!theAsioDriver)
+ {
+ info->channelGroup = -1;
+ info->type = ASIOSTInt16MSB;
+ strcpy(info->name, "None");
+ return ASE_NotPresent;
+ }
+ return theAsioDriver->getChannelInfo(info);
+}
+
+ASIOError ASIOCreateBuffers(ASIOBufferInfo *bufferInfos, long numChannels,
+ long bufferSize, ASIOCallbacks *callbacks)
+{
+ if(!theAsioDriver)
+ {
+ ASIOBufferInfo *info = bufferInfos;
+ for(long i = 0; i < numChannels; i++, info++)
+ info->buffers[0] = info->buffers[1] = 0;
+ return ASE_NotPresent;
+ }
+ return theAsioDriver->createBuffers(bufferInfos, numChannels, bufferSize, callbacks);
+}
+
+ASIOError ASIODisposeBuffers(void)
+{
+ if(!theAsioDriver)
+ return ASE_NotPresent;
+ return theAsioDriver->disposeBuffers();
+}
+
+ASIOError ASIOControlPanel(void)
+{
+ if(!theAsioDriver)
+ return ASE_NotPresent;
+ return theAsioDriver->controlPanel();
+}
+
+ASIOError ASIOFuture(long selector, void *opt)
+{
+ if(!theAsioDriver)
+ return ASE_NotPresent;
+ return theAsioDriver->future(selector, opt);
+}
+
+ASIOError ASIOOutputReady(void)
+{
+ if(!theAsioDriver)
+ return ASE_NotPresent;
+ return theAsioDriver->outputReady();
+}
+
+#if MAC
+} // extern "C"
+#pragma export off
+#endif
+
+
diff --git a/tests/asio/asio.h b/tests/asio/asio.h
new file mode 100644
index 0000000..3003130
--- /dev/null
+++ b/tests/asio/asio.h
@@ -0,0 +1,955 @@
+//---------------------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------------------
+
+/*
+ Steinberg Audio Stream I/O API
+ (c) 1997 - 1999, Steinberg Soft- und Hardware GmbH
+
+ ASIO Interface Specification v 2.0
+
+ basic concept is an i/o synchronous double-buffer scheme:
+
+ on bufferSwitch(index == 0), host will read/write:
+
+ after ASIOStart(), the
+ read first input buffer A (index 0)
+ | will be invalid (empty)
+ * ------------------------
+ |------------------------|-----------------------|
+ | | |
+ | Input Buffer A (0) | Input Buffer B (1) |
+ | | |
+ |------------------------|-----------------------|
+ | | |
+ | Output Buffer A (0) | Output Buffer B (1) |
+ | | |
+ |------------------------|-----------------------|
+ * -------------------------
+ | before calling ASIOStart(),
+ write host will have filled output
+ buffer B (index 1) already
+
+ *please* take special care of proper statement of input
+ and output latencies (see ASIOGetLatencies()), these
+ control sequencer sync accuracy
+
+*/
+
+//---------------------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------------------
+
+/*
+
+prototypes summary:
+
+ASIOError ASIOInit(ASIODriverInfo *info);
+ASIOError ASIOExit(void);
+ASIOError ASIOStart(void);
+ASIOError ASIOStop(void);
+ASIOError ASIOGetChannels(long *numInputChannels, long *numOutputChannels);
+ASIOError ASIOGetLatencies(long *inputLatency, long *outputLatency);
+ASIOError ASIOGetBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity);
+ASIOError ASIOCanSampleRate(ASIOSampleRate sampleRate);
+ASIOError ASIOGetSampleRate(ASIOSampleRate *currentRate);
+ASIOError ASIOSetSampleRate(ASIOSampleRate sampleRate);
+ASIOError ASIOGetClockSources(ASIOClockSource *clocks, long *numSources);
+ASIOError ASIOSetClockSource(long reference);
+ASIOError ASIOGetSamplePosition (ASIOSamples *sPos, ASIOTimeStamp *tStamp);
+ASIOError ASIOGetChannelInfo(ASIOChannelInfo *info);
+ASIOError ASIOCreateBuffers(ASIOBufferInfo *bufferInfos, long numChannels,
+ long bufferSize, ASIOCallbacks *callbacks);
+ASIOError ASIODisposeBuffers(void);
+ASIOError ASIOControlPanel(void);
+void *ASIOFuture(long selector, void *params);
+ASIOError ASIOOutputReady(void);
+
+*/
+
+//---------------------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------------------
+
+#ifndef __ASIO_H
+#define __ASIO_H
+
+// force 4 byte alignment
+#if defined(_MSC_VER) && !defined(__MWERKS__)
+#pragma pack(push,4)
+#elif PRAGMA_ALIGN_SUPPORTED
+#pragma options align = native
+#endif
+
+//- - - - - - - - - - - - - - - - - - - - - - - - -
+// Type definitions
+//- - - - - - - - - - - - - - - - - - - - - - - - -
+
+// number of samples data type is 64 bit integer
+#if NATIVE_INT64
+ typedef long long int ASIOSamples;
+#else
+ typedef struct ASIOSamples {
+ unsigned long hi;
+ unsigned long lo;
+ } ASIOSamples;
+#endif
+
+// Timestamp data type is 64 bit integer,
+// Time format is Nanoseconds.
+#if NATIVE_INT64
+ typedef long long int ASIOTimeStamp ;
+#else
+ typedef struct ASIOTimeStamp {
+ unsigned long hi;
+ unsigned long lo;
+ } ASIOTimeStamp;
+#endif
+
+// Samplerates are expressed in IEEE 754 64 bit double float,
+// native format as host computer
+#if IEEE754_64FLOAT
+ typedef double ASIOSampleRate;
+#else
+ typedef struct ASIOSampleRate {
+ char ieee[8];
+ } ASIOSampleRate;
+#endif
+
+// Boolean values are expressed as long
+typedef long ASIOBool;
+enum {
+ ASIOFalse = 0,
+ ASIOTrue = 1
+};
+
+// Sample Types are expressed as long
+typedef long ASIOSampleType;
+enum {
+ ASIOSTInt16MSB = 0,
+ ASIOSTInt24MSB = 1, // used for 20 bits as well
+ ASIOSTInt32MSB = 2,
+ ASIOSTFloat32MSB = 3, // IEEE 754 32 bit float
+ ASIOSTFloat64MSB = 4, // IEEE 754 64 bit double float
+
+ // these are used for 32 bit data buffer, with different alignment of the data inside
+ // 32 bit PCI bus systems can be more easily used with these
+ ASIOSTInt32MSB16 = 8, // 32 bit data with 18 bit alignment
+ ASIOSTInt32MSB18 = 9, // 32 bit data with 18 bit alignment
+ ASIOSTInt32MSB20 = 10, // 32 bit data with 20 bit alignment
+ ASIOSTInt32MSB24 = 11, // 32 bit data with 24 bit alignment
+
+ ASIOSTInt16LSB = 16,
+ ASIOSTInt24LSB = 17, // used for 20 bits as well
+ ASIOSTInt32LSB = 18,
+ ASIOSTFloat32LSB = 19, // IEEE 754 32 bit float, as found on Intel x86 architecture
+ ASIOSTFloat64LSB = 20, // 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
+ ASIOSTInt32LSB16 = 24, // 32 bit data with 18 bit alignment
+ ASIOSTInt32LSB18 = 25, // 32 bit data with 18 bit alignment
+ ASIOSTInt32LSB20 = 26, // 32 bit data with 20 bit alignment
+ ASIOSTInt32LSB24 = 27 // 32 bit data with 24 bit alignment
+};
+
+//- - - - - - - - - - - - - - - - - - - - - - - - -
+// Error codes
+//- - - - - - - - - - - - - - - - - - - - - - - - -
+
+typedef long ASIOError;
+enum {
+ ASE_OK = 0, // This value will be returned whenever the call succeeded
+ ASE_SUCCESS = 0x3f4847a0, // unique success return value for ASIOFuture calls
+ ASE_NotPresent = -1000, // hardware input or output is not present or available
+ ASE_HWMalfunction, // hardware is malfunctioning (can be returned by any ASIO function)
+ ASE_InvalidParameter, // input parameter invalid
+ ASE_InvalidMode, // hardware is in a bad mode or used in a bad mode
+ ASE_SPNotAdvancing, // hardware is not running when sample position is inquired
+ ASE_NoClock, // sample clock or rate cannot be determined or is not present
+ ASE_NoMemory // not enough memory for completing the request
+};
+
+//---------------------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------------------
+
+//- - - - - - - - - - - - - - - - - - - - - - - - -
+// Time Info support
+//- - - - - - - - - - - - - - - - - - - - - - - - -
+
+typedef struct ASIOTimeCode
+{
+ double speed; // speed relation (fraction of nominal speed)
+ // optional; set to 0. or 1. if not supported
+ ASIOSamples timeCodeSamples; // time in samples
+ unsigned long flags; // some information flags (see below)
+ char future[64];
+} ASIOTimeCode;
+
+typedef enum ASIOTimeCodeFlags
+{
+ kTcValid = 1,
+ kTcRunning = 1 << 1,
+ kTcReverse = 1 << 2,
+ kTcOnspeed = 1 << 3,
+ kTcStill = 1 << 4,
+
+ kTcSpeedValid = 1 << 8
+} ASIOTimeCodeFlags;
+
+typedef struct AsioTimeInfo
+{
+ double speed; // absolute speed (1. = nominal)
+ ASIOTimeStamp systemTime; // system time related to samplePosition, in nanoseconds
+ // on mac, must be derived from Microseconds() (not UpTime()!)
+ // on windows, must be derived from timeGetTime()
+ ASIOSamples samplePosition;
+ ASIOSampleRate sampleRate; // current rate
+ unsigned long flags; // (see below)
+ char reserved[12];
+} AsioTimeInfo;
+
+typedef enum AsioTimeInfoFlags
+{
+ kSystemTimeValid = 1, // must always be valid
+ kSamplePositionValid = 1 << 1, // must always be valid
+ kSampleRateValid = 1 << 2,
+ kSpeedValid = 1 << 3,
+
+ kSampleRateChanged = 1 << 4,
+ kClockSourceChanged = 1 << 5
+} AsioTimeInfoFlags;
+
+typedef struct ASIOTime // both input/output
+{
+ long reserved[4]; // must be 0
+ struct AsioTimeInfo timeInfo; // required
+ struct ASIOTimeCode timeCode; // optional, evaluated if (timeCode.flags & kTcValid)
+} ASIOTime;
+
+/*
+
+using time info:
+it is recommended to use the new method with time info even if the asio
+device does not support timecode; continuous calls to ASIOGetSamplePosition
+and ASIOGetSampleRate are avoided, and there is a more defined relationship
+between callback time and the time info.
+
+see the example below.
+to initiate time info mode, after you have received the callbacks pointer in
+ASIOCreateBuffers, you will call the asioMessage callback with kAsioSupportsTimeInfo
+as the argument. if this returns 1, host has accepted time info mode.
+now host expects the new callback bufferSwitchTimeInfo to be used instead
+of the old bufferSwitch method. the ASIOTime structure is assumed to be valid
+and accessible until the callback returns.
+
+using time code:
+if the device supports reading time code, it will call host's asioMessage callback
+with kAsioSupportsTimeCode as the selector. it may then fill the according
+fields and set the kTcValid flag.
+host will call the future method with the kAsioEnableTimeCodeRead selector when
+it wants to enable or disable tc reading by the device. you should also support
+the kAsioCanTimeInfo and kAsioCanTimeCode selectors in ASIOFuture (see example).
+
+note:
+the AsioTimeInfo/ASIOTimeCode pair is supposed to work in both directions.
+as a matter of convention, the relationship between the sample
+position counter and the time code at buffer switch time is
+(ignoring offset between tc and sample pos when tc is running):
+
+on input: sample 0 -> input buffer sample 0 -> time code 0
+on output: sample 0 -> output buffer sample 0 -> time code 0
+
+this means that for 'real' calculations, one has to take into account
+the according latencies.
+
+example:
+
+ASIOTime asioTime;
+
+in createBuffers()
+{
+ memset(&asioTime, 0, sizeof(ASIOTime));
+ AsioTimeInfo* ti = &asioTime.timeInfo;
+ ti->sampleRate = theSampleRate;
+ ASIOTimeCode* tc = &asioTime.timeCode;
+ tc->speed = 1.;
+ timeInfoMode = false;
+ canTimeCode = false;
+ if(callbacks->asioMessage(kAsioSupportsTimeInfo, 0, 0, 0) == 1)
+ {
+ timeInfoMode = true;
+#if kCanTimeCode
+ if(callbacks->asioMessage(kAsioSupportsTimeCode, 0, 0, 0) == 1)
+ canTimeCode = true;
+#endif
+ }
+}
+
+void switchBuffers(long doubleBufferIndex, bool processNow)
+{
+ if(timeInfoMode)
+ {
+ AsioTimeInfo* ti = &asioTime.timeInfo;
+ ti->flags = kSystemTimeValid | kSamplePositionValid | kSampleRateValid;
+ ti->systemTime = theNanoSeconds;
+ ti->samplePosition = theSamplePosition;
+ if(ti->sampleRate != theSampleRate)
+ ti->flags |= kSampleRateChanged;
+ ti->sampleRate = theSampleRate;
+
+#if kCanTimeCode
+ if(canTimeCode && timeCodeEnabled)
+ {
+ ASIOTimeCode* tc = &asioTime.timeCode;
+ tc->timeCodeSamples = tcSamples; // tc in samples
+ tc->flags = kTcValid | kTcRunning | kTcOnspeed; // if so...
+ }
+ ASIOTime* bb = callbacks->bufferSwitchTimeInfo(&asioTime, doubleBufferIndex, processNow ? ASIOTrue : ASIOFalse);
+#else
+ callbacks->bufferSwitchTimeInfo(&asioTime, doubleBufferIndex, processNow ? ASIOTrue : ASIOFalse);
+#endif
+ }
+ else
+ callbacks->bufferSwitch(doubleBufferIndex, ASIOFalse);
+}
+
+ASIOError ASIOFuture(long selector, void *params)
+{
+ switch(selector)
+ {
+ case kAsioEnableTimeCodeRead:
+ timeCodeEnabled = true;
+ return ASE_SUCCESS;
+ case kAsioDisableTimeCodeRead:
+ timeCodeEnabled = false;
+ return ASE_SUCCESS;
+ case kAsioCanTimeInfo:
+ return ASE_SUCCESS;
+ #if kCanTimeCode
+ case kAsioCanTimeCode:
+ return ASE_SUCCESS;
+ #endif
+ }
+ return ASE_NotPresent;
+};
+
+*/
+
+//- - - - - - - - - - - - - - - - - - - - - - - - -
+// application's audio stream handler callbacks
+//- - - - - - - - - - - - - - - - - - - - - - - - -
+
+typedef struct ASIOCallbacks
+{
+ void (*bufferSwitch) (long doubleBufferIndex, ASIOBool directProcess);
+ // bufferSwitch indicates that both input and output are to be processed.
+ // the current buffer half index (0 for A, 1 for B) determines
+ // - the output buffer that the host should start to fill. the other buffer
+ // will be passed to output hardware regardless of whether it got filled
+ // in time or not.
+ // - the input buffer that is now filled with incoming data. Note that
+ // because of the synchronicity of i/o, the input always has at
+ // least one buffer latency in relation to the output.
+ // directProcess suggests to the host whether it should immedeately
+ // start processing (directProcess == ASIOTrue), or whether its process
+ // should be deferred because the call comes from a very low level
+ // (for instance, a high level priority interrupt), and direct processing
+ // would cause timing instabilities for the rest of the system. If in doubt,
+ // directProcess should be set to ASIOFalse.
+ // Note: bufferSwitch may be called at interrupt time for highest efficiency.
+
+ void (*sampleRateDidChange) (ASIOSampleRate sRate);
+ // gets called when the AudioStreamIO detects a sample rate change
+ // If sample rate is unknown, 0 is passed (for instance, clock loss
+ // when externally synchronized).
+
+ long (*asioMessage) (long selector, long value, void* message, double* opt);
+ // generic callback for various purposes, see selectors below.
+ // note this is only present if the asio version is 2 or higher
+
+ ASIOTime* (*bufferSwitchTimeInfo) (ASIOTime* params, long doubleBufferIndex, ASIOBool directProcess);
+ // new callback with time info. makes ASIOGetSamplePosition() and various
+ // calls to ASIOGetSampleRate obsolete,
+ // and allows for timecode sync etc. to be preferred; will be used if
+ // the driver calls asioMessage with selector kAsioSupportsTimeInfo.
+} ASIOCallbacks;
+
+// asioMessage selectors
+enum
+{
+ kAsioSelectorSupported = 1, // selector in <value>, returns 1L if supported,
+ // 0 otherwise
+ kAsioEngineVersion, // returns engine (host) asio implementation version,
+ // 2 or higher
+ kAsioResetRequest, // request driver reset. if accepted, this
+ // will close the driver (ASIO_Exit() ) and
+ // re-open it again (ASIO_Init() etc). some
+ // drivers need to reconfigure for instance
+ // when the sample rate changes, or some basic
+ // changes have been made in ASIO_ControlPanel().
+ // returns 1L; note the request is merely passed
+ // to the application, there is no way to determine
+ // if it gets accepted at this time (but it usually
+ // will be).
+ kAsioBufferSizeChange, // not yet supported, will currently always return 0L.
+ // for now, use kAsioResetRequest instead.
+ // once implemented, the new buffer size is expected
+ // in <value>, and on success returns 1L
+ kAsioResyncRequest, // the driver went out of sync, such that
+ // the timestamp is no longer valid. this
+ // is a request to re-start the engine and
+ // slave devices (sequencer). returns 1 for ok,
+ // 0 if not supported.
+ kAsioLatenciesChanged, // the drivers latencies have changed. The engine
+ // will refetch the latencies.
+ kAsioSupportsTimeInfo, // if host returns true here, it will expect the
+ // callback bufferSwitchTimeInfo to be called instead
+ // of bufferSwitch
+ kAsioSupportsTimeCode, // supports time code reading/writing
+
+ kAsioSupportsInputMonitor, // supports input monitoring
+
+ kAsioNumMessageSelectors
+};
+
+//---------------------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------------------
+
+//- - - - - - - - - - - - - - - - - - - - - - - - -
+// (De-)Construction
+//- - - - - - - - - - - - - - - - - - - - - - - - -
+
+typedef struct ASIODriverInfo
+{
+ long asioVersion; // currently, 2
+ long driverVersion; // driver specific
+ char name[32];
+ char errorMessage[124];
+ void *sysRef; // on input: system reference
+ // (Windows: application main window handle, Mac & SGI: 0)
+} ASIODriverInfo;
+
+ASIOError ASIOInit(ASIODriverInfo *info);
+/* Purpose:
+ Initialize the AudioStreamIO.
+ Parameter:
+ info: pointer to an ASIODriver structure:
+ - asioVersion:
+ - on input, the host version. *** Note *** this is 0 for earlier asio
+ implementations, and the asioMessage callback is implemeted
+ only if asioVersion is 2 or greater. sorry but due to a design fault
+ the driver doesn't have access to the host version in ASIOInit :-(
+ added selector for host (engine) version in the asioMessage callback
+ so we're ok from now on.
+ - on return, asio implementation version.
+ older versions are 1
+ if you support this version (namely, ASIO_outputReady() )
+ this should be 2 or higher. also see the note in
+ ASIO_getTimeStamp() !
+ - version: on return, the driver version (format is driver specific)
+ - name: on return, a null-terminated string containing the driver's name
+ - error message: on return, should contain a user message describing
+ the type of error that occured during ASIOInit(), if any.
+ - sysRef: platform specific
+ Returns:
+ If neither input nor output is present ASE_NotPresent
+ will be returned.
+ ASE_NoMemory, ASE_HWMalfunction are other possible error conditions
+*/
+
+ASIOError ASIOExit(void);
+/* Purpose:
+ Terminates the AudioStreamIO.
+ Parameter:
+ None.
+ Returns:
+ If neither input nor output is present ASE_NotPresent
+ will be returned.
+ Notes: this implies ASIOStop() and ASIODisposeBuffers(),
+ meaning that no host callbacks must be accessed after ASIOExit().
+*/
+
+//- - - - - - - - - - - - - - - - - - - - - - - - -
+// Start/Stop
+//- - - - - - - - - - - - - - - - - - - - - - - - -
+
+ASIOError ASIOStart(void);
+/* Purpose:
+ Start input and output processing synchronously.
+ This will
+ - reset the sample counter to zero
+ - start the hardware (both input and output)
+ The first call to the hosts' bufferSwitch(index == 0) then tells
+ the host to read from input buffer A (index 0), and start
+ processing to output buffer A while output buffer B (which
+ has been filled by the host prior to calling ASIOStart())
+ is possibly sounding (see also ASIOGetLatencies())
+ Parameter:
+ None.
+ Returns:
+ If neither input nor output is present, ASE_NotPresent
+ will be returned.
+ If the hardware fails to start, ASE_HWMalfunction will be returned.
+ Notes:
+ There is no restriction on the time that ASIOStart() takes
+ to perform (that is, it is not considered a realtime trigger).
+*/
+
+ASIOError ASIOStop(void);
+/* Purpose:
+ Stops input and output processing altogether.
+ Parameter:
+ None.
+ Returns:
+ If neither input nor output is present ASE_NotPresent
+ will be returned.
+ Notes:
+ On return from ASIOStop(), the driver must in no
+ case call the hosts' bufferSwitch() routine.
+*/
+
+//- - - - - - - - - - - - - - - - - - - - - - - - -
+// Inquiry methods and sample rate
+//- - - - - - - - - - - - - - - - - - - - - - - - -
+
+ASIOError ASIOGetChannels(long *numInputChannels, long *numOutputChannels);
+/* Purpose:
+ Returns number of individual input/output channels.
+ Parameter:
+ numInputChannels will hold the number of available input channels
+ numOutputChannels will hold the number of available output channels
+ Returns:
+ If no input/output is present ASE_NotPresent will be returned.
+ If only inputs, or only outputs are available, the according
+ other parameter will be zero, and ASE_OK is returned.
+*/
+
+ASIOError ASIOGetLatencies(long *inputLatency, long *outputLatency);
+/* Purpose:
+ Returns the input and output latencies. This includes
+ device specific delays, like FIFOs etc.
+ Parameter:
+ inputLatency will hold the 'age' of the first sample frame
+ in the input buffer when the hosts reads it in bufferSwitch()
+ (this is theoretical, meaning it does not include the overhead
+ and delay between the actual physical switch, and the time
+ when bufferSitch() enters).
+ This will usually be the size of one block in sample frames, plus
+ device specific latencies.
+
+ outputLatency will specify the time between the buffer switch,
+ and the time when the next play buffer will start to sound.
+ The next play buffer is defined as the one the host starts
+ processing after (or at) bufferSwitch(), indicated by the
+ index parameter (0 for buffer A, 1 for buffer B).
+ It will usually be either one block, if the host writes directly
+ to a dma buffer, or two or more blocks if the buffer is 'latched' by
+ the driver. As an example, on ASIOStart(), the host will have filled
+ the play buffer at index 1 already; when it gets the callback (with
+ the parameter index == 0), this tells it to read from the input
+ buffer 0, and start to fill the play buffer 0 (assuming that now
+ play buffer 1 is already sounding). In this case, the output
+ latency is one block. If the driver decides to copy buffer 1
+ at that time, and pass it to the hardware at the next slot (which
+ is most commonly done, but should be avoided), the output latency
+ becomes two blocks instead, resulting in a total i/o latency of at least
+ 3 blocks. As memory access is the main bottleneck in native dsp processing,
+ and to acheive less latency, it is highly recommended to try to avoid
+ copying (this is also why the driver is the owner of the buffers). To
+ summarize, the minimum i/o latency can be acheived if the input buffer
+ is processed by the host into the output buffer which will physically
+ start to sound on the next time slice. Also note that the host expects
+ the bufferSwitch() callback to be accessed for each time slice in order
+ to retain sync, possibly recursively; if it fails to process a block in
+ time, it will suspend its operation for some time in order to recover.
+ Returns:
+ If no input/output is present ASE_NotPresent will be returned.
+*/
+
+ASIOError ASIOGetBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity);
+/* Purpose:
+ Returns min, max, and preferred buffer sizes for input/output
+ Parameter:
+ minSize will hold the minimum buffer size
+ maxSize will hold the maxium possible buffer size
+ preferredSize will hold the preferred buffer size (a size which
+ best fits performance and hardware requirements)
+ granularity will hold the granularity at which buffer sizes
+ may differ. Usually, the buffer size will be a power of 2;
+ in this case, granularity will hold -1 on return, signalling
+ possible buffer sizes starting from minSize, increased in
+ powers of 2 up to maxSize.
+ Returns:
+ If no input/output is present ASE_NotPresent will be returned.
+ Notes:
+ When minimum and maximum buffer size are equal,
+ the preferred buffer size has to be the same value as well; granularity
+ should be 0 in this case.
+*/
+
+ASIOError ASIOCanSampleRate(ASIOSampleRate sampleRate);
+/* Purpose:
+ Inquires the hardware for the available sample rates.
+ Parameter:
+ sampleRate is the rate in question.
+ Returns:
+ If the inquired sample rate is not supported, ASE_NoClock will be returned.
+ If no input/output is present ASE_NotPresent will be returned.
+*/
+ASIOError ASIOGetSampleRate(ASIOSampleRate *currentRate);
+/* Purpose:
+ Get the current sample Rate.
+ Parameter:
+ currentRate will hold the current sample rate on return.
+ Returns:
+ If sample rate is unknown, sampleRate will be 0 and ASE_NoClock will be returned.
+ If no input/output is present ASE_NotPresent will be returned.
+ Notes:
+*/
+
+ASIOError ASIOSetSampleRate(ASIOSampleRate sampleRate);
+/* Purpose:
+ Set the hardware to the requested sample Rate. If sampleRate == 0,
+ enable external sync.
+ Parameter:
+ sampleRate: on input, the requested rate
+ Returns:
+ If sampleRate is unknown ASE_NoClock will be returned.
+ If the current clock is external, and sampleRate is != 0,
+ ASE_InvalidMode will be returned
+ If no input/output is present ASE_NotPresent will be returned.
+ Notes:
+*/
+
+typedef struct ASIOClockSource
+{
+ long index; // as used for ASIOSetClockSource()
+ long associatedChannel; // for instance, S/PDIF or AES/EBU
+ long associatedGroup; // see channel groups (ASIOGetChannelInfo())
+ ASIOBool isCurrentSource; // ASIOTrue if this is the current clock source
+ char name[32]; // for user selection
+} ASIOClockSource;
+
+ASIOError ASIOGetClockSources(ASIOClockSource *clocks, long *numSources);
+/* Purpose:
+ Get the available external audio clock sources
+ Parameter:
+ clocks points to an array of ASIOClockSource structures:
+ - index: this is used to identify the clock source
+ when ASIOSetClockSource() is accessed, should be
+ an index counting from zero
+ - associatedInputChannel: the first channel of an associated
+ input group, if any.
+ - associatedGroup: the group index of that channel.
+ groups of channels are defined to seperate for
+ instance analog, S/PDIF, AES/EBU, ADAT connectors etc,
+ when present simultaniously. Note that associated channel
+ is enumerated according to numInputs/numOutputs, means it
+ is independant from a group (see also ASIOGetChannelInfo())
+ inputs are associated to a clock if the physical connection
+ transfers both data and clock (like S/PDIF, AES/EBU, or
+ ADAT inputs). if there is no input channel associated with
+ the clock source (like Word Clock, or internal oscillator), both
+ associatedChannel and associatedGroup should be set to -1.
+ - isCurrentSource: on exit, ASIOTrue if this is the current clock
+ source, ASIOFalse else
+ - name: a null-terminated string for user selection of the available sources.
+ numSources:
+ on input: the number of allocated array members
+ on output: the number of available clock sources, at least
+ 1 (internal clock generator).
+ Returns:
+ If no input/output is present ASE_NotPresent will be returned.
+ Notes:
+*/
+
+ASIOError ASIOSetClockSource(long index);
+/* Purpose:
+ Set the audio clock source
+ Parameter:
+ index as obtained from an inquiry to ASIOGetClockSources()
+ Returns:
+ If no input/output is present ASE_NotPresent will be returned.
+ If the clock can not be selected because an input channel which
+ carries the current clock source is active, ASE_InvalidMode
+ *may* be returned (this depends on the properties of the driver
+ and/or hardware).
+ Notes:
+ Should *not* return ASE_NoClock if there is no clock signal present
+ at the selected source; this will be inquired via ASIOGetSampleRate().
+ It should call the host callback procedure sampleRateHasChanged(),
+ if the switch causes a sample rate change, or if no external clock
+ is present at the selected source.
+*/
+
+ASIOError ASIOGetSamplePosition (ASIOSamples *sPos, ASIOTimeStamp *tStamp);
+/* Purpose:
+ Inquires the sample position/time stamp pair.
+ Parameter:
+ sPos will hold the sample position on return. The sample
+ position is reset to zero when ASIOStart() gets called.
+ tStamp will hold the system time when the sample position
+ was latched.
+ Returns:
+ If no input/output is present, ASE_NotPresent will be returned.
+ If there is no clock, ASE_SPNotAdvancing will be returned.
+ Notes:
+
+ in order to be able to synchronise properly,
+ the sample position / time stamp pair must refer to the current block,
+ that is, the engine will call ASIOGetSamplePosition() in its bufferSwitch()
+ callback and expect the time for the current block. thus, when requested
+ in the very first bufferSwitch after ASIO_Start(), the sample position
+ should be zero, and the time stamp should refer to the very time where
+ the stream was started. it also means that the sample position must be
+ block aligned. the driver must ensure proper interpolation if the system
+ time can not be determined for the block position. the driver is responsible
+ for precise time stamps as it usually has most direct access to lower
+ level resources. proper behaviour of ASIO_GetSamplePosition() and ASIO_GetLatencies()
+ are essential for precise media synchronization!
+*/
+
+typedef struct ASIOChannelInfo
+{
+ long channel; // on input, channel index
+ ASIOBool isInput; // on input
+ ASIOBool isActive; // on exit
+ long channelGroup; // dto
+ ASIOSampleType type; // dto
+ char name[32]; // dto
+} ASIOChannelInfo;
+
+ASIOError ASIOGetChannelInfo(ASIOChannelInfo *info);
+/* Purpose:
+ retreive information about the nature of a channel
+ Parameter:
+ info: pointer to a ASIOChannelInfo structure with
+ - channel: on input, the channel index of the channel in question.
+ - isInput: on input, ASIOTrue if info for an input channel is
+ requested, else output
+ - channelGroup: on return, the channel group that the channel
+ belongs to. For drivers which support different types of
+ channels, like analog, S/PDIF, AES/EBU, ADAT etc interfaces,
+ there should be a reasonable grouping of these types. Groups
+ are always independant form a channel index, that is, a channel
+ index always counts from 0 to numInputs/numOutputs regardless
+ of the group it may belong to.
+ There will always be at least one group (group 0). Please
+ also note that by default, the host may decide to activate
+ channels 0 and 1; thus, these should belong to the most
+ useful type (analog i/o, if present).
+ - type: on return, contains the sample type of the channel
+ - isActive: on return, ASIOTrue if channel is active as it was
+ installed by ASIOCreateBuffers(), ASIOFalse else
+ - name: describing the type of channel in question. Used to allow
+ for user selection, and enabling of specific channels. examples:
+ "Analog In", "SPDIF Out" etc
+ Returns:
+ If no input/output is present ASE_NotPresent will be returned.
+ Notes:
+ If possible, the string should be organised such that the first
+ characters are most significantly describing the nature of the
+ port, to allow for identification even if the view showing the
+ port name is too small to display more than 8 characters, for
+ instance.
+*/
+
+//- - - - - - - - - - - - - - - - - - - - - - - - -
+// Buffer preparation
+//- - - - - - - - - - - - - - - - - - - - - - - - -
+
+typedef struct ASIOBufferInfo
+{
+ ASIOBool isInput; // on input: ASIOTrue: input, else output
+ long channelNum; // on input: channel index
+ void *buffers[2]; // on output: double buffer addresses
+} ASIOBufferInfo;
+
+ASIOError ASIOCreateBuffers(ASIOBufferInfo *bufferInfos, long numChannels,
+ long bufferSize, ASIOCallbacks *callbacks);
+
+/* Purpose:
+ Allocates input/output buffers for all input and output channels to be activated.
+ Parameter:
+ bufferInfos is a pointer to an array of ASIOBufferInfo structures:
+ - isInput: on input, ASIOTrue if the buffer is to be allocated
+ for an input, output buffer else
+ - channelNum: on input, the index of the channel in question
+ (counting from 0)
+ - buffers: on exit, 2 pointers to the halves of the channels' double-buffer.
+ the size of the buffer(s) of course depend on both the ASIOSampleType
+ as obtained from ASIOGetChannelInfo(), and bufferSize
+ numChannels is the sum of all input and output channels to be created;
+ thus bufferInfos is a pointer to an array of numChannels ASIOBufferInfo
+ structures.
+ bufferSize selects one of the possible buffer sizes as obtained from
+ ASIOGetBufferSizes().
+ callbacks is a pointer to an ASIOCallbacks structure.
+ Returns:
+ If not enough memory is available ASE_NoMemory will be returned.
+ If no input/output is present ASE_NotPresent will be returned.
+ If bufferSize is not supported, or one or more of the bufferInfos elements
+ contain invalid settings, ASE_InvalidMode will be returned.
+ Notes:
+ If individual channel selection is not possible but requested,
+ the driver has to handle this. namely, bufferSwitch() will only
+ have filled buffers of enabled outputs. If possible, processing
+ and buss activities overhead should be avoided for channels which
+ were not enabled here.
+*/
+
+ASIOError ASIODisposeBuffers(void);
+/* Purpose:
+ Releases all buffers for the device.
+ Parameter:
+ None.
+ Returns:
+ If no buffer were ever prepared, ASE_InvalidMode will be returned.
+ If no input/output is present ASE_NotPresent will be returned.
+ Notes:
+ This implies ASIOStop().
+*/
+
+ASIOError ASIOControlPanel(void);
+/* Purpose:
+ request the driver to start a control panel component
+ for device specific user settings. This will not be
+ accessed on some platforms (where the component is accessed
+ instead).
+ Parameter:
+ None.
+ Returns:
+ If no panel is available ASE_NotPresent will be returned.
+ Actually, the return code is ignored.
+ Notes:
+ if the user applied settings which require a re-configuration
+ of parts or all of the enigine and/or driver (such as a change of
+ the block size), the asioMessage callback can be used (see
+ ASIO_Callbacks).
+*/
+
+ASIOError ASIOFuture(long selector, void *params);
+/* Purpose:
+ various
+ Parameter:
+ selector: operation Code as to be defined. zero is reserved for
+ testing purposes.
+ params: depends on the selector; usually pointer to a structure
+ for passing and retreiving any type and amount of parameters.
+ Returns:
+ the return value is also selector dependant. if the selector
+ is unknown, ASE_InvalidParameter should be returned to prevent
+ further calls with this selector. on success, ASE_SUCCESS
+ must be returned (note: ASE_OK is *not* sufficient!)
+ Notes:
+ see selectors defined below.
+*/
+
+enum
+{
+ kAsioEnableTimeCodeRead = 1, // no arguments
+ kAsioDisableTimeCodeRead, // no arguments
+ kAsioSetInputMonitor, // ASIOInputMonitor* in params
+ kAsioTransport, // ASIOTransportParameters* in params
+ kAsioSetInputGain, // ASIOChannelControls* in params, apply gain
+ kAsioGetInputMeter, // ASIOChannelControls* in params, fill meter
+ kAsioSetOutputGain, // ASIOChannelControls* in params, apply gain
+ kAsioGetOutputMeter, // ASIOChannelControls* in params, fill meter
+ kAsioCanInputMonitor, // no arguments for kAsioCanXXX selectors
+ kAsioCanTimeInfo,
+ kAsioCanTimeCode,
+ kAsioCanTransport,
+ kAsioCanInputGain,
+ kAsioCanInputMeter,
+ kAsioCanOutputGain,
+ kAsioCanOutputMeter
+};
+
+typedef struct ASIOInputMonitor
+{
+ long input; // this input was set to monitor (or off), -1: all
+ long output; // suggested output for monitoring the input (if so)
+ long gain; // suggested gain, ranging 0 - 0x7fffffffL (-inf to +12 dB)
+ ASIOBool state; // ASIOTrue => on, ASIOFalse => off
+ long pan; // suggested pan, 0 => all left, 0x7fffffff => right
+} ASIOInputMonitor;
+
+typedef struct ASIOChannelControls
+{
+ long channel; // on input, channel index
+ ASIOBool isInput; // on input
+ long gain; // on input, ranges 0 thru 0x7fffffff
+ long meter; // on return, ranges 0 thru 0x7fffffff
+ char future[32];
+} ASIOChannelControls;
+
+typedef struct ASIOTransportParameters
+{
+ long command; // see enum below
+ ASIOSamples samplePosition;
+ long track;
+ long trackSwitches[16]; // 512 tracks on/off
+ char future[64];
+} ASIOTransportParameters;
+
+enum
+{
+ kTransStart = 1,
+ kTransStop,
+ kTransLocate, // to samplePosition
+ kTransPunchIn,
+ kTransPunchOut,
+ kTransArmOn, // track
+ kTransArmOff, // track
+ kTransMonitorOn, // track
+ kTransMonitorOff, // track
+ kTransArm, // trackSwitches
+ kTransMonitor // trackSwitches
+};
+
+ASIOError ASIOOutputReady(void);
+/* Purpose:
+ this tells the driver that the host has completed processing
+ the output buffers. if the data format required by the hardware
+ differs from the supported asio formats, but the hardware
+ buffers are DMA buffers, the driver will have to convert
+ the audio stream data; as the bufferSwitch callback is
+ usually issued at dma block switch time, the driver will
+ have to convert the *previous* host buffer, which increases
+ the output latency by one block.
+ when the host finds out that ASIOOutputReady() returns
+ true, it will issue this call whenever it completed
+ output processing. then the driver can convert the
+ host data directly to the dma buffer to be played next,
+ reducing output latency by one block.
+ another way to look at it is, that the buffer switch is called
+ in order to pass the *input* stream to the host, so that it can
+ process the input into the output, and the output stream is passed
+ to the driver when the host has completed its process.
+ Parameter:
+ None
+ Returns:
+ only if the above mentioned scenario is given, and a reduction
+ of output latency can be acheived by this mechanism, should
+ ASE_OK be returned. otherwise (and usually), ASE_NotPresent
+ should be returned in order to prevent further calls to this
+ function. note that the host may want to determine if it is
+ to use this when the system is not yet fully initialized, so
+ ASE_OK should always be returned if the mechanism makes sense.
+ Notes:
+ please remeber to adjust ASIOGetLatencies() according to
+ whether ASIOOutputReady() was ever called or not, if your
+ driver supports this scenario.
+ also note that the engine may fail to call ASIO_OutputReady()
+ in time in overload cases. as already mentioned, bufferSwitch
+ should be called for every block regardless of whether a block
+ could be processed in time.
+*/
+
+// restore old alignment
+#if defined(_MSC_VER) && !defined(__MWERKS__)
+#pragma pack(pop)
+#elif PRAGMA_ALIGN_SUPPORTED
+#pragma options align = reset
+#endif
+
+#endif
+
diff --git a/tests/asio/asiodrivers.cpp b/tests/asio/asiodrivers.cpp
new file mode 100644
index 0000000..5f56454
--- /dev/null
+++ b/tests/asio/asiodrivers.cpp
@@ -0,0 +1,186 @@
+#include <string.h>
+#include "asiodrivers.h"
+
+AsioDrivers* asioDrivers = 0;
+
+bool loadAsioDriver(char *name);
+
+bool loadAsioDriver(char *name)
+{
+ if(!asioDrivers)
+ asioDrivers = new AsioDrivers();
+ if(asioDrivers)
+ return asioDrivers->loadDriver(name);
+ return false;
+}
+
+//------------------------------------------------------------------------------------
+
+#if MAC
+
+bool resolveASIO(unsigned long aconnID);
+
+AsioDrivers::AsioDrivers() : CodeFragments("ASIO Drivers", 'AsDr', 'Asio')
+{
+ connID = -1;
+ curIndex = -1;
+}
+
+AsioDrivers::~AsioDrivers()
+{
+ removeCurrentDriver();
+}
+
+bool AsioDrivers::getCurrentDriverName(char *name)
+{
+ if(curIndex >= 0)
+ return getName(curIndex, name);
+ return false;
+}
+
+long AsioDrivers::getDriverNames(char **names, long maxDrivers)
+{
+ for(long i = 0; i < getNumFragments() && i < maxDrivers; i++)
+ getName(i, names[i]);
+ return getNumFragments() < maxDrivers ? getNumFragments() : maxDrivers;
+}
+
+bool AsioDrivers::loadDriver(char *name)
+{
+ char dname[64];
+ unsigned long newID;
+
+ for(long i = 0; i < getNumFragments(); i++)
+ {
+ if(getName(i, dname) && !strcmp(name, dname))
+ {
+ if(newInstance(i, &newID))
+ {
+ if(resolveASIO(newID))
+ {
+ if(connID != -1)
+ removeInstance(curIndex, connID);
+ curIndex = i;
+ connID = newID;
+ return true;
+ }
+ }
+ break;
+ }
+ }
+ return false;
+}
+
+void AsioDrivers::removeCurrentDriver()
+{
+ if(connID != -1)
+ removeInstance(curIndex, connID);
+ connID = -1;
+ curIndex = -1;
+}
+
+//------------------------------------------------------------------------------------
+
+#elif WINDOWS
+
+#include "iasiodrv.h"
+
+extern IASIO* theAsioDriver;
+
+AsioDrivers::AsioDrivers() : AsioDriverList()
+{
+ curIndex = -1;
+}
+
+AsioDrivers::~AsioDrivers()
+{
+}
+
+bool AsioDrivers::getCurrentDriverName(char *name)
+{
+ if(curIndex >= 0)
+ return asioGetDriverName(curIndex, name, 32) == 0 ? true : false;
+ name[0] = 0;
+ return false;
+}
+
+long AsioDrivers::getDriverNames(char **names, long maxDrivers)
+{
+ for(long i = 0; i < asioGetNumDev() && i < maxDrivers; i++)
+ asioGetDriverName(i, names[i], 32);
+ return asioGetNumDev() < maxDrivers ? asioGetNumDev() : maxDrivers;
+}
+
+bool AsioDrivers::loadDriver(char *name)
+{
+ char dname[64];
+ char curName[64];
+
+ for(long i = 0; i < asioGetNumDev(); i++)
+ {
+ if(!asioGetDriverName(i, dname, 32) && !strcmp(name, dname))
+ {
+ curName[0] = 0;
+ getCurrentDriverName(curName); // in case we fail...
+ removeCurrentDriver();
+
+ if(!asioOpenDriver(i, (void **)&theAsioDriver))
+ {
+ curIndex = i;
+ return true;
+ }
+ else
+ {
+ theAsioDriver = 0;
+ if(curName[0] && strcmp(dname, curName))
+ loadDriver(curName); // try restore
+ }
+ break;
+ }
+ }
+ return false;
+}
+
+void AsioDrivers::removeCurrentDriver()
+{
+ if(curIndex != -1)
+ asioCloseDriver(curIndex);
+ curIndex = -1;
+}
+
+#elif SGI || BEOS
+
+#include "asiolist.h"
+
+AsioDrivers::AsioDrivers()
+ : AsioDriverList()
+{
+ curIndex = -1;
+}
+
+AsioDrivers::~AsioDrivers()
+{
+}
+
+bool AsioDrivers::getCurrentDriverName(char *name)
+{
+ return false;
+}
+
+long AsioDrivers::getDriverNames(char **names, long maxDrivers)
+{
+ return 0;
+}
+
+bool AsioDrivers::loadDriver(char *name)
+{
+ return false;
+}
+
+void AsioDrivers::removeCurrentDriver()
+{
+}
+
+#else
+#error implement me
+#endif
diff --git a/tests/asio/asiodrivers.h b/tests/asio/asiodrivers.h
new file mode 100644
index 0000000..2ddf7ad
--- /dev/null
+++ b/tests/asio/asiodrivers.h
@@ -0,0 +1,41 @@
+#ifndef __AsioDrivers__
+#define __AsioDrivers__
+
+#include "ginclude.h"
+
+#if MAC
+#include "CodeFragments.hpp"
+
+class AsioDrivers : public CodeFragments
+
+#elif WINDOWS
+#include <windows.h>
+#include "asiolist.h"
+
+class AsioDrivers : public AsioDriverList
+
+#elif SGI || BEOS
+#include "asiolist.h"
+
+class AsioDrivers : public AsioDriverList
+
+#else
+#error implement me
+#endif
+
+{
+public:
+ AsioDrivers();
+ ~AsioDrivers();
+
+ bool getCurrentDriverName(char *name);
+ long getDriverNames(char **names, long maxDrivers);
+ bool loadDriver(char *name);
+ void removeCurrentDriver();
+ long getCurrentDriverIndex() {return curIndex;}
+protected:
+ unsigned long connID;
+ long curIndex;
+};
+
+#endif
diff --git a/tests/asio/asiodrvr.h b/tests/asio/asiodrvr.h
new file mode 100644
index 0000000..663f75a
--- /dev/null
+++ b/tests/asio/asiodrvr.h
@@ -0,0 +1,76 @@
+/*
+ Steinberg Audio Stream I/O API
+ (c) 1996, Steinberg Soft- und Hardware GmbH
+ charlie (May 1996)
+
+ asiodrvr.h
+ c++ superclass to implement asio functionality. from this,
+ you can derive whatever required
+*/
+
+#ifndef _asiodrvr_
+#define _asiodrvr_
+
+// cpu and os system we are running on
+#include "asiosys.h"
+// basic "C" interface
+#include "asio.h"
+
+class AsioDriver;
+extern AsioDriver *getDriver(); // for generic constructor
+
+#if WINDOWS
+#include <windows.h>
+#include "combase.h"
+#include "iasiodrv.h"
+class AsioDriver : public IASIO ,public CUnknown
+{
+public:
+ AsioDriver(LPUNKNOWN pUnk, HRESULT *phr);
+
+ DECLARE_IUNKNOWN
+ // Factory method
+ static CUnknown *CreateInstance(LPUNKNOWN pUnk, HRESULT *phr);
+ // IUnknown
+ virtual HRESULT STDMETHODCALLTYPE NonDelegatingQueryInterface(REFIID riid,void **ppvObject);
+
+#else
+
+class AsioDriver
+{
+public:
+ AsioDriver();
+#endif
+ virtual ~AsioDriver();
+
+ virtual ASIOBool init(void* sysRef);
+ virtual void getDriverName(char *name); // max 32 bytes incl. terminating zero
+ virtual long getDriverVersion();
+ virtual void getErrorMessage(char *string); // max 124 bytes incl.
+
+ virtual ASIOError start();
+ virtual ASIOError stop();
+
+ virtual ASIOError getChannels(long *numInputChannels, long *numOutputChannels);
+ virtual ASIOError getLatencies(long *inputLatency, long *outputLatency);
+ virtual ASIOError getBufferSize(long *minSize, long *maxSize,
+ long *preferredSize, long *granularity);
+
+ virtual ASIOError canSampleRate(ASIOSampleRate sampleRate);
+ virtual ASIOError getSampleRate(ASIOSampleRate *sampleRate);
+ virtual ASIOError setSampleRate(ASIOSampleRate sampleRate);
+ virtual ASIOError getClockSources(ASIOClockSource *clocks, long *numSources);
+ virtual ASIOError setClockSource(long reference);
+
+ virtual ASIOError getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp);
+ virtual ASIOError getChannelInfo(ASIOChannelInfo *info);
+
+ virtual ASIOError createBuffers(ASIOBufferInfo *bufferInfos, long numChannels,
+ long bufferSize, ASIOCallbacks *callbacks);
+ virtual ASIOError disposeBuffers();
+
+ virtual ASIOError controlPanel();
+ virtual ASIOError future(long selector, void *opt);
+ virtual ASIOError outputReady();
+};
+#endif
diff --git a/tests/asio/asiolist.cpp b/tests/asio/asiolist.cpp
new file mode 100644
index 0000000..5a62f5b
--- /dev/null
+++ b/tests/asio/asiolist.cpp
@@ -0,0 +1,268 @@
+#include <windows.h>
+#include "iasiodrv.h"
+#include "asiolist.h"
+
+#define ASIODRV_DESC "description"
+#define INPROC_SERVER "InprocServer32"
+#define ASIO_PATH "software\\asio"
+#define COM_CLSID "clsid"
+
+// ******************************************************************
+// Local Functions
+// ******************************************************************
+static LONG findDrvPath (char *clsidstr,char *dllpath,int dllpathsize)
+{
+ HKEY hkEnum,hksub,hkpath;
+ char databuf[512];
+ LONG cr,rc = -1;
+ DWORD datatype,datasize;
+ DWORD index;
+ OFSTRUCT ofs;
+ HFILE hfile;
+ BOOL found = FALSE;
+
+ CharLowerBuff(clsidstr,strlen(clsidstr));
+ if ((cr = RegOpenKey(HKEY_CLASSES_ROOT,COM_CLSID,&hkEnum)) == ERROR_SUCCESS) {
+
+ index = 0;
+ while (cr == ERROR_SUCCESS && !found) {
+ cr = RegEnumKey(hkEnum,index++,(LPTSTR)databuf,512);
+ if (cr == ERROR_SUCCESS) {
+ CharLowerBuff(databuf,strlen(databuf));
+ if (!(strcmp(databuf,clsidstr))) {
+ if ((cr = RegOpenKeyEx(hkEnum,(LPCTSTR)databuf,0,KEY_READ,&hksub)) == ERROR_SUCCESS) {
+ if ((cr = RegOpenKeyEx(hksub,(LPCTSTR)INPROC_SERVER,0,KEY_READ,&hkpath)) == ERROR_SUCCESS) {
+ datatype = REG_SZ; datasize = (DWORD)dllpathsize;
+ cr = RegQueryValueEx(hkpath,0,0,&datatype,(LPBYTE)dllpath,&datasize);
+ if (cr == ERROR_SUCCESS) {
+ memset(&ofs,0,sizeof(OFSTRUCT));
+ ofs.cBytes = sizeof(OFSTRUCT);
+ hfile = OpenFile(dllpath,&ofs,OF_EXIST);
+ if (hfile) rc = 0;
+ }
+ RegCloseKey(hkpath);
+ }
+ RegCloseKey(hksub);
+ }
+ found = TRUE; // break out
+ }
+ }
+ }
+ RegCloseKey(hkEnum);
+ }
+ return rc;
+}
+
+
+static LPASIODRVSTRUCT newDrvStruct (HKEY hkey,char *keyname,int drvID,LPASIODRVSTRUCT lpdrv)
+{
+ HKEY hksub;
+ char databuf[256];
+ char dllpath[MAXPATHLEN];
+ WORD wData[100];
+ CLSID clsid;
+ DWORD datatype,datasize;
+ LONG cr,rc;
+
+ if (!lpdrv) {
+ if ((cr = RegOpenKeyEx(hkey,(LPCTSTR)keyname,0,KEY_READ,&hksub)) == ERROR_SUCCESS) {
+
+ datatype = REG_SZ; datasize = 256;
+ cr = RegQueryValueEx(hksub,COM_CLSID,0,&datatype,(LPBYTE)databuf,&datasize);
+ if (cr == ERROR_SUCCESS) {
+ rc = findDrvPath (databuf,dllpath,MAXPATHLEN);
+ if (rc == 0) {
+ lpdrv = new ASIODRVSTRUCT[1];
+ if (lpdrv) {
+ memset(lpdrv,0,sizeof(ASIODRVSTRUCT));
+ lpdrv->drvID = drvID;
+ MultiByteToWideChar(CP_ACP,0,(LPCSTR)databuf,-1,(LPWSTR)wData,100);
+ if ((cr = CLSIDFromString((LPOLESTR)wData,(LPCLSID)&clsid)) == S_OK) {
+ memcpy(&lpdrv->clsid,&clsid,sizeof(CLSID));
+ }
+
+ datatype = REG_SZ; datasize = 256;
+ cr = RegQueryValueEx(hksub,ASIODRV_DESC,0,&datatype,(LPBYTE)databuf,&datasize);
+ if (cr == ERROR_SUCCESS) {
+ strcpy(lpdrv->drvname,databuf);
+ }
+ else strcpy(lpdrv->drvname,keyname);
+ }
+ }
+ }
+ RegCloseKey(hksub);
+ }
+ }
+ else lpdrv->next = newDrvStruct(hkey,keyname,drvID+1,lpdrv->next);
+
+ return lpdrv;
+}
+
+static void deleteDrvStruct (LPASIODRVSTRUCT lpdrv)
+{
+ IASIO *iasio;
+
+ if (lpdrv != 0) {
+ deleteDrvStruct(lpdrv->next);
+ if (lpdrv->asiodrv) {
+ iasio = (IASIO *)lpdrv->asiodrv;
+ iasio->Release();
+ }
+ delete lpdrv;
+ }
+}
+
+
+static LPASIODRVSTRUCT getDrvStruct (int drvID,LPASIODRVSTRUCT lpdrv)
+{
+ while (lpdrv) {
+ if (lpdrv->drvID == drvID) return lpdrv;
+ lpdrv = lpdrv->next;
+ }
+ return 0;
+}
+// ******************************************************************
+
+
+// ******************************************************************
+// AsioDriverList
+// ******************************************************************
+AsioDriverList::AsioDriverList ()
+{
+ HKEY hkEnum = 0;
+ char keyname[MAXDRVNAMELEN];
+ LPASIODRVSTRUCT pdl;
+ LONG cr;
+ DWORD index = 0;
+ BOOL fin = FALSE;
+
+ numdrv = 0;
+ lpdrvlist = 0;
+
+ cr = RegOpenKey(HKEY_LOCAL_MACHINE,ASIO_PATH,&hkEnum);
+ while (cr == ERROR_SUCCESS) {
+ if ((cr = RegEnumKey(hkEnum,index++,(LPTSTR)keyname,MAXDRVNAMELEN))== ERROR_SUCCESS) {
+ lpdrvlist = newDrvStruct (hkEnum,keyname,0,lpdrvlist);
+ }
+ else fin = TRUE;
+ }
+ if (hkEnum) RegCloseKey(hkEnum);
+
+ pdl = lpdrvlist;
+ while (pdl) {
+ numdrv++;
+ pdl = pdl->next;
+ }
+
+ if (numdrv) CoInitialize(0); // initialize COM
+}
+
+AsioDriverList::~AsioDriverList ()
+{
+ if (numdrv) {
+ deleteDrvStruct(lpdrvlist);
+ CoUninitialize();
+ }
+}
+
+
+LONG AsioDriverList::asioGetNumDev (VOID)
+{
+ return (LONG)numdrv;
+}
+
+
+LONG AsioDriverList::asioOpenDriver (int drvID,LPVOID *asiodrv)
+{
+ LPASIODRVSTRUCT lpdrv = 0;
+ long rc;
+
+ if (!asiodrv) return DRVERR_INVALID_PARAM;
+
+ if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
+ if (!lpdrv->asiodrv) {
+ rc = CoCreateInstance(lpdrv->clsid,0,CLSCTX_INPROC_SERVER,lpdrv->clsid,asiodrv);
+ if (rc == S_OK) {
+ lpdrv->asiodrv = *asiodrv;
+ return 0;
+ }
+ // else if (rc == REGDB_E_CLASSNOTREG)
+ // strcpy (info->messageText, "Driver not registered in the Registration Database!");
+ }
+ else rc = DRVERR_DEVICE_ALREADY_OPEN;
+ }
+ else rc = DRVERR_DEVICE_NOT_FOUND;
+
+ return rc;
+}
+
+
+LONG AsioDriverList::asioCloseDriver (int drvID)
+{
+ LPASIODRVSTRUCT lpdrv = 0;
+ IASIO *iasio;
+
+ if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
+ if (lpdrv->asiodrv) {
+ iasio = (IASIO *)lpdrv->asiodrv;
+ iasio->Release();
+ lpdrv->asiodrv = 0;
+ }
+ }
+
+ return 0;
+}
+
+LONG AsioDriverList::asioGetDriverName (int drvID,char *drvname,int drvnamesize)
+{
+ LPASIODRVSTRUCT lpdrv = 0;
+
+ if (!drvname) return DRVERR_INVALID_PARAM;
+
+ if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
+ if (strlen(lpdrv->drvname) < (unsigned int)drvnamesize) {
+ strcpy(drvname,lpdrv->drvname);
+ }
+ else {
+ memcpy(drvname,lpdrv->drvname,drvnamesize-4);
+ drvname[drvnamesize-4] = '.';
+ drvname[drvnamesize-3] = '.';
+ drvname[drvnamesize-2] = '.';
+ drvname[drvnamesize-1] = 0;
+ }
+ return 0;
+ }
+ return DRVERR_DEVICE_NOT_FOUND;
+}
+
+LONG AsioDriverList::asioGetDriverPath (int drvID,char *dllpath,int dllpathsize)
+{
+ LPASIODRVSTRUCT lpdrv = 0;
+
+ if (!dllpath) return DRVERR_INVALID_PARAM;
+
+ if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
+ if (strlen(lpdrv->dllpath) < (unsigned int)dllpathsize) {
+ strcpy(dllpath,lpdrv->dllpath);
+ return 0;
+ }
+ dllpath[0] = 0;
+ return DRVERR_INVALID_PARAM;
+ }
+ return DRVERR_DEVICE_NOT_FOUND;
+}
+
+LONG AsioDriverList::asioGetDriverCLSID (int drvID,CLSID *clsid)
+{
+ LPASIODRVSTRUCT lpdrv = 0;
+
+ if (!clsid) return DRVERR_INVALID_PARAM;
+
+ if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
+ memcpy(clsid,&lpdrv->clsid,sizeof(CLSID));
+ return 0;
+ }
+ return DRVERR_DEVICE_NOT_FOUND;
+}
+
+
diff --git a/tests/asio/asiolist.h b/tests/asio/asiolist.h
new file mode 100644
index 0000000..01c64f0
--- /dev/null
+++ b/tests/asio/asiolist.h
@@ -0,0 +1,46 @@
+#ifndef __asiolist__
+#define __asiolist__
+
+#define DRVERR -5000
+#define DRVERR_INVALID_PARAM DRVERR-1
+#define DRVERR_DEVICE_ALREADY_OPEN DRVERR-2
+#define DRVERR_DEVICE_NOT_FOUND DRVERR-3
+
+#define MAXPATHLEN 512
+#define MAXDRVNAMELEN 128
+
+struct asiodrvstruct
+{
+ int drvID;
+ CLSID clsid;
+ char dllpath[MAXPATHLEN];
+ char drvname[MAXDRVNAMELEN];
+ LPVOID asiodrv;
+ struct asiodrvstruct *next;
+};
+
+typedef struct asiodrvstruct ASIODRVSTRUCT;
+typedef ASIODRVSTRUCT *LPASIODRVSTRUCT;
+
+class AsioDriverList {
+public:
+ AsioDriverList();
+ ~AsioDriverList();
+
+ LONG asioOpenDriver (int,VOID **);
+ LONG asioCloseDriver (int);
+
+ // nice to have
+ LONG asioGetNumDev (VOID);
+ LONG asioGetDriverName (int,char *,int);
+ LONG asioGetDriverPath (int,char *,int);
+ LONG asioGetDriverCLSID (int,CLSID *);
+
+ // or use directly access
+ LPASIODRVSTRUCT lpdrvlist;
+ int numdrv;
+};
+
+typedef class AsioDriverList *LPASIODRIVERLIST;
+
+#endif
diff --git a/tests/asio/asiosys.h b/tests/asio/asiosys.h
new file mode 100644
index 0000000..37f7a48
--- /dev/null
+++ b/tests/asio/asiosys.h
@@ -0,0 +1,82 @@
+#ifndef __asiosys__
+ #define __asiosys__
+
+ #ifdef WIN32
+ #undef MAC
+ #define PPC 0
+ #define WINDOWS 1
+ #define SGI 0
+ #define SUN 0
+ #define LINUX 0
+ #define BEOS 0
+
+ #define NATIVE_INT64 0
+ #define IEEE754_64FLOAT 1
+
+ #elif BEOS
+ #define MAC 0
+ #define PPC 0
+ #define WINDOWS 0
+ #define PC 0
+ #define SGI 0
+ #define SUN 0
+ #define LINUX 0
+
+ #define NATIVE_INT64 0
+ #define IEEE754_64FLOAT 1
+
+ #ifndef DEBUG
+ #define DEBUG 0
+ #if DEBUG
+ void DEBUGGERMESSAGE(char *string);
+ #else
+ #define DEBUGGERMESSAGE(a)
+ #endif
+ #endif
+
+ #elif SGI
+ #define MAC 0
+ #define PPC 0
+ #define WINDOWS 0
+ #define PC 0
+ #define SUN 0
+ #define LINUX 0
+ #define BEOS 0
+
+ #define NATIVE_INT64 0
+ #define IEEE754_64FLOAT 1
+
+ #ifndef DEBUG
+ #define DEBUG 0
+ #if DEBUG
+ void DEBUGGERMESSAGE(char *string);
+ #else
+ #define DEBUGGERMESSAGE(a)
+ #endif
+ #endif
+
+ #else // MAC
+
+ #define MAC 1
+ #define PPC 1
+ #define WINDOWS 0
+ #define PC 0
+ #define SGI 0
+ #define SUN 0
+ #define LINUX 0
+ #define BEOS 0
+
+ #define NATIVE_INT64 0
+ #define IEEE754_64FLOAT 1
+
+ #ifndef DEBUG
+ #define DEBUG 0
+ #if DEBUG
+ void DEBUGGERMESSAGE(char *string);
+ #else
+ #define DEBUGGERMESSAGE(a)
+ #endif
+ #endif
+ #endif
+
+#endif
diff --git a/tests/asio/call_inout.dsp b/tests/asio/call_inout.dsp
new file mode 100755
index 0000000..97cc4d9
--- /dev/null
+++ b/tests/asio/call_inout.dsp
@@ -0,0 +1,148 @@
+# Microsoft Developer Studio Project File - Name="call_inout" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=call_inout - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "call_inout.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "call_inout.mak" CFG="call_inout - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "call_inout - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "call_inout - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "call_inout - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "../../" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "call_inout - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /D "__RTAUDIO_DEBUG__" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "call_inout - Win32 Release"
+# Name "call_inout - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\asio.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiodrivers.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiolist.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\call_inout.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\RtAudio.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\asio.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiodrivers.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiodrvr.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiolist.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiosys.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ginclude.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\iasiodrv.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\RtAudio.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/tests/asio/call_saw.dsp b/tests/asio/call_saw.dsp
new file mode 100755
index 0000000..09fff2d
--- /dev/null
+++ b/tests/asio/call_saw.dsp
@@ -0,0 +1,148 @@
+# Microsoft Developer Studio Project File - Name="call_saw" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=call_saw - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "call_saw.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "call_saw.mak" CFG="call_saw - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "call_saw - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "call_saw - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "call_saw - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "../../" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "call_saw - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /D "__RTAUDIO_DEBUG__" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "call_saw - Win32 Release"
+# Name "call_saw - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\asio.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiodrivers.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiolist.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\call_saw.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\RtAudio.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\asio.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiodrivers.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiodrvr.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiolist.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiosys.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ginclude.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\iasiodrv.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\RtAudio.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/tests/asio/ginclude.h b/tests/asio/ginclude.h
new file mode 100644
index 0000000..b627dc2
--- /dev/null
+++ b/tests/asio/ginclude.h
@@ -0,0 +1,38 @@
+#ifndef __gInclude__
+#define __gInclude__
+
+#if SGI
+ #undef BEOS
+ #undef MAC
+ #undef WINDOWS
+ //
+ #define ASIO_BIG_ENDIAN 1
+ #define ASIO_CPU_MIPS 1
+#elif defined WIN32
+ #undef BEOS
+ #undef MAC
+ #undef SGI
+ #define WINDOWS 1
+ #define ASIO_LITTLE_ENDIAN 1
+ #define ASIO_CPU_X86 1
+#elif BEOS
+ #undef MAC
+ #undef SGI
+ #undef WINDOWS
+ #define ASIO_LITTLE_ENDIAN 1
+ #define ASIO_CPU_X86 1
+ //
+#else
+ #define MAC 1
+ #undef BEOS
+ #undef WINDOWS
+ #undef SGI
+ #define ASIO_BIG_ENDIAN 1
+ #define ASIO_CPU_PPC 1
+#endif
+
+// always
+#define NATIVE_INT64 0
+#define IEEE754_64FLOAT 1
+
+#endif // __gInclude__
diff --git a/tests/asio/iasiodrv.h b/tests/asio/iasiodrv.h
new file mode 100644
index 0000000..64d2dbb
--- /dev/null
+++ b/tests/asio/iasiodrv.h
@@ -0,0 +1,37 @@
+#include "asiosys.h"
+#include "asio.h"
+
+/* Forward Declarations */
+
+#ifndef __ASIODRIVER_FWD_DEFINED__
+#define __ASIODRIVER_FWD_DEFINED__
+typedef interface IASIO IASIO;
+#endif /* __ASIODRIVER_FWD_DEFINED__ */
+
+interface IASIO : public IUnknown
+{
+
+ virtual ASIOBool init(void *sysHandle) = 0;
+ virtual void getDriverName(char *name) = 0;
+ virtual long getDriverVersion() = 0;
+ virtual void getErrorMessage(char *string) = 0;
+ virtual ASIOError start() = 0;
+ virtual ASIOError stop() = 0;
+ virtual ASIOError getChannels(long *numInputChannels, long *numOutputChannels) = 0;
+ virtual ASIOError getLatencies(long *inputLatency, long *outputLatency) = 0;
+ virtual ASIOError getBufferSize(long *minSize, long *maxSize,
+ long *preferredSize, long *granularity) = 0;
+ virtual ASIOError canSampleRate(ASIOSampleRate sampleRate) = 0;
+ virtual ASIOError getSampleRate(ASIOSampleRate *sampleRate) = 0;
+ virtual ASIOError setSampleRate(ASIOSampleRate sampleRate) = 0;
+ virtual ASIOError getClockSources(ASIOClockSource *clocks, long *numSources) = 0;
+ virtual ASIOError setClockSource(long reference) = 0;
+ virtual ASIOError getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp) = 0;
+ virtual ASIOError getChannelInfo(ASIOChannelInfo *info) = 0;
+ virtual ASIOError createBuffers(ASIOBufferInfo *bufferInfos, long numChannels,
+ long bufferSize, ASIOCallbacks *callbacks) = 0;
+ virtual ASIOError disposeBuffers() = 0;
+ virtual ASIOError controlPanel() = 0;
+ virtual ASIOError future(long selector,void *opt) = 0;
+ virtual ASIOError outputReady() = 0;
+};
diff --git a/tests/asio/in_out.dsp b/tests/asio/in_out.dsp
new file mode 100755
index 0000000..a1036bc
--- /dev/null
+++ b/tests/asio/in_out.dsp
@@ -0,0 +1,148 @@
+# Microsoft Developer Studio Project File - Name="in_out" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=in_out - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "in_out.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "in_out.mak" CFG="in_out - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "in_out - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "in_out - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "in_out - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "../../" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "in_out - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /D "__RTAUDIO_DEBUG__" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "in_out - Win32 Release"
+# Name "in_out - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\asio.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiodrivers.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiolist.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\in_out.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\RtAudio.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\asio.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiodrivers.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiodrvr.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiolist.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiosys.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ginclude.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\iasiodrv.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\RtAudio.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/tests/asio/info.dsp b/tests/asio/info.dsp
new file mode 100755
index 0000000..1d18051
--- /dev/null
+++ b/tests/asio/info.dsp
@@ -0,0 +1,148 @@
+# Microsoft Developer Studio Project File - Name="info" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=info - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "info.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "info.mak" CFG="info - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "info - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "info - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "info - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "../../" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "info - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /D "__RTAUDIO_DEBUG__" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "info - Win32 Release"
+# Name "info - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\asio.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiodrivers.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiolist.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\info.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\RtAudio.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\asio.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiodrivers.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiodrvr.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiolist.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiosys.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ginclude.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\iasiodrv.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\RtAudio.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/tests/asio/play_raw.dsp b/tests/asio/play_raw.dsp
new file mode 100755
index 0000000..96ddffb
--- /dev/null
+++ b/tests/asio/play_raw.dsp
@@ -0,0 +1,148 @@
+# Microsoft Developer Studio Project File - Name="play_raw" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=play_raw - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "play_raw.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "play_raw.mak" CFG="play_raw - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "play_raw - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "play_raw - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "play_raw - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "../../" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "play_raw - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /D "__RTAUDIO_DEBUG__" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "play_raw - Win32 Release"
+# Name "play_raw - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\asio.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiodrivers.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiolist.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\play_raw.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\RtAudio.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\asio.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiodrivers.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiodrvr.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiolist.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiosys.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ginclude.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\iasiodrv.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\RtAudio.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/tests/asio/play_saw.dsp b/tests/asio/play_saw.dsp
new file mode 100755
index 0000000..7aab9f1
--- /dev/null
+++ b/tests/asio/play_saw.dsp
@@ -0,0 +1,148 @@
+# Microsoft Developer Studio Project File - Name="play_saw" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=play_saw - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "play_saw.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "play_saw.mak" CFG="play_saw - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "play_saw - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "play_saw - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "play_saw - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "../../" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "play_saw - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /D "__RTAUDIO_DEBUG__" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "play_saw - Win32 Release"
+# Name "play_saw - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\asio.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiodrivers.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiolist.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\play_saw.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\RtAudio.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\asio.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiodrivers.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiodrvr.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiolist.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiosys.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ginclude.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\iasiodrv.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\RtAudio.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/tests/asio/record_raw.dsp b/tests/asio/record_raw.dsp
new file mode 100755
index 0000000..f39827a
--- /dev/null
+++ b/tests/asio/record_raw.dsp
@@ -0,0 +1,148 @@
+# Microsoft Developer Studio Project File - Name="record_raw" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=record_raw - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "record_raw.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "record_raw.mak" CFG="record_raw - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "record_raw - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "record_raw - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "record_raw - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "../../" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "record_raw - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /D "__RTAUDIO_DEBUG__" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "record_raw - Win32 Release"
+# Name "record_raw - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\asio.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiodrivers.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiolist.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\record_raw.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\RtAudio.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\asio.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiodrivers.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiodrvr.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiolist.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\asiosys.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ginclude.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\iasiodrv.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\RtAudio.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/tests/asio/rtaudio.dsw b/tests/asio/rtaudio.dsw
new file mode 100755
index 0000000..c070e92
--- /dev/null
+++ b/tests/asio/rtaudio.dsw
@@ -0,0 +1,101 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "call_inout"=.\call_inout.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "call_saw"=.\call_saw.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "in_out"=.\in_out.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "info"=.\info.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "play_raw"=.\play_raw.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "play_saw"=.\play_saw.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "record_raw"=.\record_raw.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+