-//---------------------------------------------------------------------------------------------------\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