Merge 4.0.3 into releases
[rtaudio.git] / include / asio.h
diff --git a/include/asio.h b/include/asio.h
new file mode 100644 (file)
index 0000000..8ec811f
--- /dev/null
@@ -0,0 +1,1054 @@
+//---------------------------------------------------------------------------------------------------\r
+//---------------------------------------------------------------------------------------------------\r
+\r
+/*\r
+       Steinberg Audio Stream I/O API\r
+       (c) 1997 - 2005, Steinberg Media Technologies GmbH\r
+\r
+       ASIO Interface Specification v 2.1\r
+\r
+       2005 - Added support for DSD sample data (in cooperation with Sony)\r
+\r
+\r
+       basic concept is an i/o synchronous double-buffer scheme:\r
+       \r
+       on bufferSwitch(index == 0), host will read/write:\r
+\r
+               after ASIOStart(), the\r
+  read  first input buffer A (index 0)\r
+       |   will be invalid (empty)\r
+       *   ------------------------\r
+       |------------------------|-----------------------|\r
+       |                        |                       |\r
+       |  Input Buffer A (0)    |   Input Buffer B (1)  |\r
+       |                        |                       |\r
+       |------------------------|-----------------------|\r
+       |                        |                       |\r
+       |  Output Buffer A (0)   |   Output Buffer B (1) |\r
+       |                        |                       |\r
+       |------------------------|-----------------------|\r
+       *                        -------------------------\r
+       |                        before calling ASIOStart(),\r
+  write                      host will have filled output\r
+                             buffer B (index 1) already\r
+\r
+  *please* take special care of proper statement of input\r
+  and output latencies (see ASIOGetLatencies()), these\r
+  control sequencer sync accuracy\r
+\r
+*/\r
+\r
+//---------------------------------------------------------------------------------------------------\r
+//---------------------------------------------------------------------------------------------------\r
+\r
+/*\r
+\r
+prototypes summary:\r
+\r
+ASIOError ASIOInit(ASIODriverInfo *info);\r
+ASIOError ASIOExit(void);\r
+ASIOError ASIOStart(void);\r
+ASIOError ASIOStop(void);\r
+ASIOError ASIOGetChannels(long *numInputChannels, long *numOutputChannels);\r
+ASIOError ASIOGetLatencies(long *inputLatency, long *outputLatency);\r
+ASIOError ASIOGetBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity);\r
+ASIOError ASIOCanSampleRate(ASIOSampleRate sampleRate);\r
+ASIOError ASIOGetSampleRate(ASIOSampleRate *currentRate);\r
+ASIOError ASIOSetSampleRate(ASIOSampleRate sampleRate);\r
+ASIOError ASIOGetClockSources(ASIOClockSource *clocks, long *numSources);\r
+ASIOError ASIOSetClockSource(long reference);\r
+ASIOError ASIOGetSamplePosition (ASIOSamples *sPos, ASIOTimeStamp *tStamp);\r
+ASIOError ASIOGetChannelInfo(ASIOChannelInfo *info);\r
+ASIOError ASIOCreateBuffers(ASIOBufferInfo *bufferInfos, long numChannels,\r
+       long bufferSize, ASIOCallbacks *callbacks);\r
+ASIOError ASIODisposeBuffers(void);\r
+ASIOError ASIOControlPanel(void);\r
+void *ASIOFuture(long selector, void *params);\r
+ASIOError ASIOOutputReady(void);\r
+\r
+*/\r
+\r
+//---------------------------------------------------------------------------------------------------\r
+//---------------------------------------------------------------------------------------------------\r
+\r
+#ifndef __ASIO_H\r
+#define __ASIO_H\r
+\r
+// force 4 byte alignment\r
+#if defined(_MSC_VER) && !defined(__MWERKS__) \r
+#pragma pack(push,4)\r
+#elif PRAGMA_ALIGN_SUPPORTED\r
+#pragma options align = native\r
+#endif\r
+\r
+//- - - - - - - - - - - - - - - - - - - - - - - - -\r
+// Type definitions\r
+//- - - - - - - - - - - - - - - - - - - - - - - - -\r
+\r
+// number of samples data type is 64 bit integer\r
+#if NATIVE_INT64\r
+       typedef long long int ASIOSamples;\r
+#else\r
+       typedef struct ASIOSamples {\r
+               unsigned long hi;\r
+               unsigned long lo;\r
+       } ASIOSamples;\r
+#endif\r
+\r
+// Timestamp data type is 64 bit integer,\r
+// Time format is Nanoseconds.\r
+#if NATIVE_INT64\r
+       typedef long long int ASIOTimeStamp ;\r
+#else\r
+       typedef struct ASIOTimeStamp {\r
+               unsigned long hi;\r
+               unsigned long lo;\r
+       } ASIOTimeStamp;\r
+#endif\r
+\r
+// Samplerates are expressed in IEEE 754 64 bit double float,\r
+// native format as host computer\r
+#if IEEE754_64FLOAT\r
+       typedef double ASIOSampleRate;\r
+#else\r
+       typedef struct ASIOSampleRate {\r
+               char ieee[8];\r
+       } ASIOSampleRate;\r
+#endif\r
+\r
+// Boolean values are expressed as long\r
+typedef long ASIOBool;\r
+enum {\r
+       ASIOFalse = 0,\r
+       ASIOTrue = 1\r
+};\r
+\r
+// Sample Types are expressed as long\r
+typedef long ASIOSampleType;\r
+enum {\r
+       ASIOSTInt16MSB   = 0,\r
+       ASIOSTInt24MSB   = 1,           // used for 20 bits as well\r
+       ASIOSTInt32MSB   = 2,\r
+       ASIOSTFloat32MSB = 3,           // IEEE 754 32 bit float\r
+       ASIOSTFloat64MSB = 4,           // IEEE 754 64 bit double float\r
+\r
+       // these are used for 32 bit data buffer, with different alignment of the data inside\r
+       // 32 bit PCI bus systems can be more easily used with these\r
+       ASIOSTInt32MSB16 = 8,           // 32 bit data with 16 bit alignment\r
+       ASIOSTInt32MSB18 = 9,           // 32 bit data with 18 bit alignment\r
+       ASIOSTInt32MSB20 = 10,          // 32 bit data with 20 bit alignment\r
+       ASIOSTInt32MSB24 = 11,          // 32 bit data with 24 bit alignment\r
+       \r
+       ASIOSTInt16LSB   = 16,\r
+       ASIOSTInt24LSB   = 17,          // used for 20 bits as well\r
+       ASIOSTInt32LSB   = 18,\r
+       ASIOSTFloat32LSB = 19,          // IEEE 754 32 bit float, as found on Intel x86 architecture\r
+       ASIOSTFloat64LSB = 20,          // IEEE 754 64 bit double float, as found on Intel x86 architecture\r
+\r
+       // these are used for 32 bit data buffer, with different alignment of the data inside\r
+       // 32 bit PCI bus systems can more easily used with these\r
+       ASIOSTInt32LSB16 = 24,          // 32 bit data with 18 bit alignment\r
+       ASIOSTInt32LSB18 = 25,          // 32 bit data with 18 bit alignment\r
+       ASIOSTInt32LSB20 = 26,          // 32 bit data with 20 bit alignment\r
+       ASIOSTInt32LSB24 = 27,          // 32 bit data with 24 bit alignment\r
+\r
+       //      ASIO DSD format.\r
+       ASIOSTDSDInt8LSB1   = 32,               // DSD 1 bit data, 8 samples per byte. First sample in Least significant bit.\r
+       ASIOSTDSDInt8MSB1   = 33,               // DSD 1 bit data, 8 samples per byte. First sample in Most significant bit.\r
+       ASIOSTDSDInt8NER8       = 40,           // DSD 8 bit data, 1 sample per byte. No Endianness required.\r
+\r
+       ASIOSTLastEntry\r
+};\r
+\r
+/*-----------------------------------------------------------------------------\r
+// DSD operation and buffer layout\r
+// Definition by Steinberg/Sony Oxford.\r
+//\r
+// We have tried to treat DSD as PCM and so keep a consistant structure across\r
+// the ASIO interface.\r
+//\r
+// DSD's sample rate is normally referenced as a multiple of 44.1Khz, so\r
+// the standard sample rate is refered to as 64Fs (or 2.8224Mhz). We looked\r
+// at making a special case for DSD and adding a field to the ASIOFuture that\r
+// would allow the user to select the Over Sampleing Rate (OSR) as a seperate\r
+// entity but decided in the end just to treat it as a simple value of\r
+// 2.8224Mhz and use the standard interface to set it.\r
+//\r
+// The second problem was the "word" size, in PCM the word size is always a\r
+// greater than or equal to 8 bits (a byte). This makes life easy as we can\r
+// then pack the samples into the "natural" size for the machine.\r
+// In DSD the "word" size is 1 bit. This is not a major problem and can easily\r
+// be dealt with if we ensure that we always deal with a multiple of 8 samples.\r
+//\r
+// DSD brings with it another twist to the Endianness religion. How are the\r
+// samples packed into the byte. It would be nice to just say the most significant\r
+// bit is always the first sample, however there would then be a performance hit\r
+// on little endian machines. Looking at how some of the processing goes...\r
+// Little endian machines like the first sample to be in the Least Significant Bit,\r
+//   this is because when you write it to memory the data is in the correct format\r
+//   to be shifted in and out of the words.\r
+// Big endian machine prefer the first sample to be in the Most Significant Bit,\r
+//   again for the same reasion.\r
+//\r
+// And just when things were looking really muddy there is a proposed extension to\r
+// DSD that uses 8 bit word sizes. It does not care what endianness you use.\r
+//\r
+// Switching the driver between DSD and PCM mode\r
+// ASIOFuture allows for extending the ASIO API quite transparently.\r
+// See kAsioSetIoFormat, kAsioGetIoFormat, kAsioCanDoIoFormat\r
+//\r
+//-----------------------------------------------------------------------------*/\r
+\r
+\r
+//- - - - - - - - - - - - - - - - - - - - - - - - -\r
+// Error codes\r
+//- - - - - - - - - - - - - - - - - - - - - - - - -\r
+\r
+typedef long ASIOError;\r
+enum {\r
+       ASE_OK = 0,             // This value will be returned whenever the call succeeded\r
+       ASE_SUCCESS = 0x3f4847a0,       // unique success return value for ASIOFuture calls\r
+       ASE_NotPresent = -1000, // hardware input or output is not present or available\r
+       ASE_HWMalfunction,      // hardware is malfunctioning (can be returned by any ASIO function)\r
+       ASE_InvalidParameter,   // input parameter invalid\r
+       ASE_InvalidMode,        // hardware is in a bad mode or used in a bad mode\r
+       ASE_SPNotAdvancing,     // hardware is not running when sample position is inquired\r
+       ASE_NoClock,            // sample clock or rate cannot be determined or is not present\r
+       ASE_NoMemory            // not enough memory for completing the request\r
+};\r
+\r
+//---------------------------------------------------------------------------------------------------\r
+//---------------------------------------------------------------------------------------------------\r
+\r
+//- - - - - - - - - - - - - - - - - - - - - - - - -\r
+// Time Info support\r
+//- - - - - - - - - - - - - - - - - - - - - - - - -\r
+\r
+typedef struct ASIOTimeCode\r
+{       \r
+       double          speed;                  // speed relation (fraction of nominal speed)\r
+                                               // optional; set to 0. or 1. if not supported\r
+       ASIOSamples     timeCodeSamples;        // time in samples\r
+       unsigned long   flags;                  // some information flags (see below)\r
+       char future[64];\r
+} ASIOTimeCode;\r
+\r
+typedef enum ASIOTimeCodeFlags\r
+{\r
+       kTcValid                = 1,\r
+       kTcRunning              = 1 << 1,\r
+       kTcReverse              = 1 << 2,\r
+       kTcOnspeed              = 1 << 3,\r
+       kTcStill                = 1 << 4,\r
+       \r
+       kTcSpeedValid           = 1 << 8\r
+}  ASIOTimeCodeFlags;\r
+\r
+typedef struct AsioTimeInfo\r
+{\r
+       double          speed;                  // absolute speed (1. = nominal)\r
+       ASIOTimeStamp   systemTime;             // system time related to samplePosition, in nanoseconds\r
+                                               // on mac, must be derived from Microseconds() (not UpTime()!)\r
+                                               // on windows, must be derived from timeGetTime()\r
+       ASIOSamples     samplePosition;\r
+       ASIOSampleRate  sampleRate;             // current rate\r
+       unsigned long flags;                    // (see below)\r
+       char reserved[12];\r
+} AsioTimeInfo;\r
+\r
+typedef enum AsioTimeInfoFlags\r
+{\r
+       kSystemTimeValid        = 1,            // must always be valid\r
+       kSamplePositionValid    = 1 << 1,       // must always be valid\r
+       kSampleRateValid        = 1 << 2,\r
+       kSpeedValid             = 1 << 3,\r
+       \r
+       kSampleRateChanged      = 1 << 4,\r
+       kClockSourceChanged     = 1 << 5\r
+} AsioTimeInfoFlags;\r
+\r
+typedef struct ASIOTime                          // both input/output\r
+{\r
+       long reserved[4];                       // must be 0\r
+       struct AsioTimeInfo     timeInfo;       // required\r
+       struct ASIOTimeCode     timeCode;       // optional, evaluated if (timeCode.flags & kTcValid)\r
+} ASIOTime;\r
+\r
+/*\r
+\r
+using time info:\r
+it is recommended to use the new method with time info even if the asio\r
+device does not support timecode; continuous calls to ASIOGetSamplePosition\r
+and ASIOGetSampleRate are avoided, and there is a more defined relationship\r
+between callback time and the time info.\r
+\r
+see the example below.\r
+to initiate time info mode, after you have received the callbacks pointer in\r
+ASIOCreateBuffers, you will call the asioMessage callback with kAsioSupportsTimeInfo\r
+as the argument. if this returns 1, host has accepted time info mode.\r
+now host expects the new callback bufferSwitchTimeInfo to be used instead\r
+of the old bufferSwitch method. the ASIOTime structure is assumed to be valid\r
+and accessible until the callback returns.\r
+\r
+using time code:\r
+if the device supports reading time code, it will call host's asioMessage callback\r
+with kAsioSupportsTimeCode as the selector. it may then fill the according\r
+fields and set the kTcValid flag.\r
+host will call the future method with the kAsioEnableTimeCodeRead selector when\r
+it wants to enable or disable tc reading by the device. you should also support\r
+the kAsioCanTimeInfo and kAsioCanTimeCode selectors in ASIOFuture (see example).\r
+\r
+note:\r
+the AsioTimeInfo/ASIOTimeCode pair is supposed to work in both directions.\r
+as a matter of convention, the relationship between the sample\r
+position counter and the time code at buffer switch time is\r
+(ignoring offset between tc and sample pos when tc is running):\r
+\r
+on input:      sample 0 -> input  buffer sample 0 -> time code 0\r
+on output:     sample 0 -> output buffer sample 0 -> time code 0\r
+\r
+this means that for 'real' calculations, one has to take into account\r
+the according latencies.\r
+\r
+example:\r
+\r
+ASIOTime asioTime;\r
+\r
+in createBuffers()\r
+{\r
+       memset(&asioTime, 0, sizeof(ASIOTime));\r
+       AsioTimeInfo* ti = &asioTime.timeInfo;\r
+       ti->sampleRate = theSampleRate;\r
+       ASIOTimeCode* tc = &asioTime.timeCode;\r
+       tc->speed = 1.;\r
+       timeInfoMode = false;\r
+       canTimeCode = false;\r
+       if(callbacks->asioMessage(kAsioSupportsTimeInfo, 0, 0, 0) == 1)\r
+       {\r
+               timeInfoMode = true;\r
+#if kCanTimeCode\r
+               if(callbacks->asioMessage(kAsioSupportsTimeCode, 0, 0, 0) == 1)\r
+                       canTimeCode = true;\r
+#endif\r
+       }\r
+}\r
+\r
+void switchBuffers(long doubleBufferIndex, bool processNow)\r
+{\r
+       if(timeInfoMode)\r
+       {\r
+               AsioTimeInfo* ti = &asioTime.timeInfo;\r
+               ti->flags =     kSystemTimeValid | kSamplePositionValid | kSampleRateValid;\r
+               ti->systemTime = theNanoSeconds;\r
+               ti->samplePosition = theSamplePosition;\r
+               if(ti->sampleRate != theSampleRate)\r
+                       ti->flags |= kSampleRateChanged;\r
+               ti->sampleRate = theSampleRate;\r
+\r
+#if kCanTimeCode\r
+               if(canTimeCode && timeCodeEnabled)\r
+               {\r
+                       ASIOTimeCode* tc = &asioTime.timeCode;\r
+                       tc->timeCodeSamples = tcSamples;                                                // tc in samples\r
+                       tc->flags = kTcValid | kTcRunning | kTcOnspeed;                 // if so...\r
+               }\r
+               ASIOTime* bb = callbacks->bufferSwitchTimeInfo(&asioTime, doubleBufferIndex, processNow ? ASIOTrue : ASIOFalse);\r
+#else\r
+               callbacks->bufferSwitchTimeInfo(&asioTime, doubleBufferIndex, processNow ? ASIOTrue : ASIOFalse);\r
+#endif\r
+       }\r
+       else\r
+               callbacks->bufferSwitch(doubleBufferIndex, ASIOFalse);\r
+}\r
+\r
+ASIOError ASIOFuture(long selector, void *params)\r
+{\r
+       switch(selector)\r
+       {\r
+               case kAsioEnableTimeCodeRead:\r
+                       timeCodeEnabled = true;\r
+                       return ASE_SUCCESS;\r
+               case kAsioDisableTimeCodeRead:\r
+                       timeCodeEnabled = false;\r
+                       return ASE_SUCCESS;\r
+               case kAsioCanTimeInfo:\r
+                       return ASE_SUCCESS;\r
+               #if kCanTimeCode\r
+               case kAsioCanTimeCode:\r
+                       return ASE_SUCCESS;\r
+               #endif\r
+       }\r
+       return ASE_NotPresent;\r
+};\r
+\r
+*/\r
+\r
+//- - - - - - - - - - - - - - - - - - - - - - - - -\r
+// application's audio stream handler callbacks\r
+//- - - - - - - - - - - - - - - - - - - - - - - - -\r
+\r
+typedef struct ASIOCallbacks\r
+{\r
+       void (*bufferSwitch) (long doubleBufferIndex, ASIOBool directProcess);\r
+               // bufferSwitch indicates that both input and output are to be processed.\r
+               // the current buffer half index (0 for A, 1 for B) determines\r
+               // - the output buffer that the host should start to fill. the other buffer\r
+               //   will be passed to output hardware regardless of whether it got filled\r
+               //   in time or not.\r
+               // - the input buffer that is now filled with incoming data. Note that\r
+               //   because of the synchronicity of i/o, the input always has at\r
+               //   least one buffer latency in relation to the output.\r
+               // directProcess suggests to the host whether it should immedeately\r
+               // start processing (directProcess == ASIOTrue), or whether its process\r
+               // should be deferred because the call comes from a very low level\r
+               // (for instance, a high level priority interrupt), and direct processing\r
+               // would cause timing instabilities for the rest of the system. If in doubt,\r
+               // directProcess should be set to ASIOFalse.\r
+               // Note: bufferSwitch may be called at interrupt time for highest efficiency.\r
+\r
+       void (*sampleRateDidChange) (ASIOSampleRate sRate);\r
+               // gets called when the AudioStreamIO detects a sample rate change\r
+               // If sample rate is unknown, 0 is passed (for instance, clock loss\r
+               // when externally synchronized).\r
+\r
+       long (*asioMessage) (long selector, long value, void* message, double* opt);\r
+               // generic callback for various purposes, see selectors below.\r
+               // note this is only present if the asio version is 2 or higher\r
+\r
+       ASIOTime* (*bufferSwitchTimeInfo) (ASIOTime* params, long doubleBufferIndex, ASIOBool directProcess);\r
+               // new callback with time info. makes ASIOGetSamplePosition() and various\r
+               // calls to ASIOGetSampleRate obsolete,\r
+               // and allows for timecode sync etc. to be preferred; will be used if\r
+               // the driver calls asioMessage with selector kAsioSupportsTimeInfo.\r
+} ASIOCallbacks;\r
+\r
+// asioMessage selectors\r
+enum\r
+{\r
+       kAsioSelectorSupported = 1,     // selector in <value>, returns 1L if supported,\r
+                                                               // 0 otherwise\r
+    kAsioEngineVersion,                        // returns engine (host) asio implementation version,\r
+                                                               // 2 or higher\r
+       kAsioResetRequest,                      // request driver reset. if accepted, this\r
+                                                               // will close the driver (ASIO_Exit() ) and\r
+                                                               // re-open it again (ASIO_Init() etc). some\r
+                                                               // drivers need to reconfigure for instance\r
+                                                               // when the sample rate changes, or some basic\r
+                                                               // changes have been made in ASIO_ControlPanel().\r
+                                                               // returns 1L; note the request is merely passed\r
+                                                               // to the application, there is no way to determine\r
+                                                               // if it gets accepted at this time (but it usually\r
+                                                               // will be).\r
+       kAsioBufferSizeChange,          // not yet supported, will currently always return 0L.\r
+                                                               // for now, use kAsioResetRequest instead.\r
+                                                               // once implemented, the new buffer size is expected\r
+                                                               // in <value>, and on success returns 1L\r
+       kAsioResyncRequest,                     // the driver went out of sync, such that\r
+                                                               // the timestamp is no longer valid. this\r
+                                                               // is a request to re-start the engine and\r
+                                                               // slave devices (sequencer). returns 1 for ok,\r
+                                                               // 0 if not supported.\r
+       kAsioLatenciesChanged,          // the drivers latencies have changed. The engine\r
+                                                               // will refetch the latencies.\r
+       kAsioSupportsTimeInfo,          // if host returns true here, it will expect the\r
+                                                               // callback bufferSwitchTimeInfo to be called instead\r
+                                                               // of bufferSwitch\r
+       kAsioSupportsTimeCode,          // \r
+       kAsioMMCCommand,                        // unused - value: number of commands, message points to mmc commands\r
+       kAsioSupportsInputMonitor,      // kAsioSupportsXXX return 1 if host supports this\r
+       kAsioSupportsInputGain,     // unused and undefined\r
+       kAsioSupportsInputMeter,    // unused and undefined\r
+       kAsioSupportsOutputGain,    // unused and undefined\r
+       kAsioSupportsOutputMeter,   // unused and undefined\r
+       kAsioOverload,              // driver detected an overload\r
+\r
+       kAsioNumMessageSelectors\r
+};\r
+\r
+//---------------------------------------------------------------------------------------------------\r
+//---------------------------------------------------------------------------------------------------\r
+\r
+//- - - - - - - - - - - - - - - - - - - - - - - - -\r
+// (De-)Construction\r
+//- - - - - - - - - - - - - - - - - - - - - - - - -\r
+\r
+typedef struct ASIODriverInfo\r
+{\r
+       long asioVersion;               // currently, 2\r
+       long driverVersion;             // driver specific\r
+       char name[32];\r
+       char errorMessage[124];\r
+       void *sysRef;                   // on input: system reference\r
+                                                       // (Windows: application main window handle, Mac & SGI: 0)\r
+} ASIODriverInfo;\r
+\r
+ASIOError ASIOInit(ASIODriverInfo *info);\r
+/* Purpose:\r
+         Initialize the AudioStreamIO.\r
+       Parameter:\r
+         info: pointer to an ASIODriver structure:\r
+           - asioVersion:\r
+                       - on input, the host version. *** Note *** this is 0 for earlier asio\r
+                       implementations, and the asioMessage callback is implemeted\r
+                       only if asioVersion is 2 or greater. sorry but due to a design fault\r
+                       the driver doesn't have access to the host version in ASIOInit :-(\r
+                       added selector for host (engine) version in the asioMessage callback\r
+                       so we're ok from now on.\r
+                       - on return, asio implementation version.\r
+                         older versions are 1\r
+                         if you support this version (namely, ASIO_outputReady() )\r
+                         this should be 2 or higher. also see the note in\r
+                         ASIO_getTimeStamp() !\r
+           - version: on return, the driver version (format is driver specific)\r
+           - name: on return, a null-terminated string containing the driver's name\r
+               - error message: on return, should contain a user message describing\r
+                 the type of error that occured during ASIOInit(), if any.\r
+               - sysRef: platform specific\r
+       Returns:\r
+         If neither input nor output is present ASE_NotPresent\r
+         will be returned.\r
+         ASE_NoMemory, ASE_HWMalfunction are other possible error conditions\r
+*/\r
+\r
+ASIOError ASIOExit(void);\r
+/* Purpose:\r
+         Terminates the AudioStreamIO.\r
+       Parameter:\r
+         None.\r
+       Returns:\r
+         If neither input nor output is present ASE_NotPresent\r
+         will be returned.\r
+       Notes: this implies ASIOStop() and ASIODisposeBuffers(),\r
+         meaning that no host callbacks must be accessed after ASIOExit().\r
+*/\r
+\r
+//- - - - - - - - - - - - - - - - - - - - - - - - -\r
+// Start/Stop\r
+//- - - - - - - - - - - - - - - - - - - - - - - - -\r
+\r
+ASIOError ASIOStart(void);\r
+/* Purpose:\r
+         Start input and output processing synchronously.\r
+         This will\r
+         - reset the sample counter to zero\r
+         - start the hardware (both input and output)\r
+           The first call to the hosts' bufferSwitch(index == 0) then tells\r
+           the host to read from input buffer A (index 0), and start\r
+           processing to output buffer A while output buffer B (which\r
+           has been filled by the host prior to calling ASIOStart())\r
+           is possibly sounding (see also ASIOGetLatencies()) \r
+       Parameter:\r
+         None.\r
+       Returns:\r
+         If neither input nor output is present, ASE_NotPresent\r
+         will be returned.\r
+         If the hardware fails to start, ASE_HWMalfunction will be returned.\r
+       Notes:\r
+         There is no restriction on the time that ASIOStart() takes\r
+         to perform (that is, it is not considered a realtime trigger).\r
+*/\r
+\r
+ASIOError ASIOStop(void);\r
+/* Purpose:\r
+         Stops input and output processing altogether.\r
+       Parameter:\r
+         None.\r
+       Returns:\r
+         If neither input nor output is present ASE_NotPresent\r
+         will be returned.\r
+       Notes:\r
+         On return from ASIOStop(), the driver must in no\r
+         case call the hosts' bufferSwitch() routine.\r
+*/\r
+\r
+//- - - - - - - - - - - - - - - - - - - - - - - - -\r
+// Inquiry methods and sample rate\r
+//- - - - - - - - - - - - - - - - - - - - - - - - -\r
+\r
+ASIOError ASIOGetChannels(long *numInputChannels, long *numOutputChannels);\r
+/* Purpose:\r
+         Returns number of individual input/output channels.\r
+       Parameter:\r
+         numInputChannels will hold the number of available input channels\r
+         numOutputChannels will hold the number of available output channels\r
+       Returns:\r
+         If no input/output is present ASE_NotPresent will be returned.\r
+         If only inputs, or only outputs are available, the according\r
+         other parameter will be zero, and ASE_OK is returned.\r
+*/\r
+\r
+ASIOError ASIOGetLatencies(long *inputLatency, long *outputLatency);\r
+/* Purpose:\r
+         Returns the input and output latencies. This includes\r
+         device specific delays, like FIFOs etc.\r
+       Parameter:\r
+         inputLatency will hold the 'age' of the first sample frame\r
+         in the input buffer when the hosts reads it in bufferSwitch()\r
+         (this is theoretical, meaning it does not include the overhead\r
+         and delay between the actual physical switch, and the time\r
+         when bufferSitch() enters).\r
+         This will usually be the size of one block in sample frames, plus\r
+         device specific latencies.\r
+\r
+         outputLatency will specify the time between the buffer switch,\r
+         and the time when the next play buffer will start to sound.\r
+         The next play buffer is defined as the one the host starts\r
+         processing after (or at) bufferSwitch(), indicated by the\r
+         index parameter (0 for buffer A, 1 for buffer B).\r
+         It will usually be either one block, if the host writes directly\r
+         to a dma buffer, or two or more blocks if the buffer is 'latched' by\r
+         the driver. As an example, on ASIOStart(), the host will have filled\r
+         the play buffer at index 1 already; when it gets the callback (with\r
+         the parameter index == 0), this tells it to read from the input\r
+         buffer 0, and start to fill the play buffer 0 (assuming that now\r
+         play buffer 1 is already sounding). In this case, the output\r
+         latency is one block. If the driver decides to copy buffer 1\r
+         at that time, and pass it to the hardware at the next slot (which\r
+         is most commonly done, but should be avoided), the output latency\r
+         becomes two blocks instead, resulting in a total i/o latency of at least\r
+         3 blocks. As memory access is the main bottleneck in native dsp processing,\r
+         and to acheive less latency, it is highly recommended to try to avoid\r
+         copying (this is also why the driver is the owner of the buffers). To\r
+         summarize, the minimum i/o latency can be acheived if the input buffer\r
+         is processed by the host into the output buffer which will physically\r
+         start to sound on the next time slice. Also note that the host expects\r
+         the bufferSwitch() callback to be accessed for each time slice in order\r
+         to retain sync, possibly recursively; if it fails to process a block in\r
+         time, it will suspend its operation for some time in order to recover.\r
+       Returns:\r
+         If no input/output is present ASE_NotPresent will be returned.\r
+*/\r
+\r
+ASIOError ASIOGetBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity);\r
+/* Purpose:\r
+         Returns min, max, and preferred buffer sizes for input/output\r
+       Parameter:\r
+         minSize will hold the minimum buffer size\r
+         maxSize will hold the maxium possible buffer size\r
+         preferredSize will hold the preferred buffer size (a size which\r
+         best fits performance and hardware requirements)\r
+         granularity will hold the granularity at which buffer sizes\r
+         may differ. Usually, the buffer size will be a power of 2;\r
+         in this case, granularity will hold -1 on return, signalling\r
+         possible buffer sizes starting from minSize, increased in\r
+         powers of 2 up to maxSize.\r
+       Returns:\r
+         If no input/output is present ASE_NotPresent will be returned.\r
+       Notes:\r
+         When minimum and maximum buffer size are equal,\r
+         the preferred buffer size has to be the same value as well; granularity\r
+         should be 0 in this case.\r
+*/\r
+\r
+ASIOError ASIOCanSampleRate(ASIOSampleRate sampleRate);\r
+/* Purpose:\r
+         Inquires the hardware for the available sample rates.\r
+       Parameter:\r
+         sampleRate is the rate in question.\r
+       Returns:\r
+         If the inquired sample rate is not supported, ASE_NoClock will be returned.\r
+         If no input/output is present ASE_NotPresent will be returned.\r
+*/\r
+ASIOError ASIOGetSampleRate(ASIOSampleRate *currentRate);\r
+/* Purpose:\r
+         Get the current sample Rate.\r
+       Parameter:\r
+         currentRate will hold the current sample rate on return.\r
+       Returns:\r
+         If sample rate is unknown, sampleRate will be 0 and ASE_NoClock will be returned.\r
+         If no input/output is present ASE_NotPresent will be returned.\r
+       Notes:\r
+*/\r
+\r
+ASIOError ASIOSetSampleRate(ASIOSampleRate sampleRate);\r
+/* Purpose:\r
+         Set the hardware to the requested sample Rate. If sampleRate == 0,\r
+         enable external sync.\r
+       Parameter:\r
+         sampleRate: on input, the requested rate\r
+       Returns:\r
+         If sampleRate is unknown ASE_NoClock will be returned.\r
+         If the current clock is external, and sampleRate is != 0,\r
+         ASE_InvalidMode will be returned\r
+         If no input/output is present ASE_NotPresent will be returned.\r
+       Notes:\r
+*/\r
+\r
+typedef struct ASIOClockSource\r
+{\r
+       long index;                                     // as used for ASIOSetClockSource()\r
+       long associatedChannel;         // for instance, S/PDIF or AES/EBU\r
+       long associatedGroup;           // see channel groups (ASIOGetChannelInfo())\r
+       ASIOBool isCurrentSource;       // ASIOTrue if this is the current clock source\r
+       char name[32];                          // for user selection\r
+} ASIOClockSource;\r
+\r
+ASIOError ASIOGetClockSources(ASIOClockSource *clocks, long *numSources);\r
+/* Purpose:\r
+         Get the available external audio clock sources\r
+       Parameter:\r
+         clocks points to an array of ASIOClockSource structures:\r
+               - index: this is used to identify the clock source\r
+                 when ASIOSetClockSource() is accessed, should be\r
+                 an index counting from zero\r
+               - associatedInputChannel: the first channel of an associated\r
+                 input group, if any.\r
+               - associatedGroup: the group index of that channel.\r
+                 groups of channels are defined to seperate for\r
+                 instance analog, S/PDIF, AES/EBU, ADAT connectors etc,\r
+                 when present simultaniously. Note that associated channel\r
+                 is enumerated according to numInputs/numOutputs, means it\r
+                 is independant from a group (see also ASIOGetChannelInfo())\r
+                 inputs are associated to a clock if the physical connection\r
+                 transfers both data and clock (like S/PDIF, AES/EBU, or\r
+                 ADAT inputs). if there is no input channel associated with\r
+                 the clock source (like Word Clock, or internal oscillator), both\r
+                 associatedChannel and associatedGroup should be set to -1.\r
+               - isCurrentSource: on exit, ASIOTrue if this is the current clock\r
+                 source, ASIOFalse else\r
+               - name: a null-terminated string for user selection of the available sources.\r
+         numSources:\r
+             on input: the number of allocated array members\r
+             on output: the number of available clock sources, at least\r
+             1 (internal clock generator).\r
+       Returns:\r
+         If no input/output is present ASE_NotPresent will be returned.\r
+       Notes:\r
+*/\r
+\r
+ASIOError ASIOSetClockSource(long index);\r
+/* Purpose:\r
+         Set the audio clock source\r
+       Parameter:\r
+         index as obtained from an inquiry to ASIOGetClockSources()\r
+       Returns:\r
+         If no input/output is present ASE_NotPresent will be returned.\r
+         If the clock can not be selected because an input channel which\r
+         carries the current clock source is active, ASE_InvalidMode\r
+         *may* be returned (this depends on the properties of the driver\r
+         and/or hardware).\r
+       Notes:\r
+         Should *not* return ASE_NoClock if there is no clock signal present\r
+         at the selected source; this will be inquired via ASIOGetSampleRate().\r
+         It should call the host callback procedure sampleRateHasChanged(),\r
+         if the switch causes a sample rate change, or if no external clock\r
+         is present at the selected source.\r
+*/\r
+\r
+ASIOError ASIOGetSamplePosition (ASIOSamples *sPos, ASIOTimeStamp *tStamp);\r
+/* Purpose:\r
+         Inquires the sample position/time stamp pair.\r
+       Parameter:\r
+         sPos will hold the sample position on return. The sample\r
+         position is reset to zero when ASIOStart() gets called.\r
+         tStamp will hold the system time when the sample position\r
+         was latched.\r
+       Returns:\r
+         If no input/output is present, ASE_NotPresent will be returned.\r
+         If there is no clock, ASE_SPNotAdvancing will be returned.\r
+       Notes:\r
+\r
+         in order to be able to synchronise properly,\r
+         the sample position / time stamp pair must refer to the current block,\r
+         that is, the engine will call ASIOGetSamplePosition() in its bufferSwitch()\r
+         callback and expect the time for the current block. thus, when requested\r
+         in the very first bufferSwitch after ASIO_Start(), the sample position\r
+         should be zero, and the time stamp should refer to the very time where\r
+         the stream was started. it also means that the sample position must be\r
+         block aligned. the driver must ensure proper interpolation if the system\r
+         time can not be determined for the block position. the driver is responsible\r
+         for precise time stamps as it usually has most direct access to lower\r
+         level resources. proper behaviour of ASIO_GetSamplePosition() and ASIO_GetLatencies()\r
+         are essential for precise media synchronization!\r
+*/\r
+\r
+typedef struct ASIOChannelInfo\r
+{\r
+       long channel;                   // on input, channel index\r
+       ASIOBool isInput;               // on input\r
+       ASIOBool isActive;              // on exit\r
+       long channelGroup;              // dto\r
+       ASIOSampleType type;    // dto\r
+       char name[32];                  // dto\r
+} ASIOChannelInfo;\r
+\r
+ASIOError ASIOGetChannelInfo(ASIOChannelInfo *info);\r
+/* Purpose:\r
+         retreive information about the nature of a channel\r
+       Parameter:\r
+         info: pointer to a ASIOChannelInfo structure with\r
+               - channel: on input, the channel index of the channel in question.\r
+               - isInput: on input, ASIOTrue if info for an input channel is\r
+                 requested, else output\r
+               - channelGroup: on return, the channel group that the channel\r
+                 belongs to. For drivers which support different types of\r
+                 channels, like analog, S/PDIF, AES/EBU, ADAT etc interfaces,\r
+                 there should be a reasonable grouping of these types. Groups\r
+                 are always independant form a channel index, that is, a channel\r
+                 index always counts from 0 to numInputs/numOutputs regardless\r
+                 of the group it may belong to.\r
+                 There will always be at least one group (group 0). Please\r
+                 also note that by default, the host may decide to activate\r
+                 channels 0 and 1; thus, these should belong to the most\r
+                 useful type (analog i/o, if present).\r
+               - type: on return, contains the sample type of the channel\r
+               - isActive: on return, ASIOTrue if channel is active as it was\r
+                 installed by ASIOCreateBuffers(), ASIOFalse else\r
+               - name:  describing the type of channel in question. Used to allow\r
+                 for user selection, and enabling of specific channels. examples:\r
+             "Analog In", "SPDIF Out" etc\r
+       Returns:\r
+         If no input/output is present ASE_NotPresent will be returned.\r
+       Notes:\r
+         If possible, the string should be organised such that the first\r
+         characters are most significantly describing the nature of the\r
+         port, to allow for identification even if the view showing the\r
+         port name is too small to display more than 8 characters, for\r
+         instance.\r
+*/\r
+\r
+//- - - - - - - - - - - - - - - - - - - - - - - - -\r
+// Buffer preparation\r
+//- - - - - - - - - - - - - - - - - - - - - - - - -\r
+\r
+typedef struct ASIOBufferInfo\r
+{\r
+       ASIOBool isInput;                       // on input:  ASIOTrue: input, else output\r
+       long channelNum;                        // on input:  channel index\r
+       void *buffers[2];                       // on output: double buffer addresses\r
+} ASIOBufferInfo;\r
+\r
+ASIOError ASIOCreateBuffers(ASIOBufferInfo *bufferInfos, long numChannels,\r
+       long bufferSize, ASIOCallbacks *callbacks);\r
+\r
+/* Purpose:\r
+         Allocates input/output buffers for all input and output channels to be activated.\r
+       Parameter:\r
+         bufferInfos is a pointer to an array of ASIOBufferInfo structures:\r
+           - isInput: on input, ASIOTrue if the buffer is to be allocated\r
+             for an input, output buffer else\r
+           - channelNum: on input, the index of the channel in question\r
+             (counting from 0)\r
+           - buffers: on exit, 2 pointers to the halves of the channels' double-buffer.\r
+             the size of the buffer(s) of course depend on both the ASIOSampleType\r
+             as obtained from ASIOGetChannelInfo(), and bufferSize\r
+         numChannels is the sum of all input and output channels to be created;\r
+         thus bufferInfos is a pointer to an array of numChannels ASIOBufferInfo\r
+         structures.\r
+         bufferSize selects one of the possible buffer sizes as obtained from\r
+         ASIOGetBufferSizes().\r
+         callbacks is a pointer to an ASIOCallbacks structure.\r
+       Returns:\r
+         If not enough memory is available ASE_NoMemory will be returned.\r
+         If no input/output is present ASE_NotPresent will be returned.\r
+         If bufferSize is not supported, or one or more of the bufferInfos elements\r
+         contain invalid settings, ASE_InvalidMode will be returned.\r
+       Notes:\r
+         If individual channel selection is not possible but requested,\r
+         the driver has to handle this. namely, bufferSwitch() will only\r
+         have filled buffers of enabled outputs. If possible, processing\r
+         and buss activities overhead should be avoided for channels which\r
+         were not enabled here.\r
+*/\r
+\r
+ASIOError ASIODisposeBuffers(void);\r
+/* Purpose:\r
+         Releases all buffers for the device.\r
+       Parameter:\r
+         None.\r
+       Returns:\r
+         If no buffer were ever prepared, ASE_InvalidMode will be returned.\r
+         If no input/output is present ASE_NotPresent will be returned.\r
+       Notes:\r
+         This implies ASIOStop().\r
+*/\r
+\r
+ASIOError ASIOControlPanel(void);\r
+/* Purpose:\r
+         request the driver to start a control panel component\r
+         for device specific user settings. This will not be\r
+         accessed on some platforms (where the component is accessed\r
+         instead).\r
+       Parameter:\r
+         None.\r
+       Returns:\r
+         If no panel is available ASE_NotPresent will be returned.\r
+         Actually, the return code is ignored.\r
+       Notes:\r
+         if the user applied settings which require a re-configuration\r
+         of parts or all of the enigine and/or driver (such as a change of\r
+         the block size), the asioMessage callback can be used (see\r
+         ASIO_Callbacks).\r
+*/\r
+\r
+ASIOError ASIOFuture(long selector, void *params);\r
+/* Purpose:\r
+         various\r
+       Parameter:\r
+         selector: operation Code as to be defined. zero is reserved for\r
+         testing purposes.\r
+         params: depends on the selector; usually pointer to a structure\r
+         for passing and retreiving any type and amount of parameters.\r
+       Returns:\r
+         the return value is also selector dependant. if the selector\r
+         is unknown, ASE_InvalidParameter should be returned to prevent\r
+         further calls with this selector. on success, ASE_SUCCESS\r
+         must be returned (note: ASE_OK is *not* sufficient!)\r
+       Notes:\r
+         see selectors defined below.    \r
+*/\r
+\r
+enum\r
+{\r
+       kAsioEnableTimeCodeRead = 1,    // no arguments\r
+       kAsioDisableTimeCodeRead,               // no arguments\r
+       kAsioSetInputMonitor,                   // ASIOInputMonitor* in params\r
+       kAsioTransport,                                 // ASIOTransportParameters* in params\r
+       kAsioSetInputGain,                              // ASIOChannelControls* in params, apply gain\r
+       kAsioGetInputMeter,                             // ASIOChannelControls* in params, fill meter\r
+       kAsioSetOutputGain,                             // ASIOChannelControls* in params, apply gain\r
+       kAsioGetOutputMeter,                    // ASIOChannelControls* in params, fill meter\r
+       kAsioCanInputMonitor,                   // no arguments for kAsioCanXXX selectors\r
+       kAsioCanTimeInfo,\r
+       kAsioCanTimeCode,\r
+       kAsioCanTransport,\r
+       kAsioCanInputGain,\r
+       kAsioCanInputMeter,\r
+       kAsioCanOutputGain,\r
+       kAsioCanOutputMeter,\r
+\r
+       //      DSD support\r
+       //      The following extensions are required to allow switching\r
+       //      and control of the DSD subsystem.\r
+       kAsioSetIoFormat                        = 0x23111961,           /* ASIOIoFormat * in params.                    */\r
+       kAsioGetIoFormat                        = 0x23111983,           /* ASIOIoFormat * in params.                    */\r
+       kAsioCanDoIoFormat                      = 0x23112004,           /* ASIOIoFormat * in params.                    */\r
+};\r
+\r
+typedef struct ASIOInputMonitor\r
+{\r
+       long input;             // this input was set to monitor (or off), -1: all\r
+       long output;    // suggested output for monitoring the input (if so)\r
+       long gain;              // suggested gain, ranging 0 - 0x7fffffffL (-inf to +12 dB)\r
+       ASIOBool state; // ASIOTrue => on, ASIOFalse => off\r
+       long pan;               // suggested pan, 0 => all left, 0x7fffffff => right\r
+} ASIOInputMonitor;\r
+\r
+typedef struct ASIOChannelControls\r
+{\r
+       long channel;                   // on input, channel index\r
+       ASIOBool isInput;               // on input\r
+       long gain;                              // on input,  ranges 0 thru 0x7fffffff\r
+       long meter;                             // on return, ranges 0 thru 0x7fffffff\r
+       char future[32];\r
+} ASIOChannelControls;\r
+\r
+typedef struct ASIOTransportParameters\r
+{\r
+       long command;           // see enum below\r
+       ASIOSamples samplePosition;\r
+       long track;\r
+       long trackSwitches[16];         // 512 tracks on/off\r
+       char future[64];\r
+} ASIOTransportParameters;\r
+\r
+enum\r
+{\r
+       kTransStart = 1,\r
+       kTransStop,\r
+       kTransLocate,           // to samplePosition\r
+       kTransPunchIn,\r
+       kTransPunchOut,\r
+       kTransArmOn,            // track\r
+       kTransArmOff,           // track\r
+       kTransMonitorOn,        // track\r
+       kTransMonitorOff,       // track\r
+       kTransArm,                      // trackSwitches\r
+       kTransMonitor           // trackSwitches\r
+};\r
+\r
+/*\r
+// DSD support\r
+//     Some notes on how to use ASIOIoFormatType.\r
+//\r
+//     The caller will fill the format with the request types.\r
+//     If the board can do the request then it will leave the\r
+//     values unchanged. If the board does not support the\r
+//     request then it will change that entry to Invalid (-1)\r
+//\r
+//     So to request DSD then\r
+//\r
+//     ASIOIoFormat NeedThis={kASIODSDFormat};\r
+//\r
+//     if(ASE_SUCCESS != ASIOFuture(kAsioSetIoFormat,&NeedThis) ){\r
+//             // If the board did not accept one of the parameters then the\r
+//             // whole call will fail and the failing parameter will\r
+//             // have had its value changes to -1.\r
+//     }\r
+//\r
+// Note: Switching between the formats need to be done before the "prepared"\r
+// state (see ASIO 2 documentation) is entered.\r
+*/\r
+typedef long int ASIOIoFormatType;\r
+enum ASIOIoFormatType_e\r
+{\r
+       kASIOFormatInvalid = -1,\r
+       kASIOPCMFormat = 0,\r
+       kASIODSDFormat = 1,\r
+};\r
+\r
+typedef struct ASIOIoFormat_s\r
+{\r
+       ASIOIoFormatType        FormatType;\r
+       char                            future[512-sizeof(ASIOIoFormatType)];\r
+} ASIOIoFormat;\r
+\r
+\r
+ASIOError ASIOOutputReady(void);\r
+/* Purpose:\r
+         this tells the driver that the host has completed processing\r
+         the output buffers. if the data format required by the hardware\r
+         differs from the supported asio formats, but the hardware\r
+         buffers are DMA buffers, the driver will have to convert\r
+         the audio stream data; as the bufferSwitch callback is\r
+         usually issued at dma block switch time, the driver will\r
+         have to convert the *previous* host buffer, which increases\r
+         the output latency by one block.\r
+         when the host finds out that ASIOOutputReady() returns\r
+         true, it will issue this call whenever it completed\r
+         output processing. then the driver can convert the\r
+         host data directly to the dma buffer to be played next,\r
+         reducing output latency by one block.\r
+         another way to look at it is, that the buffer switch is called\r
+         in order to pass the *input* stream to the host, so that it can\r
+         process the input into the output, and the output stream is passed\r
+         to the driver when the host has completed its process.\r
+       Parameter:\r
+               None\r
+       Returns:\r
+         only if the above mentioned scenario is given, and a reduction\r
+         of output latency can be acheived by this mechanism, should\r
+         ASE_OK be returned. otherwise (and usually), ASE_NotPresent\r
+         should be returned in order to prevent further calls to this\r
+         function. note that the host may want to determine if it is\r
+         to use this when the system is not yet fully initialized, so\r
+         ASE_OK should always be returned if the mechanism makes sense.          \r
+       Notes:\r
+         please remeber to adjust ASIOGetLatencies() according to\r
+         whether ASIOOutputReady() was ever called or not, if your\r
+         driver supports this scenario.\r
+         also note that the engine may fail to call ASIO_OutputReady()\r
+         in time in overload cases. as already mentioned, bufferSwitch\r
+      should be called for every block regardless of whether a block\r
+      could be processed in time.\r
+*/\r
+\r
+// restore old alignment\r
+#if defined(_MSC_VER) && !defined(__MWERKS__) \r
+#pragma pack(pop)\r
+#elif PRAGMA_ALIGN_SUPPORTED\r
+#pragma options align = reset\r
+#endif\r
+\r
+#endif\r
+\r