30031306ee97e50dd97e61e34da2ec43a032f789
[rtaudio.git] / asio / asio.h
1 //---------------------------------------------------------------------------------------------------\r
2 //---------------------------------------------------------------------------------------------------\r
3 \r
4 /*\r
5         Steinberg Audio Stream I/O API\r
6         (c) 1997 - 1999, Steinberg Soft- und Hardware GmbH\r
7 \r
8         ASIO Interface Specification v 2.0\r
9 \r
10         basic concept is an i/o synchronous double-buffer scheme:\r
11         \r
12         on bufferSwitch(index == 0), host will read/write:\r
13 \r
14                 after ASIOStart(), the\r
15   read  first input buffer A (index 0)\r
16         |   will be invalid (empty)\r
17         *   ------------------------\r
18         |------------------------|-----------------------|\r
19         |                        |                       |\r
20         |  Input Buffer A (0)    |   Input Buffer B (1)  |\r
21         |                        |                       |\r
22         |------------------------|-----------------------|\r
23         |                        |                       |\r
24         |  Output Buffer A (0)   |   Output Buffer B (1) |\r
25         |                        |                       |\r
26         |------------------------|-----------------------|\r
27         *                        -------------------------\r
28         |                        before calling ASIOStart(),\r
29   write                      host will have filled output\r
30                              buffer B (index 1) already\r
31 \r
32   *please* take special care of proper statement of input\r
33   and output latencies (see ASIOGetLatencies()), these\r
34   control sequencer sync accuracy\r
35 \r
36 */\r
37 \r
38 //---------------------------------------------------------------------------------------------------\r
39 //---------------------------------------------------------------------------------------------------\r
40 \r
41 /*\r
42 \r
43 prototypes summary:\r
44 \r
45 ASIOError ASIOInit(ASIODriverInfo *info);\r
46 ASIOError ASIOExit(void);\r
47 ASIOError ASIOStart(void);\r
48 ASIOError ASIOStop(void);\r
49 ASIOError ASIOGetChannels(long *numInputChannels, long *numOutputChannels);\r
50 ASIOError ASIOGetLatencies(long *inputLatency, long *outputLatency);\r
51 ASIOError ASIOGetBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity);\r
52 ASIOError ASIOCanSampleRate(ASIOSampleRate sampleRate);\r
53 ASIOError ASIOGetSampleRate(ASIOSampleRate *currentRate);\r
54 ASIOError ASIOSetSampleRate(ASIOSampleRate sampleRate);\r
55 ASIOError ASIOGetClockSources(ASIOClockSource *clocks, long *numSources);\r
56 ASIOError ASIOSetClockSource(long reference);\r
57 ASIOError ASIOGetSamplePosition (ASIOSamples *sPos, ASIOTimeStamp *tStamp);\r
58 ASIOError ASIOGetChannelInfo(ASIOChannelInfo *info);\r
59 ASIOError ASIOCreateBuffers(ASIOBufferInfo *bufferInfos, long numChannels,\r
60         long bufferSize, ASIOCallbacks *callbacks);\r
61 ASIOError ASIODisposeBuffers(void);\r
62 ASIOError ASIOControlPanel(void);\r
63 void *ASIOFuture(long selector, void *params);\r
64 ASIOError ASIOOutputReady(void);\r
65 \r
66 */\r
67 \r
68 //---------------------------------------------------------------------------------------------------\r
69 //---------------------------------------------------------------------------------------------------\r
70 \r
71 #ifndef __ASIO_H\r
72 #define __ASIO_H\r
73 \r
74 // force 4 byte alignment\r
75 #if defined(_MSC_VER) && !defined(__MWERKS__) \r
76 #pragma pack(push,4)\r
77 #elif PRAGMA_ALIGN_SUPPORTED\r
78 #pragma options align = native\r
79 #endif\r
80 \r
81 //- - - - - - - - - - - - - - - - - - - - - - - - -\r
82 // Type definitions\r
83 //- - - - - - - - - - - - - - - - - - - - - - - - -\r
84 \r
85 // number of samples data type is 64 bit integer\r
86 #if NATIVE_INT64\r
87         typedef long long int ASIOSamples;\r
88 #else\r
89         typedef struct ASIOSamples {\r
90                 unsigned long hi;\r
91                 unsigned long lo;\r
92         } ASIOSamples;\r
93 #endif\r
94 \r
95 // Timestamp data type is 64 bit integer,\r
96 // Time format is Nanoseconds.\r
97 #if NATIVE_INT64\r
98         typedef long long int ASIOTimeStamp ;\r
99 #else\r
100         typedef struct ASIOTimeStamp {\r
101                 unsigned long hi;\r
102                 unsigned long lo;\r
103         } ASIOTimeStamp;\r
104 #endif\r
105 \r
106 // Samplerates are expressed in IEEE 754 64 bit double float,\r
107 // native format as host computer\r
108 #if IEEE754_64FLOAT\r
109         typedef double ASIOSampleRate;\r
110 #else\r
111         typedef struct ASIOSampleRate {\r
112                 char ieee[8];\r
113         } ASIOSampleRate;\r
114 #endif\r
115 \r
116 // Boolean values are expressed as long\r
117 typedef long ASIOBool;\r
118 enum {\r
119         ASIOFalse = 0,\r
120         ASIOTrue = 1\r
121 };\r
122 \r
123 // Sample Types are expressed as long\r
124 typedef long ASIOSampleType;\r
125 enum {\r
126         ASIOSTInt16MSB   = 0,\r
127         ASIOSTInt24MSB   = 1,           // used for 20 bits as well\r
128         ASIOSTInt32MSB   = 2,\r
129         ASIOSTFloat32MSB = 3,           // IEEE 754 32 bit float\r
130         ASIOSTFloat64MSB = 4,           // IEEE 754 64 bit double float\r
131 \r
132         // these are used for 32 bit data buffer, with different alignment of the data inside\r
133         // 32 bit PCI bus systems can be more easily used with these\r
134         ASIOSTInt32MSB16 = 8,           // 32 bit data with 18 bit alignment\r
135         ASIOSTInt32MSB18 = 9,           // 32 bit data with 18 bit alignment\r
136         ASIOSTInt32MSB20 = 10,          // 32 bit data with 20 bit alignment\r
137         ASIOSTInt32MSB24 = 11,          // 32 bit data with 24 bit alignment\r
138         \r
139         ASIOSTInt16LSB   = 16,\r
140         ASIOSTInt24LSB   = 17,          // used for 20 bits as well\r
141         ASIOSTInt32LSB   = 18,\r
142         ASIOSTFloat32LSB = 19,          // IEEE 754 32 bit float, as found on Intel x86 architecture\r
143         ASIOSTFloat64LSB = 20,          // IEEE 754 64 bit double float, as found on Intel x86 architecture\r
144 \r
145         // these are used for 32 bit data buffer, with different alignment of the data inside\r
146         // 32 bit PCI bus systems can more easily used with these\r
147         ASIOSTInt32LSB16 = 24,          // 32 bit data with 18 bit alignment\r
148         ASIOSTInt32LSB18 = 25,          // 32 bit data with 18 bit alignment\r
149         ASIOSTInt32LSB20 = 26,          // 32 bit data with 20 bit alignment\r
150         ASIOSTInt32LSB24 = 27           // 32 bit data with 24 bit alignment\r
151 };\r
152 \r
153 //- - - - - - - - - - - - - - - - - - - - - - - - -\r
154 // Error codes\r
155 //- - - - - - - - - - - - - - - - - - - - - - - - -\r
156 \r
157 typedef long ASIOError;\r
158 enum {\r
159         ASE_OK = 0,             // This value will be returned whenever the call succeeded\r
160         ASE_SUCCESS = 0x3f4847a0,       // unique success return value for ASIOFuture calls\r
161         ASE_NotPresent = -1000, // hardware input or output is not present or available\r
162         ASE_HWMalfunction,      // hardware is malfunctioning (can be returned by any ASIO function)\r
163         ASE_InvalidParameter,   // input parameter invalid\r
164         ASE_InvalidMode,        // hardware is in a bad mode or used in a bad mode\r
165         ASE_SPNotAdvancing,     // hardware is not running when sample position is inquired\r
166         ASE_NoClock,            // sample clock or rate cannot be determined or is not present\r
167         ASE_NoMemory            // not enough memory for completing the request\r
168 };\r
169 \r
170 //---------------------------------------------------------------------------------------------------\r
171 //---------------------------------------------------------------------------------------------------\r
172 \r
173 //- - - - - - - - - - - - - - - - - - - - - - - - -\r
174 // Time Info support\r
175 //- - - - - - - - - - - - - - - - - - - - - - - - -\r
176 \r
177 typedef struct ASIOTimeCode\r
178 {       \r
179         double          speed;                  // speed relation (fraction of nominal speed)\r
180                                                 // optional; set to 0. or 1. if not supported\r
181         ASIOSamples     timeCodeSamples;        // time in samples\r
182         unsigned long   flags;                  // some information flags (see below)\r
183         char future[64];\r
184 } ASIOTimeCode;\r
185 \r
186 typedef enum ASIOTimeCodeFlags\r
187 {\r
188         kTcValid                = 1,\r
189         kTcRunning              = 1 << 1,\r
190         kTcReverse              = 1 << 2,\r
191         kTcOnspeed              = 1 << 3,\r
192         kTcStill                = 1 << 4,\r
193         \r
194         kTcSpeedValid           = 1 << 8\r
195 }  ASIOTimeCodeFlags;\r
196 \r
197 typedef struct AsioTimeInfo\r
198 {\r
199         double          speed;                  // absolute speed (1. = nominal)\r
200         ASIOTimeStamp   systemTime;             // system time related to samplePosition, in nanoseconds\r
201                                                 // on mac, must be derived from Microseconds() (not UpTime()!)\r
202                                                 // on windows, must be derived from timeGetTime()\r
203         ASIOSamples     samplePosition;\r
204         ASIOSampleRate  sampleRate;             // current rate\r
205         unsigned long flags;                    // (see below)\r
206         char reserved[12];\r
207 } AsioTimeInfo;\r
208 \r
209 typedef enum AsioTimeInfoFlags\r
210 {\r
211         kSystemTimeValid        = 1,            // must always be valid\r
212         kSamplePositionValid    = 1 << 1,       // must always be valid\r
213         kSampleRateValid        = 1 << 2,\r
214         kSpeedValid             = 1 << 3,\r
215         \r
216         kSampleRateChanged      = 1 << 4,\r
217         kClockSourceChanged     = 1 << 5\r
218 } AsioTimeInfoFlags;\r
219 \r
220 typedef struct ASIOTime                          // both input/output\r
221 {\r
222         long reserved[4];                       // must be 0\r
223         struct AsioTimeInfo     timeInfo;       // required\r
224         struct ASIOTimeCode     timeCode;       // optional, evaluated if (timeCode.flags & kTcValid)\r
225 } ASIOTime;\r
226 \r
227 /*\r
228 \r
229 using time info:\r
230 it is recommended to use the new method with time info even if the asio\r
231 device does not support timecode; continuous calls to ASIOGetSamplePosition\r
232 and ASIOGetSampleRate are avoided, and there is a more defined relationship\r
233 between callback time and the time info.\r
234 \r
235 see the example below.\r
236 to initiate time info mode, after you have received the callbacks pointer in\r
237 ASIOCreateBuffers, you will call the asioMessage callback with kAsioSupportsTimeInfo\r
238 as the argument. if this returns 1, host has accepted time info mode.\r
239 now host expects the new callback bufferSwitchTimeInfo to be used instead\r
240 of the old bufferSwitch method. the ASIOTime structure is assumed to be valid\r
241 and accessible until the callback returns.\r
242 \r
243 using time code:\r
244 if the device supports reading time code, it will call host's asioMessage callback\r
245 with kAsioSupportsTimeCode as the selector. it may then fill the according\r
246 fields and set the kTcValid flag.\r
247 host will call the future method with the kAsioEnableTimeCodeRead selector when\r
248 it wants to enable or disable tc reading by the device. you should also support\r
249 the kAsioCanTimeInfo and kAsioCanTimeCode selectors in ASIOFuture (see example).\r
250 \r
251 note:\r
252 the AsioTimeInfo/ASIOTimeCode pair is supposed to work in both directions.\r
253 as a matter of convention, the relationship between the sample\r
254 position counter and the time code at buffer switch time is\r
255 (ignoring offset between tc and sample pos when tc is running):\r
256 \r
257 on input:       sample 0 -> input  buffer sample 0 -> time code 0\r
258 on output:      sample 0 -> output buffer sample 0 -> time code 0\r
259 \r
260 this means that for 'real' calculations, one has to take into account\r
261 the according latencies.\r
262 \r
263 example:\r
264 \r
265 ASIOTime asioTime;\r
266 \r
267 in createBuffers()\r
268 {\r
269         memset(&asioTime, 0, sizeof(ASIOTime));\r
270         AsioTimeInfo* ti = &asioTime.timeInfo;\r
271         ti->sampleRate = theSampleRate;\r
272         ASIOTimeCode* tc = &asioTime.timeCode;\r
273         tc->speed = 1.;\r
274         timeInfoMode = false;\r
275         canTimeCode = false;\r
276         if(callbacks->asioMessage(kAsioSupportsTimeInfo, 0, 0, 0) == 1)\r
277         {\r
278                 timeInfoMode = true;\r
279 #if kCanTimeCode\r
280                 if(callbacks->asioMessage(kAsioSupportsTimeCode, 0, 0, 0) == 1)\r
281                         canTimeCode = true;\r
282 #endif\r
283         }\r
284 }\r
285 \r
286 void switchBuffers(long doubleBufferIndex, bool processNow)\r
287 {\r
288         if(timeInfoMode)\r
289         {\r
290                 AsioTimeInfo* ti = &asioTime.timeInfo;\r
291                 ti->flags =     kSystemTimeValid | kSamplePositionValid | kSampleRateValid;\r
292                 ti->systemTime = theNanoSeconds;\r
293                 ti->samplePosition = theSamplePosition;\r
294                 if(ti->sampleRate != theSampleRate)\r
295                         ti->flags |= kSampleRateChanged;\r
296                 ti->sampleRate = theSampleRate;\r
297 \r
298 #if kCanTimeCode\r
299                 if(canTimeCode && timeCodeEnabled)\r
300                 {\r
301                         ASIOTimeCode* tc = &asioTime.timeCode;\r
302                         tc->timeCodeSamples = tcSamples;                                                // tc in samples\r
303                         tc->flags = kTcValid | kTcRunning | kTcOnspeed;                 // if so...\r
304                 }\r
305                 ASIOTime* bb = callbacks->bufferSwitchTimeInfo(&asioTime, doubleBufferIndex, processNow ? ASIOTrue : ASIOFalse);\r
306 #else\r
307                 callbacks->bufferSwitchTimeInfo(&asioTime, doubleBufferIndex, processNow ? ASIOTrue : ASIOFalse);\r
308 #endif\r
309         }\r
310         else\r
311                 callbacks->bufferSwitch(doubleBufferIndex, ASIOFalse);\r
312 }\r
313 \r
314 ASIOError ASIOFuture(long selector, void *params)\r
315 {\r
316         switch(selector)\r
317         {\r
318                 case kAsioEnableTimeCodeRead:\r
319                         timeCodeEnabled = true;\r
320                         return ASE_SUCCESS;\r
321                 case kAsioDisableTimeCodeRead:\r
322                         timeCodeEnabled = false;\r
323                         return ASE_SUCCESS;\r
324                 case kAsioCanTimeInfo:\r
325                         return ASE_SUCCESS;\r
326                 #if kCanTimeCode\r
327                 case kAsioCanTimeCode:\r
328                         return ASE_SUCCESS;\r
329                 #endif\r
330         }\r
331         return ASE_NotPresent;\r
332 };\r
333 \r
334 */\r
335 \r
336 //- - - - - - - - - - - - - - - - - - - - - - - - -\r
337 // application's audio stream handler callbacks\r
338 //- - - - - - - - - - - - - - - - - - - - - - - - -\r
339 \r
340 typedef struct ASIOCallbacks\r
341 {\r
342         void (*bufferSwitch) (long doubleBufferIndex, ASIOBool directProcess);\r
343                 // bufferSwitch indicates that both input and output are to be processed.\r
344                 // the current buffer half index (0 for A, 1 for B) determines\r
345                 // - the output buffer that the host should start to fill. the other buffer\r
346                 //   will be passed to output hardware regardless of whether it got filled\r
347                 //   in time or not.\r
348                 // - the input buffer that is now filled with incoming data. Note that\r
349                 //   because of the synchronicity of i/o, the input always has at\r
350                 //   least one buffer latency in relation to the output.\r
351                 // directProcess suggests to the host whether it should immedeately\r
352                 // start processing (directProcess == ASIOTrue), or whether its process\r
353                 // should be deferred because the call comes from a very low level\r
354                 // (for instance, a high level priority interrupt), and direct processing\r
355                 // would cause timing instabilities for the rest of the system. If in doubt,\r
356                 // directProcess should be set to ASIOFalse.\r
357                 // Note: bufferSwitch may be called at interrupt time for highest efficiency.\r
358 \r
359         void (*sampleRateDidChange) (ASIOSampleRate sRate);\r
360                 // gets called when the AudioStreamIO detects a sample rate change\r
361                 // If sample rate is unknown, 0 is passed (for instance, clock loss\r
362                 // when externally synchronized).\r
363 \r
364         long (*asioMessage) (long selector, long value, void* message, double* opt);\r
365                 // generic callback for various purposes, see selectors below.\r
366                 // note this is only present if the asio version is 2 or higher\r
367 \r
368         ASIOTime* (*bufferSwitchTimeInfo) (ASIOTime* params, long doubleBufferIndex, ASIOBool directProcess);\r
369                 // new callback with time info. makes ASIOGetSamplePosition() and various\r
370                 // calls to ASIOGetSampleRate obsolete,\r
371                 // and allows for timecode sync etc. to be preferred; will be used if\r
372                 // the driver calls asioMessage with selector kAsioSupportsTimeInfo.\r
373 } ASIOCallbacks;\r
374 \r
375 // asioMessage selectors\r
376 enum\r
377 {\r
378         kAsioSelectorSupported = 1,     // selector in <value>, returns 1L if supported,\r
379                                                                 // 0 otherwise\r
380     kAsioEngineVersion,                 // returns engine (host) asio implementation version,\r
381                                                                 // 2 or higher\r
382         kAsioResetRequest,                      // request driver reset. if accepted, this\r
383                                                                 // will close the driver (ASIO_Exit() ) and\r
384                                                                 // re-open it again (ASIO_Init() etc). some\r
385                                                                 // drivers need to reconfigure for instance\r
386                                                                 // when the sample rate changes, or some basic\r
387                                                                 // changes have been made in ASIO_ControlPanel().\r
388                                                                 // returns 1L; note the request is merely passed\r
389                                                                 // to the application, there is no way to determine\r
390                                                                 // if it gets accepted at this time (but it usually\r
391                                                                 // will be).\r
392         kAsioBufferSizeChange,          // not yet supported, will currently always return 0L.\r
393                                                                 // for now, use kAsioResetRequest instead.\r
394                                                                 // once implemented, the new buffer size is expected\r
395                                                                 // in <value>, and on success returns 1L\r
396         kAsioResyncRequest,                     // the driver went out of sync, such that\r
397                                                                 // the timestamp is no longer valid. this\r
398                                                                 // is a request to re-start the engine and\r
399                                                                 // slave devices (sequencer). returns 1 for ok,\r
400                                                                 // 0 if not supported.\r
401         kAsioLatenciesChanged,          // the drivers latencies have changed. The engine\r
402                                                                 // will refetch the latencies.\r
403         kAsioSupportsTimeInfo,          // if host returns true here, it will expect the\r
404                                                                 // callback bufferSwitchTimeInfo to be called instead\r
405                                                                 // of bufferSwitch\r
406         kAsioSupportsTimeCode,          // supports time code reading/writing\r
407 \r
408         kAsioSupportsInputMonitor,      // supports input monitoring\r
409 \r
410         kAsioNumMessageSelectors\r
411 };\r
412 \r
413 //---------------------------------------------------------------------------------------------------\r
414 //---------------------------------------------------------------------------------------------------\r
415 \r
416 //- - - - - - - - - - - - - - - - - - - - - - - - -\r
417 // (De-)Construction\r
418 //- - - - - - - - - - - - - - - - - - - - - - - - -\r
419 \r
420 typedef struct ASIODriverInfo\r
421 {\r
422         long asioVersion;               // currently, 2\r
423         long driverVersion;             // driver specific\r
424         char name[32];\r
425         char errorMessage[124];\r
426         void *sysRef;                   // on input: system reference\r
427                                                         // (Windows: application main window handle, Mac & SGI: 0)\r
428 } ASIODriverInfo;\r
429 \r
430 ASIOError ASIOInit(ASIODriverInfo *info);\r
431 /* Purpose:\r
432           Initialize the AudioStreamIO.\r
433         Parameter:\r
434           info: pointer to an ASIODriver structure:\r
435             - asioVersion:\r
436                         - on input, the host version. *** Note *** this is 0 for earlier asio\r
437                         implementations, and the asioMessage callback is implemeted\r
438                         only if asioVersion is 2 or greater. sorry but due to a design fault\r
439                         the driver doesn't have access to the host version in ASIOInit :-(\r
440                         added selector for host (engine) version in the asioMessage callback\r
441                         so we're ok from now on.\r
442                         - on return, asio implementation version.\r
443                           older versions are 1\r
444                           if you support this version (namely, ASIO_outputReady() )\r
445                           this should be 2 or higher. also see the note in\r
446                           ASIO_getTimeStamp() !\r
447             - version: on return, the driver version (format is driver specific)\r
448             - name: on return, a null-terminated string containing the driver's name\r
449                 - error message: on return, should contain a user message describing\r
450                   the type of error that occured during ASIOInit(), if any.\r
451                 - sysRef: platform specific\r
452         Returns:\r
453           If neither input nor output is present ASE_NotPresent\r
454           will be returned.\r
455           ASE_NoMemory, ASE_HWMalfunction are other possible error conditions\r
456 */\r
457 \r
458 ASIOError ASIOExit(void);\r
459 /* Purpose:\r
460           Terminates the AudioStreamIO.\r
461         Parameter:\r
462           None.\r
463         Returns:\r
464           If neither input nor output is present ASE_NotPresent\r
465           will be returned.\r
466         Notes: this implies ASIOStop() and ASIODisposeBuffers(),\r
467           meaning that no host callbacks must be accessed after ASIOExit().\r
468 */\r
469 \r
470 //- - - - - - - - - - - - - - - - - - - - - - - - -\r
471 // Start/Stop\r
472 //- - - - - - - - - - - - - - - - - - - - - - - - -\r
473 \r
474 ASIOError ASIOStart(void);\r
475 /* Purpose:\r
476           Start input and output processing synchronously.\r
477           This will\r
478           - reset the sample counter to zero\r
479           - start the hardware (both input and output)\r
480             The first call to the hosts' bufferSwitch(index == 0) then tells\r
481             the host to read from input buffer A (index 0), and start\r
482             processing to output buffer A while output buffer B (which\r
483             has been filled by the host prior to calling ASIOStart())\r
484             is possibly sounding (see also ASIOGetLatencies()) \r
485         Parameter:\r
486           None.\r
487         Returns:\r
488           If neither input nor output is present, ASE_NotPresent\r
489           will be returned.\r
490           If the hardware fails to start, ASE_HWMalfunction will be returned.\r
491         Notes:\r
492           There is no restriction on the time that ASIOStart() takes\r
493           to perform (that is, it is not considered a realtime trigger).\r
494 */\r
495 \r
496 ASIOError ASIOStop(void);\r
497 /* Purpose:\r
498           Stops input and output processing altogether.\r
499         Parameter:\r
500           None.\r
501         Returns:\r
502           If neither input nor output is present ASE_NotPresent\r
503           will be returned.\r
504         Notes:\r
505           On return from ASIOStop(), the driver must in no\r
506           case call the hosts' bufferSwitch() routine.\r
507 */\r
508 \r
509 //- - - - - - - - - - - - - - - - - - - - - - - - -\r
510 // Inquiry methods and sample rate\r
511 //- - - - - - - - - - - - - - - - - - - - - - - - -\r
512 \r
513 ASIOError ASIOGetChannels(long *numInputChannels, long *numOutputChannels);\r
514 /* Purpose:\r
515           Returns number of individual input/output channels.\r
516         Parameter:\r
517           numInputChannels will hold the number of available input channels\r
518           numOutputChannels will hold the number of available output channels\r
519         Returns:\r
520           If no input/output is present ASE_NotPresent will be returned.\r
521           If only inputs, or only outputs are available, the according\r
522           other parameter will be zero, and ASE_OK is returned.\r
523 */\r
524 \r
525 ASIOError ASIOGetLatencies(long *inputLatency, long *outputLatency);\r
526 /* Purpose:\r
527           Returns the input and output latencies. This includes\r
528           device specific delays, like FIFOs etc.\r
529         Parameter:\r
530           inputLatency will hold the 'age' of the first sample frame\r
531           in the input buffer when the hosts reads it in bufferSwitch()\r
532           (this is theoretical, meaning it does not include the overhead\r
533           and delay between the actual physical switch, and the time\r
534           when bufferSitch() enters).\r
535           This will usually be the size of one block in sample frames, plus\r
536           device specific latencies.\r
537 \r
538           outputLatency will specify the time between the buffer switch,\r
539           and the time when the next play buffer will start to sound.\r
540           The next play buffer is defined as the one the host starts\r
541           processing after (or at) bufferSwitch(), indicated by the\r
542           index parameter (0 for buffer A, 1 for buffer B).\r
543           It will usually be either one block, if the host writes directly\r
544           to a dma buffer, or two or more blocks if the buffer is 'latched' by\r
545           the driver. As an example, on ASIOStart(), the host will have filled\r
546           the play buffer at index 1 already; when it gets the callback (with\r
547           the parameter index == 0), this tells it to read from the input\r
548           buffer 0, and start to fill the play buffer 0 (assuming that now\r
549           play buffer 1 is already sounding). In this case, the output\r
550           latency is one block. If the driver decides to copy buffer 1\r
551           at that time, and pass it to the hardware at the next slot (which\r
552           is most commonly done, but should be avoided), the output latency\r
553           becomes two blocks instead, resulting in a total i/o latency of at least\r
554           3 blocks. As memory access is the main bottleneck in native dsp processing,\r
555           and to acheive less latency, it is highly recommended to try to avoid\r
556           copying (this is also why the driver is the owner of the buffers). To\r
557           summarize, the minimum i/o latency can be acheived if the input buffer\r
558           is processed by the host into the output buffer which will physically\r
559           start to sound on the next time slice. Also note that the host expects\r
560           the bufferSwitch() callback to be accessed for each time slice in order\r
561           to retain sync, possibly recursively; if it fails to process a block in\r
562           time, it will suspend its operation for some time in order to recover.\r
563         Returns:\r
564           If no input/output is present ASE_NotPresent will be returned.\r
565 */\r
566 \r
567 ASIOError ASIOGetBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity);\r
568 /* Purpose:\r
569           Returns min, max, and preferred buffer sizes for input/output\r
570         Parameter:\r
571           minSize will hold the minimum buffer size\r
572           maxSize will hold the maxium possible buffer size\r
573           preferredSize will hold the preferred buffer size (a size which\r
574           best fits performance and hardware requirements)\r
575           granularity will hold the granularity at which buffer sizes\r
576           may differ. Usually, the buffer size will be a power of 2;\r
577           in this case, granularity will hold -1 on return, signalling\r
578           possible buffer sizes starting from minSize, increased in\r
579           powers of 2 up to maxSize.\r
580         Returns:\r
581           If no input/output is present ASE_NotPresent will be returned.\r
582         Notes:\r
583           When minimum and maximum buffer size are equal,\r
584           the preferred buffer size has to be the same value as well; granularity\r
585           should be 0 in this case.\r
586 */\r
587 \r
588 ASIOError ASIOCanSampleRate(ASIOSampleRate sampleRate);\r
589 /* Purpose:\r
590           Inquires the hardware for the available sample rates.\r
591         Parameter:\r
592           sampleRate is the rate in question.\r
593         Returns:\r
594           If the inquired sample rate is not supported, ASE_NoClock will be returned.\r
595           If no input/output is present ASE_NotPresent will be returned.\r
596 */\r
597 ASIOError ASIOGetSampleRate(ASIOSampleRate *currentRate);\r
598 /* Purpose:\r
599           Get the current sample Rate.\r
600         Parameter:\r
601           currentRate will hold the current sample rate on return.\r
602         Returns:\r
603           If sample rate is unknown, sampleRate will be 0 and ASE_NoClock will be returned.\r
604           If no input/output is present ASE_NotPresent will be returned.\r
605         Notes:\r
606 */\r
607 \r
608 ASIOError ASIOSetSampleRate(ASIOSampleRate sampleRate);\r
609 /* Purpose:\r
610           Set the hardware to the requested sample Rate. If sampleRate == 0,\r
611           enable external sync.\r
612         Parameter:\r
613           sampleRate: on input, the requested rate\r
614         Returns:\r
615           If sampleRate is unknown ASE_NoClock will be returned.\r
616           If the current clock is external, and sampleRate is != 0,\r
617           ASE_InvalidMode will be returned\r
618           If no input/output is present ASE_NotPresent will be returned.\r
619         Notes:\r
620 */\r
621 \r
622 typedef struct ASIOClockSource\r
623 {\r
624         long index;                                     // as used for ASIOSetClockSource()\r
625         long associatedChannel;         // for instance, S/PDIF or AES/EBU\r
626         long associatedGroup;           // see channel groups (ASIOGetChannelInfo())\r
627         ASIOBool isCurrentSource;       // ASIOTrue if this is the current clock source\r
628         char name[32];                          // for user selection\r
629 } ASIOClockSource;\r
630 \r
631 ASIOError ASIOGetClockSources(ASIOClockSource *clocks, long *numSources);\r
632 /* Purpose:\r
633           Get the available external audio clock sources\r
634         Parameter:\r
635           clocks points to an array of ASIOClockSource structures:\r
636                 - index: this is used to identify the clock source\r
637                   when ASIOSetClockSource() is accessed, should be\r
638                   an index counting from zero\r
639                 - associatedInputChannel: the first channel of an associated\r
640                   input group, if any.\r
641                 - associatedGroup: the group index of that channel.\r
642                   groups of channels are defined to seperate for\r
643                   instance analog, S/PDIF, AES/EBU, ADAT connectors etc,\r
644                   when present simultaniously. Note that associated channel\r
645                   is enumerated according to numInputs/numOutputs, means it\r
646                   is independant from a group (see also ASIOGetChannelInfo())\r
647                   inputs are associated to a clock if the physical connection\r
648                   transfers both data and clock (like S/PDIF, AES/EBU, or\r
649                   ADAT inputs). if there is no input channel associated with\r
650                   the clock source (like Word Clock, or internal oscillator), both\r
651                   associatedChannel and associatedGroup should be set to -1.\r
652                 - isCurrentSource: on exit, ASIOTrue if this is the current clock\r
653                   source, ASIOFalse else\r
654                 - name: a null-terminated string for user selection of the available sources.\r
655           numSources:\r
656               on input: the number of allocated array members\r
657               on output: the number of available clock sources, at least\r
658               1 (internal clock generator).\r
659         Returns:\r
660           If no input/output is present ASE_NotPresent will be returned.\r
661         Notes:\r
662 */\r
663 \r
664 ASIOError ASIOSetClockSource(long index);\r
665 /* Purpose:\r
666           Set the audio clock source\r
667         Parameter:\r
668           index as obtained from an inquiry to ASIOGetClockSources()\r
669         Returns:\r
670           If no input/output is present ASE_NotPresent will be returned.\r
671           If the clock can not be selected because an input channel which\r
672           carries the current clock source is active, ASE_InvalidMode\r
673           *may* be returned (this depends on the properties of the driver\r
674           and/or hardware).\r
675         Notes:\r
676           Should *not* return ASE_NoClock if there is no clock signal present\r
677           at the selected source; this will be inquired via ASIOGetSampleRate().\r
678           It should call the host callback procedure sampleRateHasChanged(),\r
679           if the switch causes a sample rate change, or if no external clock\r
680           is present at the selected source.\r
681 */\r
682 \r
683 ASIOError ASIOGetSamplePosition (ASIOSamples *sPos, ASIOTimeStamp *tStamp);\r
684 /* Purpose:\r
685           Inquires the sample position/time stamp pair.\r
686         Parameter:\r
687           sPos will hold the sample position on return. The sample\r
688           position is reset to zero when ASIOStart() gets called.\r
689           tStamp will hold the system time when the sample position\r
690           was latched.\r
691         Returns:\r
692           If no input/output is present, ASE_NotPresent will be returned.\r
693           If there is no clock, ASE_SPNotAdvancing will be returned.\r
694         Notes:\r
695 \r
696           in order to be able to synchronise properly,\r
697           the sample position / time stamp pair must refer to the current block,\r
698           that is, the engine will call ASIOGetSamplePosition() in its bufferSwitch()\r
699           callback and expect the time for the current block. thus, when requested\r
700           in the very first bufferSwitch after ASIO_Start(), the sample position\r
701           should be zero, and the time stamp should refer to the very time where\r
702           the stream was started. it also means that the sample position must be\r
703           block aligned. the driver must ensure proper interpolation if the system\r
704           time can not be determined for the block position. the driver is responsible\r
705           for precise time stamps as it usually has most direct access to lower\r
706           level resources. proper behaviour of ASIO_GetSamplePosition() and ASIO_GetLatencies()\r
707           are essential for precise media synchronization!\r
708 */\r
709 \r
710 typedef struct ASIOChannelInfo\r
711 {\r
712         long channel;                   // on input, channel index\r
713         ASIOBool isInput;               // on input\r
714         ASIOBool isActive;              // on exit\r
715         long channelGroup;              // dto\r
716         ASIOSampleType type;    // dto\r
717         char name[32];                  // dto\r
718 } ASIOChannelInfo;\r
719 \r
720 ASIOError ASIOGetChannelInfo(ASIOChannelInfo *info);\r
721 /* Purpose:\r
722           retreive information about the nature of a channel\r
723         Parameter:\r
724           info: pointer to a ASIOChannelInfo structure with\r
725                 - channel: on input, the channel index of the channel in question.\r
726                 - isInput: on input, ASIOTrue if info for an input channel is\r
727                   requested, else output\r
728                 - channelGroup: on return, the channel group that the channel\r
729                   belongs to. For drivers which support different types of\r
730                   channels, like analog, S/PDIF, AES/EBU, ADAT etc interfaces,\r
731                   there should be a reasonable grouping of these types. Groups\r
732                   are always independant form a channel index, that is, a channel\r
733                   index always counts from 0 to numInputs/numOutputs regardless\r
734                   of the group it may belong to.\r
735                   There will always be at least one group (group 0). Please\r
736                   also note that by default, the host may decide to activate\r
737                   channels 0 and 1; thus, these should belong to the most\r
738                   useful type (analog i/o, if present).\r
739                 - type: on return, contains the sample type of the channel\r
740                 - isActive: on return, ASIOTrue if channel is active as it was\r
741                   installed by ASIOCreateBuffers(), ASIOFalse else\r
742                 - name:  describing the type of channel in question. Used to allow\r
743                   for user selection, and enabling of specific channels. examples:\r
744               "Analog In", "SPDIF Out" etc\r
745         Returns:\r
746           If no input/output is present ASE_NotPresent will be returned.\r
747         Notes:\r
748           If possible, the string should be organised such that the first\r
749           characters are most significantly describing the nature of the\r
750           port, to allow for identification even if the view showing the\r
751           port name is too small to display more than 8 characters, for\r
752           instance.\r
753 */\r
754 \r
755 //- - - - - - - - - - - - - - - - - - - - - - - - -\r
756 // Buffer preparation\r
757 //- - - - - - - - - - - - - - - - - - - - - - - - -\r
758 \r
759 typedef struct ASIOBufferInfo\r
760 {\r
761         ASIOBool isInput;                       // on input:  ASIOTrue: input, else output\r
762         long channelNum;                        // on input:  channel index\r
763         void *buffers[2];                       // on output: double buffer addresses\r
764 } ASIOBufferInfo;\r
765 \r
766 ASIOError ASIOCreateBuffers(ASIOBufferInfo *bufferInfos, long numChannels,\r
767         long bufferSize, ASIOCallbacks *callbacks);\r
768 \r
769 /* Purpose:\r
770           Allocates input/output buffers for all input and output channels to be activated.\r
771         Parameter:\r
772           bufferInfos is a pointer to an array of ASIOBufferInfo structures:\r
773             - isInput: on input, ASIOTrue if the buffer is to be allocated\r
774               for an input, output buffer else\r
775             - channelNum: on input, the index of the channel in question\r
776               (counting from 0)\r
777             - buffers: on exit, 2 pointers to the halves of the channels' double-buffer.\r
778               the size of the buffer(s) of course depend on both the ASIOSampleType\r
779               as obtained from ASIOGetChannelInfo(), and bufferSize\r
780           numChannels is the sum of all input and output channels to be created;\r
781           thus bufferInfos is a pointer to an array of numChannels ASIOBufferInfo\r
782           structures.\r
783           bufferSize selects one of the possible buffer sizes as obtained from\r
784           ASIOGetBufferSizes().\r
785           callbacks is a pointer to an ASIOCallbacks structure.\r
786         Returns:\r
787           If not enough memory is available ASE_NoMemory will be returned.\r
788           If no input/output is present ASE_NotPresent will be returned.\r
789           If bufferSize is not supported, or one or more of the bufferInfos elements\r
790           contain invalid settings, ASE_InvalidMode will be returned.\r
791         Notes:\r
792           If individual channel selection is not possible but requested,\r
793           the driver has to handle this. namely, bufferSwitch() will only\r
794           have filled buffers of enabled outputs. If possible, processing\r
795           and buss activities overhead should be avoided for channels which\r
796           were not enabled here.\r
797 */\r
798 \r
799 ASIOError ASIODisposeBuffers(void);\r
800 /* Purpose:\r
801           Releases all buffers for the device.\r
802         Parameter:\r
803           None.\r
804         Returns:\r
805           If no buffer were ever prepared, ASE_InvalidMode will be returned.\r
806           If no input/output is present ASE_NotPresent will be returned.\r
807         Notes:\r
808           This implies ASIOStop().\r
809 */\r
810 \r
811 ASIOError ASIOControlPanel(void);\r
812 /* Purpose:\r
813           request the driver to start a control panel component\r
814           for device specific user settings. This will not be\r
815           accessed on some platforms (where the component is accessed\r
816           instead).\r
817         Parameter:\r
818           None.\r
819         Returns:\r
820           If no panel is available ASE_NotPresent will be returned.\r
821           Actually, the return code is ignored.\r
822         Notes:\r
823           if the user applied settings which require a re-configuration\r
824           of parts or all of the enigine and/or driver (such as a change of\r
825           the block size), the asioMessage callback can be used (see\r
826           ASIO_Callbacks).\r
827 */\r
828 \r
829 ASIOError ASIOFuture(long selector, void *params);\r
830 /* Purpose:\r
831           various\r
832         Parameter:\r
833           selector: operation Code as to be defined. zero is reserved for\r
834           testing purposes.\r
835           params: depends on the selector; usually pointer to a structure\r
836           for passing and retreiving any type and amount of parameters.\r
837         Returns:\r
838           the return value is also selector dependant. if the selector\r
839           is unknown, ASE_InvalidParameter should be returned to prevent\r
840           further calls with this selector. on success, ASE_SUCCESS\r
841           must be returned (note: ASE_OK is *not* sufficient!)\r
842         Notes:\r
843           see selectors defined below.    \r
844 */\r
845 \r
846 enum\r
847 {\r
848         kAsioEnableTimeCodeRead = 1,    // no arguments\r
849         kAsioDisableTimeCodeRead,               // no arguments\r
850         kAsioSetInputMonitor,                   // ASIOInputMonitor* in params\r
851         kAsioTransport,                                 // ASIOTransportParameters* in params\r
852         kAsioSetInputGain,                              // ASIOChannelControls* in params, apply gain\r
853         kAsioGetInputMeter,                             // ASIOChannelControls* in params, fill meter\r
854         kAsioSetOutputGain,                             // ASIOChannelControls* in params, apply gain\r
855         kAsioGetOutputMeter,                    // ASIOChannelControls* in params, fill meter\r
856         kAsioCanInputMonitor,                   // no arguments for kAsioCanXXX selectors\r
857         kAsioCanTimeInfo,\r
858         kAsioCanTimeCode,\r
859         kAsioCanTransport,\r
860         kAsioCanInputGain,\r
861         kAsioCanInputMeter,\r
862         kAsioCanOutputGain,\r
863         kAsioCanOutputMeter\r
864 };\r
865 \r
866 typedef struct ASIOInputMonitor\r
867 {\r
868         long input;             // this input was set to monitor (or off), -1: all\r
869         long output;    // suggested output for monitoring the input (if so)\r
870         long gain;              // suggested gain, ranging 0 - 0x7fffffffL (-inf to +12 dB)\r
871         ASIOBool state; // ASIOTrue => on, ASIOFalse => off\r
872         long pan;               // suggested pan, 0 => all left, 0x7fffffff => right\r
873 } ASIOInputMonitor;\r
874 \r
875 typedef struct ASIOChannelControls\r
876 {\r
877         long channel;                   // on input, channel index\r
878         ASIOBool isInput;               // on input\r
879         long gain;                              // on input,  ranges 0 thru 0x7fffffff\r
880         long meter;                             // on return, ranges 0 thru 0x7fffffff\r
881         char future[32];\r
882 } ASIOChannelControls;\r
883 \r
884 typedef struct ASIOTransportParameters\r
885 {\r
886         long command;           // see enum below\r
887         ASIOSamples samplePosition;\r
888         long track;\r
889         long trackSwitches[16];         // 512 tracks on/off\r
890         char future[64];\r
891 } ASIOTransportParameters;\r
892 \r
893 enum\r
894 {\r
895         kTransStart = 1,\r
896         kTransStop,\r
897         kTransLocate,           // to samplePosition\r
898         kTransPunchIn,\r
899         kTransPunchOut,\r
900         kTransArmOn,            // track\r
901         kTransArmOff,           // track\r
902         kTransMonitorOn,        // track\r
903         kTransMonitorOff,       // track\r
904         kTransArm,                      // trackSwitches\r
905         kTransMonitor           // trackSwitches\r
906 };\r
907 \r
908 ASIOError ASIOOutputReady(void);\r
909 /* Purpose:\r
910           this tells the driver that the host has completed processing\r
911           the output buffers. if the data format required by the hardware\r
912           differs from the supported asio formats, but the hardware\r
913           buffers are DMA buffers, the driver will have to convert\r
914           the audio stream data; as the bufferSwitch callback is\r
915           usually issued at dma block switch time, the driver will\r
916           have to convert the *previous* host buffer, which increases\r
917           the output latency by one block.\r
918           when the host finds out that ASIOOutputReady() returns\r
919           true, it will issue this call whenever it completed\r
920           output processing. then the driver can convert the\r
921           host data directly to the dma buffer to be played next,\r
922           reducing output latency by one block.\r
923           another way to look at it is, that the buffer switch is called\r
924           in order to pass the *input* stream to the host, so that it can\r
925           process the input into the output, and the output stream is passed\r
926           to the driver when the host has completed its process.\r
927         Parameter:\r
928                 None\r
929         Returns:\r
930           only if the above mentioned scenario is given, and a reduction\r
931           of output latency can be acheived by this mechanism, should\r
932           ASE_OK be returned. otherwise (and usually), ASE_NotPresent\r
933           should be returned in order to prevent further calls to this\r
934           function. note that the host may want to determine if it is\r
935           to use this when the system is not yet fully initialized, so\r
936           ASE_OK should always be returned if the mechanism makes sense.          \r
937         Notes:\r
938           please remeber to adjust ASIOGetLatencies() according to\r
939           whether ASIOOutputReady() was ever called or not, if your\r
940           driver supports this scenario.\r
941           also note that the engine may fail to call ASIO_OutputReady()\r
942           in time in overload cases. as already mentioned, bufferSwitch\r
943       should be called for every block regardless of whether a block\r
944       could be processed in time.\r
945 */\r
946 \r
947 // restore old alignment\r
948 #if defined(_MSC_VER) && !defined(__MWERKS__) \r
949 #pragma pack(pop)\r
950 #elif PRAGMA_ALIGN_SUPPORTED\r
951 #pragma options align = reset\r
952 #endif\r
953 \r
954 #endif\r
955 \r