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