--- /dev/null
+//---------------------------------------------------------------------------------------------------\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