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