1070 lines · 41.6 KB · C
RawDownload
//---------------------------------------------------------------------------------------------------//--------------------------------------------------------------------------------------------------- /*	Steinberg Audio Stream I/O API	(c) 1997 - 2013, Steinberg Media Technologies GmbH 	ASIO Interface Specification v 2.3 	2005 - Added support for DSD sample data (in cooperation with Sony)	2012 - Added support for drop out detection			 	basic concept is an i/o synchronous double-buffer scheme:		on bufferSwitch(index == 0), host will read/write: 		after ASIOStart(), the  read  first input buffer A (index 0)	|   will be invalid (empty)	*   ------------------------	|------------------------|-----------------------|	|                        |                       |	|  Input Buffer A (0)    |   Input Buffer B (1)  |	|                        |                       |	|------------------------|-----------------------|	|                        |                       |	|  Output Buffer A (0)   |   Output Buffer B (1) |	|                        |                       |	|------------------------|-----------------------|	*                        -------------------------	|                        before calling ASIOStart(),  write                      host will have filled output                             buffer B (index 1) already   *please* take special care of proper statement of input  and output latencies (see ASIOGetLatencies()), these  control sequencer sync accuracy */ //---------------------------------------------------------------------------------------------------//--------------------------------------------------------------------------------------------------- /* prototypes summary: ASIOError ASIOInit(ASIODriverInfo *info);ASIOError ASIOExit(void);ASIOError ASIOStart(void);ASIOError ASIOStop(void);ASIOError ASIOGetChannels(long *numInputChannels, long *numOutputChannels);ASIOError ASIOGetLatencies(long *inputLatency, long *outputLatency);ASIOError ASIOGetBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity);ASIOError ASIOCanSampleRate(ASIOSampleRate sampleRate);ASIOError ASIOGetSampleRate(ASIOSampleRate *currentRate);ASIOError ASIOSetSampleRate(ASIOSampleRate sampleRate);ASIOError ASIOGetClockSources(ASIOClockSource *clocks, long *numSources);ASIOError ASIOSetClockSource(long reference);ASIOError ASIOGetSamplePosition (ASIOSamples *sPos, ASIOTimeStamp *tStamp);ASIOError ASIOGetChannelInfo(ASIOChannelInfo *info);ASIOError ASIOCreateBuffers(ASIOBufferInfo *bufferInfos, long numChannels,	long bufferSize, ASIOCallbacks *callbacks);ASIOError ASIODisposeBuffers(void);ASIOError ASIOControlPanel(void);void *ASIOFuture(long selector, void *params);ASIOError ASIOOutputReady(void); */ //---------------------------------------------------------------------------------------------------//--------------------------------------------------------------------------------------------------- #ifndef __ASIO_H#define __ASIO_H // force 4 byte alignment#if defined(_MSC_VER) && !defined(__MWERKS__) #pragma pack(push,4)#elif PRAGMA_ALIGN_SUPPORTED#pragma options align = native#endif //- - - - - - - - - - - - - - - - - - - - - - - - -// Type definitions//- - - - - - - - - - - - - - - - - - - - - - - - - // number of samples data type is 64 bit integer#if NATIVE_INT64	typedef long long int ASIOSamples;#else	typedef struct ASIOSamples {		unsigned long hi;		unsigned long lo;	} ASIOSamples;#endif // Timestamp data type is 64 bit integer,// Time format is Nanoseconds.#if NATIVE_INT64	typedef long long int ASIOTimeStamp ;#else	typedef struct ASIOTimeStamp {		unsigned long hi;		unsigned long lo;	} ASIOTimeStamp;#endif // Samplerates are expressed in IEEE 754 64 bit double float,// native format as host computer#if IEEE754_64FLOAT	typedef double ASIOSampleRate;#else	typedef struct ASIOSampleRate {		char ieee[8];	} ASIOSampleRate;#endif // Boolean values are expressed as longtypedef long ASIOBool;enum {	ASIOFalse = 0,	ASIOTrue = 1}; // Sample Types are expressed as longtypedef long ASIOSampleType;enum {	ASIOSTInt16MSB   = 0,	ASIOSTInt24MSB   = 1,		// used for 20 bits as well	ASIOSTInt32MSB   = 2,	ASIOSTFloat32MSB = 3,		// IEEE 754 32 bit float	ASIOSTFloat64MSB = 4,		// IEEE 754 64 bit double float 	// these are used for 32 bit data buffer, with different alignment of the data inside	// 32 bit PCI bus systems can be more easily used with these	ASIOSTInt32MSB16 = 8,		// 32 bit data with 16 bit alignment	ASIOSTInt32MSB18 = 9,		// 32 bit data with 18 bit alignment	ASIOSTInt32MSB20 = 10,		// 32 bit data with 20 bit alignment	ASIOSTInt32MSB24 = 11,		// 32 bit data with 24 bit alignment		ASIOSTInt16LSB   = 16,	ASIOSTInt24LSB   = 17,		// used for 20 bits as well	ASIOSTInt32LSB   = 18,	ASIOSTFloat32LSB = 19,		// IEEE 754 32 bit float, as found on Intel x86 architecture	ASIOSTFloat64LSB = 20, 		// IEEE 754 64 bit double float, as found on Intel x86 architecture 	// these are used for 32 bit data buffer, with different alignment of the data inside	// 32 bit PCI bus systems can more easily used with these	ASIOSTInt32LSB16 = 24,		// 32 bit data with 18 bit alignment	ASIOSTInt32LSB18 = 25,		// 32 bit data with 18 bit alignment	ASIOSTInt32LSB20 = 26,		// 32 bit data with 20 bit alignment	ASIOSTInt32LSB24 = 27,		// 32 bit data with 24 bit alignment 	//	ASIO DSD format.	ASIOSTDSDInt8LSB1   = 32,		// DSD 1 bit data, 8 samples per byte. First sample in Least significant bit.	ASIOSTDSDInt8MSB1   = 33,		// DSD 1 bit data, 8 samples per byte. First sample in Most significant bit.	ASIOSTDSDInt8NER8	= 40,		// DSD 8 bit data, 1 sample per byte. No Endianness required. 	ASIOSTLastEntry}; /*-----------------------------------------------------------------------------// DSD operation and buffer layout// Definition by Steinberg/Sony Oxford.//// We have tried to treat DSD as PCM and so keep a consistent structure across// the ASIO interface.//// DSD's sample rate is normally referenced as a multiple of 44.1Khz, so// the standard sample rate is referred to as 64Fs (or 2.8224Mhz). We looked// at making a special case for DSD and adding a field to the ASIOFuture that// would allow the user to select the Over Sampleing Rate (OSR) as a separate// entity but decided in the end just to treat it as a simple value of// 2.8224Mhz and use the standard interface to set it.//// The second problem was the "word" size, in PCM the word size is always a// greater than or equal to 8 bits (a byte). This makes life easy as we can// then pack the samples into the "natural" size for the machine.// In DSD the "word" size is 1 bit. This is not a major problem and can easily// be dealt with if we ensure that we always deal with a multiple of 8 samples.//// DSD brings with it another twist to the Endianness religion. How are the// samples packed into the byte. It would be nice to just say the most significant// bit is always the first sample, however there would then be a performance hit// on little endian machines. Looking at how some of the processing goes...// Little endian machines like the first sample to be in the Least Significant Bit,//   this is because when you write it to memory the data is in the correct format//   to be shifted in and out of the words.// Big endian machine prefer the first sample to be in the Most Significant Bit,//   again for the same reasion.//// And just when things were looking really muddy there is a proposed extension to// DSD that uses 8 bit word sizes. It does not care what endianness you use.//// Switching the driver between DSD and PCM mode// ASIOFuture allows for extending the ASIO API quite transparently.// See kAsioSetIoFormat, kAsioGetIoFormat, kAsioCanDoIoFormat////-----------------------------------------------------------------------------*/  //- - - - - - - - - - - - - - - - - - - - - - - - -// Error codes//- - - - - - - - - - - - - - - - - - - - - - - - - typedef long ASIOError;enum {	ASE_OK = 0,             // This value will be returned whenever the call succeeded	ASE_SUCCESS = 0x3f4847a0,	// unique success return value for ASIOFuture calls	ASE_NotPresent = -1000, // hardware input or output is not present or available	ASE_HWMalfunction,      // hardware is malfunctioning (can be returned by any ASIO function)	ASE_InvalidParameter,   // input parameter invalid	ASE_InvalidMode,        // hardware is in a bad mode or used in a bad mode	ASE_SPNotAdvancing,     // hardware is not running when sample position is inquired	ASE_NoClock,            // sample clock or rate cannot be determined or is not present	ASE_NoMemory            // not enough memory for completing the request}; //---------------------------------------------------------------------------------------------------//--------------------------------------------------------------------------------------------------- //- - - - - - - - - - - - - - - - - - - - - - - - -// Time Info support//- - - - - - - - - - - - - - - - - - - - - - - - - typedef struct ASIOTimeCode{       	double          speed;                  // speed relation (fraction of nominal speed)	                                        // optional; set to 0. or 1. if not supported	ASIOSamples     timeCodeSamples;        // time in samples	unsigned long   flags;                  // some information flags (see below)	char future[64];} ASIOTimeCode; typedef enum ASIOTimeCodeFlags{	kTcValid                = 1,	kTcRunning              = 1 << 1,	kTcReverse              = 1 << 2,	kTcOnspeed              = 1 << 3,	kTcStill                = 1 << 4,		kTcSpeedValid           = 1 << 8}  ASIOTimeCodeFlags; typedef struct AsioTimeInfo{	double          speed;                  // absolute speed (1. = nominal)	ASIOTimeStamp   systemTime;             // system time related to samplePosition, in nanoseconds	                                        // on mac, must be derived from Microseconds() (not UpTime()!)	                                        // on windows, must be derived from timeGetTime()	ASIOSamples     samplePosition;	ASIOSampleRate  sampleRate;             // current rate	unsigned long flags;                    // (see below)	char reserved[12];} AsioTimeInfo; typedef enum AsioTimeInfoFlags{	kSystemTimeValid        = 1,            // must always be valid	kSamplePositionValid    = 1 << 1,       // must always be valid	kSampleRateValid        = 1 << 2,	kSpeedValid             = 1 << 3,		kSampleRateChanged      = 1 << 4,	kClockSourceChanged     = 1 << 5} AsioTimeInfoFlags; typedef struct ASIOTime                          // both input/output{	long reserved[4];                       // must be 0	struct AsioTimeInfo     timeInfo;       // required	struct ASIOTimeCode     timeCode;       // optional, evaluated if (timeCode.flags & kTcValid)} ASIOTime; /* using time info:it is recommended to use the new method with time info even if the asiodevice does not support timecode; continuous calls to ASIOGetSamplePositionand ASIOGetSampleRate are avoided, and there is a more defined relationshipbetween callback time and the time info. see the example below.to initiate time info mode, after you have received the callbacks pointer inASIOCreateBuffers, you will call the asioMessage callback with kAsioSupportsTimeInfoas the argument. if this returns 1, host has accepted time info mode.now host expects the new callback bufferSwitchTimeInfo to be used insteadof the old bufferSwitch method. the ASIOTime structure is assumed to be validand accessible until the callback returns. using time code:if the device supports reading time code, it will call host's asioMessage callbackwith kAsioSupportsTimeCode as the selector. it may then fill the accordingfields and set the kTcValid flag.host will call the future method with the kAsioEnableTimeCodeRead selector whenit wants to enable or disable tc reading by the device. you should also supportthe kAsioCanTimeInfo and kAsioCanTimeCode selectors in ASIOFuture (see example). note:the AsioTimeInfo/ASIOTimeCode pair is supposed to work in both directions.as a matter of convention, the relationship between the sampleposition counter and the time code at buffer switch time is(ignoring offset between tc and sample pos when tc is running): on input:	sample 0 -> input  buffer sample 0 -> time code 0on output:	sample 0 -> output buffer sample 0 -> time code 0 this means that for 'real' calculations, one has to take into accountthe according latencies. example: ASIOTime asioTime; in createBuffers(){	memset(&asioTime, 0, sizeof(ASIOTime));	AsioTimeInfo* ti = &asioTime.timeInfo;	ti->sampleRate = theSampleRate;	ASIOTimeCode* tc = &asioTime.timeCode;	tc->speed = 1.;	timeInfoMode = false;	canTimeCode = false;	if(callbacks->asioMessage(kAsioSupportsTimeInfo, 0, 0, 0) == 1)	{		timeInfoMode = true;#if kCanTimeCode		if(callbacks->asioMessage(kAsioSupportsTimeCode, 0, 0, 0) == 1)			canTimeCode = true;#endif	}} void switchBuffers(long doubleBufferIndex, bool processNow){	if(timeInfoMode)	{		AsioTimeInfo* ti = &asioTime.timeInfo;		ti->flags =	kSystemTimeValid | kSamplePositionValid | kSampleRateValid;		ti->systemTime = theNanoSeconds;		ti->samplePosition = theSamplePosition;		if(ti->sampleRate != theSampleRate)			ti->flags |= kSampleRateChanged;		ti->sampleRate = theSampleRate; #if kCanTimeCode		if(canTimeCode && timeCodeEnabled)		{			ASIOTimeCode* tc = &asioTime.timeCode;			tc->timeCodeSamples = tcSamples;						// tc in samples			tc->flags = kTcValid | kTcRunning | kTcOnspeed;			// if so...		}		ASIOTime* bb = callbacks->bufferSwitchTimeInfo(&asioTime, doubleBufferIndex, processNow ? ASIOTrue : ASIOFalse);#else		callbacks->bufferSwitchTimeInfo(&asioTime, doubleBufferIndex, processNow ? ASIOTrue : ASIOFalse);#endif	}	else		callbacks->bufferSwitch(doubleBufferIndex, ASIOFalse);} ASIOError ASIOFuture(long selector, void *params){	switch(selector)	{		case kAsioEnableTimeCodeRead:			timeCodeEnabled = true;			return ASE_SUCCESS;		case kAsioDisableTimeCodeRead:			timeCodeEnabled = false;			return ASE_SUCCESS;		case kAsioCanTimeInfo:			return ASE_SUCCESS;		#if kCanTimeCode		case kAsioCanTimeCode:			return ASE_SUCCESS;		#endif	}	return ASE_NotPresent;}; */ //- - - - - - - - - - - - - - - - - - - - - - - - -// application's audio stream handler callbacks//- - - - - - - - - - - - - - - - - - - - - - - - - typedef struct ASIOCallbacks{	void (*bufferSwitch) (long doubleBufferIndex, ASIOBool directProcess);		// bufferSwitch indicates that both input and output are to be processed.		// the current buffer half index (0 for A, 1 for B) determines		// - the output buffer that the host should start to fill. the other buffer		//   will be passed to output hardware regardless of whether it got filled		//   in time or not.		// - the input buffer that is now filled with incoming data. Note that		//   because of the synchronicity of i/o, the input always has at		//   least one buffer latency in relation to the output.		// directProcess suggests to the host whether it should immedeately		// start processing (directProcess == ASIOTrue), or whether its process		// should be deferred because the call comes from a very low level		// (for instance, a high level priority interrupt), and direct processing		// would cause timing instabilities for the rest of the system. If in doubt,		// directProcess should be set to ASIOFalse.		// Note: bufferSwitch may be called at interrupt time for highest efficiency. 	void (*sampleRateDidChange) (ASIOSampleRate sRate);		// gets called when the AudioStreamIO detects a sample rate change		// If sample rate is unknown, 0 is passed (for instance, clock loss		// when externally synchronized). 	long (*asioMessage) (long selector, long value, void* message, double* opt);		// generic callback for various purposes, see selectors below.		// note this is only present if the asio version is 2 or higher 	ASIOTime* (*bufferSwitchTimeInfo) (ASIOTime* params, long doubleBufferIndex, ASIOBool directProcess);		// new callback with time info. makes ASIOGetSamplePosition() and various		// calls to ASIOGetSampleRate obsolete,		// and allows for timecode sync etc. to be preferred; will be used if		// the driver calls asioMessage with selector kAsioSupportsTimeInfo.} ASIOCallbacks; // asioMessage selectorsenum{	kAsioSelectorSupported = 1,	// selector in <value>, returns 1L if supported,								// 0 otherwise    kAsioEngineVersion,			// returns engine (host) asio implementation version,								// 2 or higher	kAsioResetRequest,			// request driver reset. if accepted, this								// will close the driver (ASIO_Exit() ) and								// re-open it again (ASIO_Init() etc). some								// drivers need to reconfigure for instance								// when the sample rate changes, or some basic								// changes have been made in ASIO_ControlPanel().								// returns 1L; note the request is merely passed								// to the application, there is no way to determine								// if it gets accepted at this time (but it usually								// will be).	kAsioBufferSizeChange,		// not yet supported, will currently always return 0L.								// for now, use kAsioResetRequest instead.								// once implemented, the new buffer size is expected								// in <value>, and on success returns 1L	kAsioResyncRequest,			// the driver went out of sync, such that								// the timestamp is no longer valid. this								// is a request to re-start the engine and								// slave devices (sequencer). returns 1 for ok,								// 0 if not supported.	kAsioLatenciesChanged, 		// the drivers latencies have changed. The engine								// will refetch the latencies.	kAsioSupportsTimeInfo,		// if host returns true here, it will expect the								// callback bufferSwitchTimeInfo to be called instead								// of bufferSwitch	kAsioSupportsTimeCode,		// 	kAsioMMCCommand,			// unused - value: number of commands, message points to mmc commands	kAsioSupportsInputMonitor,	// kAsioSupportsXXX return 1 if host supports this	kAsioSupportsInputGain,     // unused and undefined	kAsioSupportsInputMeter,    // unused and undefined	kAsioSupportsOutputGain,    // unused and undefined	kAsioSupportsOutputMeter,   // unused and undefined	kAsioOverload,              // driver detected an overload 	kAsioNumMessageSelectors}; //---------------------------------------------------------------------------------------------------//--------------------------------------------------------------------------------------------------- //- - - - - - - - - - - - - - - - - - - - - - - - -// (De-)Construction//- - - - - - - - - - - - - - - - - - - - - - - - - typedef struct ASIODriverInfo{	long asioVersion;		// currently, 2	long driverVersion;		// driver specific	char name[32];	char errorMessage[124];	void *sysRef;			// on input: system reference							// (Windows: application main window handle, Mac & SGI: 0)} ASIODriverInfo; ASIOError ASIOInit(ASIODriverInfo *info);/* Purpose:	  Initialize the AudioStreamIO.	Parameter:	  info: pointer to an ASIODriver structure:	    - asioVersion:			- on input, the host version. *** Note *** this is 0 for earlier asio			implementations, and the asioMessage callback is implemented			only if asioVersion is 2 or greater. sorry but due to a design fault			the driver doesn't have access to the host version in ASIOInit :-(			added selector for host (engine) version in the asioMessage callback			so we're ok from now on.			- on return, asio implementation version.			  older versions are 1

Lines 1–500 of 1070.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t