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