--- /dev/null
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "asiosample"="..\driver\asiosample\asiosample\asiosample.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "hostsample"="..\host\sample\hostsample.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
--- /dev/null
+Changes in ASIO 2.3 since ASIO 2.2
+- added host queries to detect the driver's buffering and drop-out detection capabilities
+- some additional documentation on MMCSS; see page 46 of 'ASIO SDK 2.3.pdf'
+- dropped support for Mac OS 8 and 9
+
+Changes in ASIO 2.2 since ASIO 2.1
+- added support for Windows 64 bit
+
+Changes in ASIO 2.1 since ASIO 2.0
+- Sony DSD support added
+- fixed Windows registry sample to HKEY_LOCAL_MACHINE
+- fixed a definition problem for input monitoring
--- /dev/null
+/*
+ Steinberg Audio Stream I/O API
+ (c) 1996, Steinberg Soft- und Hardware GmbH
+
+ asio.cpp
+
+ asio functions entries which translate the
+ asio interface to the asiodrvr class methods
+*/
+
+#include <string.h>
+#include "asiosys.h" // platform definition
+#include "asio.h"
+
+#if MAC
+#include "asiodrvr.h"
+
+#pragma export on
+
+AsioDriver *theAsioDriver = 0;
+
+extern "C"
+{
+
+long main()
+{
+ return 'ASIO';
+}
+
+#elif WINDOWS
+
+#include "windows.h"
+#include "iasiodrv.h"
+#include "asiodrivers.h"
+
+IASIO *theAsioDriver = 0;
+extern AsioDrivers *asioDrivers;
+
+#elif SGI || SUN || BEOS || LINUX
+#include "asiodrvr.h"
+static AsioDriver *theAsioDriver = 0;
+#endif
+
+//-----------------------------------------------------------------------------------------------------
+ASIOError ASIOInit(ASIODriverInfo *info)
+{
+#if MAC || SGI || SUN || BEOS || LINUX
+ if(theAsioDriver)
+ {
+ delete theAsioDriver;
+ theAsioDriver = 0;
+ }
+ info->driverVersion = 0;
+ strcpy(info->name, "No ASIO Driver");
+ theAsioDriver = getDriver();
+ if(!theAsioDriver)
+ {
+ strcpy(info->errorMessage, "Not enough memory for the ASIO driver!");
+ return ASE_NotPresent;
+ }
+ if(!theAsioDriver->init(info->sysRef))
+ {
+ theAsioDriver->getErrorMessage(info->errorMessage);
+ delete theAsioDriver;
+ theAsioDriver = 0;
+ return ASE_NotPresent;
+ }
+ strcpy(info->errorMessage, "No ASIO Driver Error");
+ theAsioDriver->getDriverName(info->name);
+ info->driverVersion = theAsioDriver->getDriverVersion();
+ return ASE_OK;
+
+#else
+
+ info->driverVersion = 0;
+ strcpy(info->name, "No ASIO Driver");
+ if(theAsioDriver) // must be loaded!
+ {
+ if(!theAsioDriver->init(info->sysRef))
+ {
+ theAsioDriver->getErrorMessage(info->errorMessage);
+ theAsioDriver = 0;
+ return ASE_NotPresent;
+ }
+
+ strcpy(info->errorMessage, "No ASIO Driver Error");
+ theAsioDriver->getDriverName(info->name);
+ info->driverVersion = theAsioDriver->getDriverVersion();
+ return ASE_OK;
+ }
+ return ASE_NotPresent;
+
+#endif // !MAC
+}
+
+ASIOError ASIOExit(void)
+{
+ if(theAsioDriver)
+ {
+#if WINDOWS
+ asioDrivers->removeCurrentDriver();
+#else
+ delete theAsioDriver;
+#endif
+ }
+ theAsioDriver = 0;
+ return ASE_OK;
+}
+
+ASIOError ASIOStart(void)
+{
+ if(!theAsioDriver)
+ return ASE_NotPresent;
+ return theAsioDriver->start();
+}
+
+ASIOError ASIOStop(void)
+{
+ if(!theAsioDriver)
+ return ASE_NotPresent;
+ return theAsioDriver->stop();
+}
+
+ASIOError ASIOGetChannels(long *numInputChannels, long *numOutputChannels)
+{
+ if(!theAsioDriver)
+ {
+ *numInputChannels = *numOutputChannels = 0;
+ return ASE_NotPresent;
+ }
+ return theAsioDriver->getChannels(numInputChannels, numOutputChannels);
+}
+
+ASIOError ASIOGetLatencies(long *inputLatency, long *outputLatency)
+{
+ if(!theAsioDriver)
+ {
+ *inputLatency = *outputLatency = 0;
+ return ASE_NotPresent;
+ }
+ return theAsioDriver->getLatencies(inputLatency, outputLatency);
+}
+
+ASIOError ASIOGetBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity)
+{
+ if(!theAsioDriver)
+ {
+ *minSize = *maxSize = *preferredSize = *granularity = 0;
+ return ASE_NotPresent;
+ }
+ return theAsioDriver->getBufferSize(minSize, maxSize, preferredSize, granularity);
+}
+
+ASIOError ASIOCanSampleRate(ASIOSampleRate sampleRate)
+{
+ if(!theAsioDriver)
+ return ASE_NotPresent;
+ return theAsioDriver->canSampleRate(sampleRate);
+}
+
+ASIOError ASIOGetSampleRate(ASIOSampleRate *currentRate)
+{
+ if(!theAsioDriver)
+ return ASE_NotPresent;
+ return theAsioDriver->getSampleRate(currentRate);
+}
+
+ASIOError ASIOSetSampleRate(ASIOSampleRate sampleRate)
+{
+ if(!theAsioDriver)
+ return ASE_NotPresent;
+ return theAsioDriver->setSampleRate(sampleRate);
+}
+
+ASIOError ASIOGetClockSources(ASIOClockSource *clocks, long *numSources)
+{
+ if(!theAsioDriver)
+ {
+ *numSources = 0;
+ return ASE_NotPresent;
+ }
+ return theAsioDriver->getClockSources(clocks, numSources);
+}
+
+ASIOError ASIOSetClockSource(long reference)
+{
+ if(!theAsioDriver)
+ return ASE_NotPresent;
+ return theAsioDriver->setClockSource(reference);
+}
+
+ASIOError ASIOGetSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp)
+{
+ if(!theAsioDriver)
+ return ASE_NotPresent;
+ return theAsioDriver->getSamplePosition(sPos, tStamp);
+}
+
+ASIOError ASIOGetChannelInfo(ASIOChannelInfo *info)
+{
+ if(!theAsioDriver)
+ {
+ info->channelGroup = -1;
+ info->type = ASIOSTInt16MSB;
+ strcpy(info->name, "None");
+ return ASE_NotPresent;
+ }
+ return theAsioDriver->getChannelInfo(info);
+}
+
+ASIOError ASIOCreateBuffers(ASIOBufferInfo *bufferInfos, long numChannels,
+ long bufferSize, ASIOCallbacks *callbacks)
+{
+ if(!theAsioDriver)
+ {
+ ASIOBufferInfo *info = bufferInfos;
+ for(long i = 0; i < numChannels; i++, info++)
+ info->buffers[0] = info->buffers[1] = 0;
+ return ASE_NotPresent;
+ }
+ return theAsioDriver->createBuffers(bufferInfos, numChannels, bufferSize, callbacks);
+}
+
+ASIOError ASIODisposeBuffers(void)
+{
+ if(!theAsioDriver)
+ return ASE_NotPresent;
+ return theAsioDriver->disposeBuffers();
+}
+
+ASIOError ASIOControlPanel(void)
+{
+ if(!theAsioDriver)
+ return ASE_NotPresent;
+ return theAsioDriver->controlPanel();
+}
+
+ASIOError ASIOFuture(long selector, void *opt)
+{
+ if(!theAsioDriver)
+ return ASE_NotPresent;
+ return theAsioDriver->future(selector, opt);
+}
+
+ASIOError ASIOOutputReady(void)
+{
+ if(!theAsioDriver)
+ return ASE_NotPresent;
+ return theAsioDriver->outputReady();
+}
+
+#if MAC
+} // extern "C"
+#pragma export off
+#endif
+
+
--- /dev/null
+//---------------------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------------------
+
+/*
+ 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 long
+typedef long ASIOBool;
+enum {
+ ASIOFalse = 0,
+ ASIOTrue = 1
+};
+
+// Sample Types are expressed as long
+typedef 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 consistant structure across
+// the ASIO interface.
+//
+// DSD's sample rate is normally referenced as a multiple of 44.1Khz, so
+// the standard sample rate is refered 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 seperate
+// 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 asio
+device does not support timecode; continuous calls to ASIOGetSamplePosition
+and ASIOGetSampleRate are avoided, and there is a more defined relationship
+between callback time and the time info.
+
+see the example below.
+to initiate time info mode, after you have received the callbacks pointer in
+ASIOCreateBuffers, you will call the asioMessage callback with kAsioSupportsTimeInfo
+as the argument. if this returns 1, host has accepted time info mode.
+now host expects the new callback bufferSwitchTimeInfo to be used instead
+of the old bufferSwitch method. the ASIOTime structure is assumed to be valid
+and accessible until the callback returns.
+
+using time code:
+if the device supports reading time code, it will call host's asioMessage callback
+with kAsioSupportsTimeCode as the selector. it may then fill the according
+fields and set the kTcValid flag.
+host will call the future method with the kAsioEnableTimeCodeRead selector when
+it wants to enable or disable tc reading by the device. you should also support
+the 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 sample
+position 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 0
+on output: sample 0 -> output buffer sample 0 -> time code 0
+
+this means that for 'real' calculations, one has to take into account
+the 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 selectors
+enum
+{
+ 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 implemeted
+ 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
+ if you support this version (namely, ASIO_outputReady() )
+ this should be 2 or higher. also see the note in
+ ASIO_getTimeStamp() !
+ - version: on return, the driver version (format is driver specific)
+ - name: on return, a null-terminated string containing the driver's name
+ - error message: on return, should contain a user message describing
+ the type of error that occured during ASIOInit(), if any.
+ - sysRef: platform specific
+ Returns:
+ If neither input nor output is present ASE_NotPresent
+ will be returned.
+ ASE_NoMemory, ASE_HWMalfunction are other possible error conditions
+*/
+
+ASIOError ASIOExit(void);
+/* Purpose:
+ Terminates the AudioStreamIO.
+ Parameter:
+ None.
+ Returns:
+ If neither input nor output is present ASE_NotPresent
+ will be returned.
+ Notes: this implies ASIOStop() and ASIODisposeBuffers(),
+ meaning that no host callbacks must be accessed after ASIOExit().
+*/
+
+//- - - - - - - - - - - - - - - - - - - - - - - - -
+// Start/Stop
+//- - - - - - - - - - - - - - - - - - - - - - - - -
+
+ASIOError ASIOStart(void);
+/* Purpose:
+ Start input and output processing synchronously.
+ This will
+ - reset the sample counter to zero
+ - start the hardware (both input and output)
+ The first call to the hosts' bufferSwitch(index == 0) then tells
+ the host to read from input buffer A (index 0), and start
+ processing to output buffer A while output buffer B (which
+ has been filled by the host prior to calling ASIOStart())
+ is possibly sounding (see also ASIOGetLatencies())
+ Parameter:
+ None.
+ Returns:
+ If neither input nor output is present, ASE_NotPresent
+ will be returned.
+ If the hardware fails to start, ASE_HWMalfunction will be returned.
+ Notes:
+ There is no restriction on the time that ASIOStart() takes
+ to perform (that is, it is not considered a realtime trigger).
+*/
+
+ASIOError ASIOStop(void);
+/* Purpose:
+ Stops input and output processing altogether.
+ Parameter:
+ None.
+ Returns:
+ If neither input nor output is present ASE_NotPresent
+ will be returned.
+ Notes:
+ On return from ASIOStop(), the driver must in no
+ case call the hosts' bufferSwitch() routine.
+*/
+
+//- - - - - - - - - - - - - - - - - - - - - - - - -
+// Inquiry methods and sample rate
+//- - - - - - - - - - - - - - - - - - - - - - - - -
+
+ASIOError ASIOGetChannels(long *numInputChannels, long *numOutputChannels);
+/* Purpose:
+ Returns number of individual input/output channels.
+ Parameter:
+ numInputChannels will hold the number of available input channels
+ numOutputChannels will hold the number of available output channels
+ Returns:
+ If no input/output is present ASE_NotPresent will be returned.
+ If only inputs, or only outputs are available, the according
+ other parameter will be zero, and ASE_OK is returned.
+*/
+
+ASIOError ASIOGetLatencies(long *inputLatency, long *outputLatency);
+/* Purpose:
+ Returns the input and output latencies. This includes
+ device specific delays, like FIFOs etc.
+ Parameter:
+ inputLatency will hold the 'age' of the first sample frame
+ in the input buffer when the hosts reads it in bufferSwitch()
+ (this is theoretical, meaning it does not include the overhead
+ and delay between the actual physical switch, and the time
+ when bufferSitch() enters).
+ This will usually be the size of one block in sample frames, plus
+ device specific latencies.
+
+ outputLatency will specify the time between the buffer switch,
+ and the time when the next play buffer will start to sound.
+ The next play buffer is defined as the one the host starts
+ processing after (or at) bufferSwitch(), indicated by the
+ index parameter (0 for buffer A, 1 for buffer B).
+ It will usually be either one block, if the host writes directly
+ to a dma buffer, or two or more blocks if the buffer is 'latched' by
+ the driver. As an example, on ASIOStart(), the host will have filled
+ the play buffer at index 1 already; when it gets the callback (with
+ the parameter index == 0), this tells it to read from the input
+ buffer 0, and start to fill the play buffer 0 (assuming that now
+ play buffer 1 is already sounding). In this case, the output
+ latency is one block. If the driver decides to copy buffer 1
+ at that time, and pass it to the hardware at the next slot (which
+ is most commonly done, but should be avoided), the output latency
+ becomes two blocks instead, resulting in a total i/o latency of at least
+ 3 blocks. As memory access is the main bottleneck in native dsp processing,
+ and to acheive less latency, it is highly recommended to try to avoid
+ copying (this is also why the driver is the owner of the buffers). To
+ summarize, the minimum i/o latency can be acheived if the input buffer
+ is processed by the host into the output buffer which will physically
+ start to sound on the next time slice. Also note that the host expects
+ the bufferSwitch() callback to be accessed for each time slice in order
+ to retain sync, possibly recursively; if it fails to process a block in
+ time, it will suspend its operation for some time in order to recover.
+ Returns:
+ If no input/output is present ASE_NotPresent will be returned.
+*/
+
+ASIOError ASIOGetBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity);
+/* Purpose:
+ Returns min, max, and preferred buffer sizes for input/output
+ Parameter:
+ minSize will hold the minimum buffer size
+ maxSize will hold the maxium possible buffer size
+ preferredSize will hold the preferred buffer size (a size which
+ best fits performance and hardware requirements)
+ granularity will hold the granularity at which buffer sizes
+ may differ. Usually, the buffer size will be a power of 2;
+ in this case, granularity will hold -1 on return, signalling
+ possible buffer sizes starting from minSize, increased in
+ powers of 2 up to maxSize.
+ Returns:
+ If no input/output is present ASE_NotPresent will be returned.
+ Notes:
+ When minimum and maximum buffer size are equal,
+ the preferred buffer size has to be the same value as well; granularity
+ should be 0 in this case.
+*/
+
+ASIOError ASIOCanSampleRate(ASIOSampleRate sampleRate);
+/* Purpose:
+ Inquires the hardware for the available sample rates.
+ Parameter:
+ sampleRate is the rate in question.
+ Returns:
+ If the inquired sample rate is not supported, ASE_NoClock will be returned.
+ If no input/output is present ASE_NotPresent will be returned.
+*/
+ASIOError ASIOGetSampleRate(ASIOSampleRate *currentRate);
+/* Purpose:
+ Get the current sample Rate.
+ Parameter:
+ currentRate will hold the current sample rate on return.
+ Returns:
+ If sample rate is unknown, sampleRate will be 0 and ASE_NoClock will be returned.
+ If no input/output is present ASE_NotPresent will be returned.
+ Notes:
+*/
+
+ASIOError ASIOSetSampleRate(ASIOSampleRate sampleRate);
+/* Purpose:
+ Set the hardware to the requested sample Rate. If sampleRate == 0,
+ enable external sync.
+ Parameter:
+ sampleRate: on input, the requested rate
+ Returns:
+ If sampleRate is unknown ASE_NoClock will be returned.
+ If the current clock is external, and sampleRate is != 0,
+ ASE_InvalidMode will be returned
+ If no input/output is present ASE_NotPresent will be returned.
+ Notes:
+*/
+
+typedef struct ASIOClockSource
+{
+ long index; // as used for ASIOSetClockSource()
+ long associatedChannel; // for instance, S/PDIF or AES/EBU
+ long associatedGroup; // see channel groups (ASIOGetChannelInfo())
+ ASIOBool isCurrentSource; // ASIOTrue if this is the current clock source
+ char name[32]; // for user selection
+} ASIOClockSource;
+
+ASIOError ASIOGetClockSources(ASIOClockSource *clocks, long *numSources);
+/* Purpose:
+ Get the available external audio clock sources
+ Parameter:
+ clocks points to an array of ASIOClockSource structures:
+ - index: this is used to identify the clock source
+ when ASIOSetClockSource() is accessed, should be
+ an index counting from zero
+ - associatedInputChannel: the first channel of an associated
+ input group, if any.
+ - associatedGroup: the group index of that channel.
+ groups of channels are defined to seperate for
+ instance analog, S/PDIF, AES/EBU, ADAT connectors etc,
+ when present simultaniously. Note that associated channel
+ is enumerated according to numInputs/numOutputs, means it
+ is independant from a group (see also ASIOGetChannelInfo())
+ inputs are associated to a clock if the physical connection
+ transfers both data and clock (like S/PDIF, AES/EBU, or
+ ADAT inputs). if there is no input channel associated with
+ the clock source (like Word Clock, or internal oscillator), both
+ associatedChannel and associatedGroup should be set to -1.
+ - isCurrentSource: on exit, ASIOTrue if this is the current clock
+ source, ASIOFalse else
+ - name: a null-terminated string for user selection of the available sources.
+ numSources:
+ on input: the number of allocated array members
+ on output: the number of available clock sources, at least
+ 1 (internal clock generator).
+ Returns:
+ If no input/output is present ASE_NotPresent will be returned.
+ Notes:
+*/
+
+ASIOError ASIOSetClockSource(long index);
+/* Purpose:
+ Set the audio clock source
+ Parameter:
+ index as obtained from an inquiry to ASIOGetClockSources()
+ Returns:
+ If no input/output is present ASE_NotPresent will be returned.
+ If the clock can not be selected because an input channel which
+ carries the current clock source is active, ASE_InvalidMode
+ *may* be returned (this depends on the properties of the driver
+ and/or hardware).
+ Notes:
+ Should *not* return ASE_NoClock if there is no clock signal present
+ at the selected source; this will be inquired via ASIOGetSampleRate().
+ It should call the host callback procedure sampleRateHasChanged(),
+ if the switch causes a sample rate change, or if no external clock
+ is present at the selected source.
+*/
+
+ASIOError ASIOGetSamplePosition (ASIOSamples *sPos, ASIOTimeStamp *tStamp);
+/* Purpose:
+ Inquires the sample position/time stamp pair.
+ Parameter:
+ sPos will hold the sample position on return. The sample
+ position is reset to zero when ASIOStart() gets called.
+ tStamp will hold the system time when the sample position
+ was latched.
+ Returns:
+ If no input/output is present, ASE_NotPresent will be returned.
+ If there is no clock, ASE_SPNotAdvancing will be returned.
+ Notes:
+
+ in order to be able to synchronise properly,
+ the sample position / time stamp pair must refer to the current block,
+ that is, the engine will call ASIOGetSamplePosition() in its bufferSwitch()
+ callback and expect the time for the current block. thus, when requested
+ in the very first bufferSwitch after ASIO_Start(), the sample position
+ should be zero, and the time stamp should refer to the very time where
+ the stream was started. it also means that the sample position must be
+ block aligned. the driver must ensure proper interpolation if the system
+ time can not be determined for the block position. the driver is responsible
+ for precise time stamps as it usually has most direct access to lower
+ level resources. proper behaviour of ASIO_GetSamplePosition() and ASIO_GetLatencies()
+ are essential for precise media synchronization!
+*/
+
+typedef struct ASIOChannelInfo
+{
+ long channel; // on input, channel index
+ ASIOBool isInput; // on input
+ ASIOBool isActive; // on exit
+ long channelGroup; // dto
+ ASIOSampleType type; // dto
+ char name[32]; // dto
+} ASIOChannelInfo;
+
+ASIOError ASIOGetChannelInfo(ASIOChannelInfo *info);
+/* Purpose:
+ retreive information about the nature of a channel
+ Parameter:
+ info: pointer to a ASIOChannelInfo structure with
+ - channel: on input, the channel index of the channel in question.
+ - isInput: on input, ASIOTrue if info for an input channel is
+ requested, else output
+ - channelGroup: on return, the channel group that the channel
+ belongs to. For drivers which support different types of
+ channels, like analog, S/PDIF, AES/EBU, ADAT etc interfaces,
+ there should be a reasonable grouping of these types. Groups
+ are always independant form a channel index, that is, a channel
+ index always counts from 0 to numInputs/numOutputs regardless
+ of the group it may belong to.
+ There will always be at least one group (group 0). Please
+ also note that by default, the host may decide to activate
+ channels 0 and 1; thus, these should belong to the most
+ useful type (analog i/o, if present).
+ - type: on return, contains the sample type of the channel
+ - isActive: on return, ASIOTrue if channel is active as it was
+ installed by ASIOCreateBuffers(), ASIOFalse else
+ - name: describing the type of channel in question. Used to allow
+ for user selection, and enabling of specific channels. examples:
+ "Analog In", "SPDIF Out" etc
+ Returns:
+ If no input/output is present ASE_NotPresent will be returned.
+ Notes:
+ If possible, the string should be organised such that the first
+ characters are most significantly describing the nature of the
+ port, to allow for identification even if the view showing the
+ port name is too small to display more than 8 characters, for
+ instance.
+*/
+
+//- - - - - - - - - - - - - - - - - - - - - - - - -
+// Buffer preparation
+//- - - - - - - - - - - - - - - - - - - - - - - - -
+
+typedef struct ASIOBufferInfo
+{
+ ASIOBool isInput; // on input: ASIOTrue: input, else output
+ long channelNum; // on input: channel index
+ void *buffers[2]; // on output: double buffer addresses
+} ASIOBufferInfo;
+
+ASIOError ASIOCreateBuffers(ASIOBufferInfo *bufferInfos, long numChannels,
+ long bufferSize, ASIOCallbacks *callbacks);
+
+/* Purpose:
+ Allocates input/output buffers for all input and output channels to be activated.
+ Parameter:
+ bufferInfos is a pointer to an array of ASIOBufferInfo structures:
+ - isInput: on input, ASIOTrue if the buffer is to be allocated
+ for an input, output buffer else
+ - channelNum: on input, the index of the channel in question
+ (counting from 0)
+ - buffers: on exit, 2 pointers to the halves of the channels' double-buffer.
+ the size of the buffer(s) of course depend on both the ASIOSampleType
+ as obtained from ASIOGetChannelInfo(), and bufferSize
+ numChannels is the sum of all input and output channels to be created;
+ thus bufferInfos is a pointer to an array of numChannels ASIOBufferInfo
+ structures.
+ bufferSize selects one of the possible buffer sizes as obtained from
+ ASIOGetBufferSizes().
+ callbacks is a pointer to an ASIOCallbacks structure.
+ Returns:
+ If not enough memory is available ASE_NoMemory will be returned.
+ If no input/output is present ASE_NotPresent will be returned.
+ If bufferSize is not supported, or one or more of the bufferInfos elements
+ contain invalid settings, ASE_InvalidMode will be returned.
+ Notes:
+ If individual channel selection is not possible but requested,
+ the driver has to handle this. namely, bufferSwitch() will only
+ have filled buffers of enabled outputs. If possible, processing
+ and buss activities overhead should be avoided for channels which
+ were not enabled here.
+*/
+
+ASIOError ASIODisposeBuffers(void);
+/* Purpose:
+ Releases all buffers for the device.
+ Parameter:
+ None.
+ Returns:
+ If no buffer were ever prepared, ASE_InvalidMode will be returned.
+ If no input/output is present ASE_NotPresent will be returned.
+ Notes:
+ This implies ASIOStop().
+*/
+
+ASIOError ASIOControlPanel(void);
+/* Purpose:
+ request the driver to start a control panel component
+ for device specific user settings. This will not be
+ accessed on some platforms (where the component is accessed
+ instead).
+ Parameter:
+ None.
+ Returns:
+ If no panel is available ASE_NotPresent will be returned.
+ Actually, the return code is ignored.
+ Notes:
+ if the user applied settings which require a re-configuration
+ of parts or all of the enigine and/or driver (such as a change of
+ the block size), the asioMessage callback can be used (see
+ ASIO_Callbacks).
+*/
+
+ASIOError ASIOFuture(long selector, void *params);
+/* Purpose:
+ various
+ Parameter:
+ selector: operation Code as to be defined. zero is reserved for
+ testing purposes.
+ params: depends on the selector; usually pointer to a structure
+ for passing and retreiving any type and amount of parameters.
+ Returns:
+ the return value is also selector dependant. if the selector
+ is unknown, ASE_InvalidParameter should be returned to prevent
+ further calls with this selector. on success, ASE_SUCCESS
+ must be returned (note: ASE_OK is *not* sufficient!)
+ Notes:
+ see selectors defined below.
+*/
+
+enum
+{
+ kAsioEnableTimeCodeRead = 1, // no arguments
+ kAsioDisableTimeCodeRead, // no arguments
+ kAsioSetInputMonitor, // ASIOInputMonitor* in params
+ kAsioTransport, // ASIOTransportParameters* in params
+ kAsioSetInputGain, // ASIOChannelControls* in params, apply gain
+ kAsioGetInputMeter, // ASIOChannelControls* in params, fill meter
+ kAsioSetOutputGain, // ASIOChannelControls* in params, apply gain
+ kAsioGetOutputMeter, // ASIOChannelControls* in params, fill meter
+ kAsioCanInputMonitor, // no arguments for kAsioCanXXX selectors
+ kAsioCanTimeInfo,
+ kAsioCanTimeCode,
+ kAsioCanTransport,
+ kAsioCanInputGain,
+ kAsioCanInputMeter,
+ kAsioCanOutputGain,
+ kAsioCanOutputMeter,
+ kAsioOptionalOne,
+
+ // DSD support
+ // The following extensions are required to allow switching
+ // and control of the DSD subsystem.
+ kAsioSetIoFormat = 0x23111961, /* ASIOIoFormat * in params. */
+ kAsioGetIoFormat = 0x23111983, /* ASIOIoFormat * in params. */
+ kAsioCanDoIoFormat = 0x23112004, /* ASIOIoFormat * in params. */
+
+ // Extension for drop out detection
+ kAsioCanReportOverload = 0x24042012, /* return ASE_SUCCESS if driver can detect and report overloads */
+
+ kAsioGetInternalBufferSamples = 0x25042012 /* ASIOInternalBufferInfo * in params. Deliver size of driver internal buffering, return ASE_SUCCESS if supported */
+};
+
+typedef struct ASIOInputMonitor
+{
+ long input; // this input was set to monitor (or off), -1: all
+ long output; // suggested output for monitoring the input (if so)
+ long gain; // suggested gain, ranging 0 - 0x7fffffffL (-inf to +12 dB)
+ ASIOBool state; // ASIOTrue => on, ASIOFalse => off
+ long pan; // suggested pan, 0 => all left, 0x7fffffff => right
+} ASIOInputMonitor;
+
+typedef struct ASIOChannelControls
+{
+ long channel; // on input, channel index
+ ASIOBool isInput; // on input
+ long gain; // on input, ranges 0 thru 0x7fffffff
+ long meter; // on return, ranges 0 thru 0x7fffffff
+ char future[32];
+} ASIOChannelControls;
+
+typedef struct ASIOTransportParameters
+{
+ long command; // see enum below
+ ASIOSamples samplePosition;
+ long track;
+ long trackSwitches[16]; // 512 tracks on/off
+ char future[64];
+} ASIOTransportParameters;
+
+enum
+{
+ kTransStart = 1,
+ kTransStop,
+ kTransLocate, // to samplePosition
+ kTransPunchIn,
+ kTransPunchOut,
+ kTransArmOn, // track
+ kTransArmOff, // track
+ kTransMonitorOn, // track
+ kTransMonitorOff, // track
+ kTransArm, // trackSwitches
+ kTransMonitor // trackSwitches
+};
+
+/*
+// DSD support
+// Some notes on how to use ASIOIoFormatType.
+//
+// The caller will fill the format with the request types.
+// If the board can do the request then it will leave the
+// values unchanged. If the board does not support the
+// request then it will change that entry to Invalid (-1)
+//
+// So to request DSD then
+//
+// ASIOIoFormat NeedThis={kASIODSDFormat};
+//
+// if(ASE_SUCCESS != ASIOFuture(kAsioSetIoFormat,&NeedThis) ){
+// // If the board did not accept one of the parameters then the
+// // whole call will fail and the failing parameter will
+// // have had its value changes to -1.
+// }
+//
+// Note: Switching between the formats need to be done before the "prepared"
+// state (see ASIO 2 documentation) is entered.
+*/
+typedef long int ASIOIoFormatType;
+enum ASIOIoFormatType_e
+{
+ kASIOFormatInvalid = -1,
+ kASIOPCMFormat = 0,
+ kASIODSDFormat = 1,
+};
+
+typedef struct ASIOIoFormat_s
+{
+ ASIOIoFormatType FormatType;
+ char future[512-sizeof(ASIOIoFormatType)];
+} ASIOIoFormat;
+
+// Extension for drop detection
+// Note: Refers to buffering that goes beyond the double buffer e.g. used by USB driver designs
+typedef struct ASIOInternalBufferInfo
+{
+ long inputSamples; // size of driver's internal input buffering which is included in getLatencies
+ long outputSamples; // size of driver's internal output buffering which is included in getLatencies
+} ASIOInternalBufferInfo;
+
+
+ASIOError ASIOOutputReady(void);
+/* Purpose:
+ this tells the driver that the host has completed processing
+ the output buffers. if the data format required by the hardware
+ differs from the supported asio formats, but the hardware
+ buffers are DMA buffers, the driver will have to convert
+ the audio stream data; as the bufferSwitch callback is
+ usually issued at dma block switch time, the driver will
+ have to convert the *previous* host buffer, which increases
+ the output latency by one block.
+ when the host finds out that ASIOOutputReady() returns
+ true, it will issue this call whenever it completed
+ output processing. then the driver can convert the
+ host data directly to the dma buffer to be played next,
+ reducing output latency by one block.
+ another way to look at it is, that the buffer switch is called
+ in order to pass the *input* stream to the host, so that it can
+ process the input into the output, and the output stream is passed
+ to the driver when the host has completed its process.
+ Parameter:
+ None
+ Returns:
+ only if the above mentioned scenario is given, and a reduction
+ of output latency can be acheived by this mechanism, should
+ ASE_OK be returned. otherwise (and usually), ASE_NotPresent
+ should be returned in order to prevent further calls to this
+ function. note that the host may want to determine if it is
+ to use this when the system is not yet fully initialized, so
+ ASE_OK should always be returned if the mechanism makes sense.
+ Notes:
+ please remeber to adjust ASIOGetLatencies() according to
+ whether ASIOOutputReady() was ever called or not, if your
+ driver supports this scenario.
+ also note that the engine may fail to call ASIO_OutputReady()
+ in time in overload cases. as already mentioned, bufferSwitch
+ should be called for every block regardless of whether a block
+ could be processed in time.
+*/
+
+// restore old alignment
+#if defined(_MSC_VER) && !defined(__MWERKS__)
+#pragma pack(pop)
+#elif PRAGMA_ALIGN_SUPPORTED
+#pragma options align = reset
+#endif
+
+#endif
+
--- /dev/null
+/*
+ Steinberg Audio Stream I/O API
+ (c) 1996, Steinberg Soft- und Hardware GmbH
+ charlie (May 1996)
+
+ asiodrvr.cpp
+ c++ superclass to implement asio functionality. from this,
+ you can derive whatever required
+*/
+
+#include <string.h>
+#include "asiosys.h"
+#include "asiodrvr.h"
+
+#if WINDOWS
+#error do not use this
+AsioDriver::AsioDriver (LPUNKNOWN pUnk, HRESULT *phr) : CUnknown("My AsioDriver", pUnk, phr)
+{
+}
+
+#else
+
+AsioDriver::AsioDriver()
+{
+}
+
+#endif
+
+AsioDriver::~AsioDriver()
+{
+}
+
+ASIOBool AsioDriver::init(void *sysRef)
+{
+ return ASE_NotPresent;
+}
+
+void AsioDriver::getDriverName(char *name)
+{
+ strcpy(name, "No Driver");
+}
+
+long AsioDriver::getDriverVersion()
+{
+ return 0;
+}
+
+void AsioDriver::getErrorMessage(char *string)
+{
+ strcpy(string, "ASIO Driver Implementation Error!");
+}
+
+ASIOError AsioDriver::start()
+{
+ return ASE_NotPresent;
+}
+
+ASIOError AsioDriver::stop()
+{
+ return ASE_NotPresent;
+}
+
+ASIOError AsioDriver::getChannels(long *numInputChannels, long *numOutputChannels)
+{
+ return ASE_NotPresent;
+}
+
+ASIOError AsioDriver::getLatencies(long *inputLatency, long *outputLatency)
+{
+ return ASE_NotPresent;
+}
+
+ASIOError AsioDriver::getBufferSize(long *minSize, long *maxSize,
+ long *preferredSize, long *granularity)
+{
+ return ASE_NotPresent;
+}
+
+ASIOError AsioDriver::canSampleRate(ASIOSampleRate sampleRate)
+{
+ return ASE_NotPresent;
+}
+
+ASIOError AsioDriver::getSampleRate(ASIOSampleRate *sampleRate)
+{
+ return ASE_NotPresent;
+}
+
+ASIOError AsioDriver::setSampleRate(ASIOSampleRate sampleRate)
+{
+ return ASE_NotPresent;
+}
+
+ASIOError AsioDriver::getClockSources(ASIOClockSource *clocks, long *numSources)
+{
+ *numSources = 0;
+ return ASE_NotPresent;
+}
+
+ASIOError AsioDriver::setClockSource(long reference)
+{
+ return ASE_NotPresent;
+}
+
+ASIOError AsioDriver::getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp)
+{
+ return ASE_NotPresent;
+}
+
+ASIOError AsioDriver::getChannelInfo(ASIOChannelInfo *info)
+{
+ return ASE_NotPresent;
+}
+
+ASIOError AsioDriver::createBuffers(ASIOBufferInfo *channelInfos, long numChannels,
+ long bufferSize, ASIOCallbacks *callbacks)
+{
+ return ASE_NotPresent;
+}
+
+ASIOError AsioDriver::disposeBuffers()
+{
+ return ASE_NotPresent;
+}
+
+ASIOError AsioDriver::controlPanel()
+{
+ return ASE_NotPresent;
+}
+
+ASIOError AsioDriver::future(long selector, void *opt)
+{
+ return ASE_NotPresent;
+}
+
+ASIOError AsioDriver::outputReady()
+{
+ return ASE_NotPresent;
+}
\ No newline at end of file
--- /dev/null
+/*
+ Steinberg Audio Stream I/O API
+ (c) 1996, Steinberg Soft- und Hardware GmbH
+ charlie (May 1996)
+
+ asiodrvr.h
+ c++ superclass to implement asio functionality. from this,
+ you can derive whatever required
+*/
+
+#ifndef _asiodrvr_
+#define _asiodrvr_
+
+// cpu and os system we are running on
+#include "asiosys.h"
+// basic "C" interface
+#include "asio.h"
+
+class AsioDriver;
+extern AsioDriver *getDriver(); // for generic constructor
+
+#if WINDOWS
+#include <windows.h>
+#include "combase.h"
+#include "iasiodrv.h"
+class AsioDriver : public IASIO ,public CUnknown
+{
+public:
+ AsioDriver(LPUNKNOWN pUnk, HRESULT *phr);
+
+ DECLARE_IUNKNOWN
+ // Factory method
+ static CUnknown *CreateInstance(LPUNKNOWN pUnk, HRESULT *phr);
+ // IUnknown
+ virtual HRESULT STDMETHODCALLTYPE NonDelegatingQueryInterface(REFIID riid,void **ppvObject);
+
+#else
+
+class AsioDriver
+{
+public:
+ AsioDriver();
+#endif
+ virtual ~AsioDriver();
+
+ virtual ASIOBool init(void* sysRef);
+ virtual void getDriverName(char *name); // max 32 bytes incl. terminating zero
+ virtual long getDriverVersion();
+ virtual void getErrorMessage(char *string); // max 124 bytes incl.
+
+ virtual ASIOError start();
+ virtual ASIOError stop();
+
+ virtual ASIOError getChannels(long *numInputChannels, long *numOutputChannels);
+ virtual ASIOError getLatencies(long *inputLatency, long *outputLatency);
+ virtual ASIOError getBufferSize(long *minSize, long *maxSize,
+ long *preferredSize, long *granularity);
+
+ virtual ASIOError canSampleRate(ASIOSampleRate sampleRate);
+ virtual ASIOError getSampleRate(ASIOSampleRate *sampleRate);
+ virtual ASIOError setSampleRate(ASIOSampleRate sampleRate);
+ virtual ASIOError getClockSources(ASIOClockSource *clocks, long *numSources);
+ virtual ASIOError setClockSource(long reference);
+
+ virtual ASIOError getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp);
+ virtual ASIOError getChannelInfo(ASIOChannelInfo *info);
+
+ virtual ASIOError createBuffers(ASIOBufferInfo *bufferInfos, long numChannels,
+ long bufferSize, ASIOCallbacks *callbacks);
+ virtual ASIOError disposeBuffers();
+
+ virtual ASIOError controlPanel();
+ virtual ASIOError future(long selector, void *opt);
+ virtual ASIOError outputReady();
+};
+#endif
--- /dev/null
+#ifndef __asiosys__
+ #define __asiosys__
+
+ #if defined(_WIN32) || defined(_WIN64)
+ #undef MAC
+ #define PPC 0
+ #define WINDOWS 1
+ #define SGI 0
+ #define SUN 0
+ #define LINUX 0
+ #define BEOS 0
+
+ #define NATIVE_INT64 0
+ #define IEEE754_64FLOAT 1
+
+ #elif BEOS
+ #define MAC 0
+ #define PPC 0
+ #define WINDOWS 0
+ #define PC 0
+ #define SGI 0
+ #define SUN 0
+ #define LINUX 0
+
+ #define NATIVE_INT64 0
+ #define IEEE754_64FLOAT 1
+
+ #ifndef DEBUG
+ #define DEBUG 0
+ #if DEBUG
+ void DEBUGGERMESSAGE(char *string);
+ #else
+ #define DEBUGGERMESSAGE(a)
+ #endif
+ #endif
+
+ #elif SGI
+ #define MAC 0
+ #define PPC 0
+ #define WINDOWS 0
+ #define PC 0
+ #define SUN 0
+ #define LINUX 0
+ #define BEOS 0
+
+ #define NATIVE_INT64 0
+ #define IEEE754_64FLOAT 1
+
+ #ifndef DEBUG
+ #define DEBUG 0
+ #if DEBUG
+ void DEBUGGERMESSAGE(char *string);
+ #else
+ #define DEBUGGERMESSAGE(a)
+ #endif
+ #endif
+
+ #else // MAC
+
+ #define MAC 1
+ #define PPC 1
+ #define WINDOWS 0
+ #define PC 0
+ #define SGI 0
+ #define SUN 0
+ #define LINUX 0
+ #define BEOS 0
+
+ #define NATIVE_INT64 0
+ #define IEEE754_64FLOAT 1
+
+ #ifndef DEBUG
+ #define DEBUG 0
+ #if DEBUG
+ void DEBUGGERMESSAGE(char *string);
+ #else
+ #define DEBUGGERMESSAGE(a)
+ #endif
+ #endif
+ #endif
+
+#endif
--- /dev/null
+//==========================================================================;
+//
+// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+// PURPOSE.
+//
+// Copyright (c) 1992 - 1996 Microsoft Corporation. All Rights Reserved.
+//
+//--------------------------------------------------------------------------;
+
+// Base class hierachy for creating COM objects, December 1994
+
+#include <windows.h>
+#include "wxdebug.h"
+#include "combase.h"
+#pragma warning( disable : 4514 ) // Disable warnings re unused inline functions
+
+
+/* Define the static member variable */
+
+LONG CBaseObject::m_cObjects = 0;
+
+
+/* Constructor */
+
+CBaseObject::CBaseObject(TCHAR *pName)
+{
+ /* Increment the number of active objects */
+ InterlockedIncrement(&m_cObjects);
+
+#ifdef DEBUG
+ m_dwCookie = DbgRegisterObjectCreation(pName);
+#endif
+}
+
+
+/* Destructor */
+
+CBaseObject::~CBaseObject()
+{
+ /* Decrement the number of objects active */
+ InterlockedDecrement(&m_cObjects);
+
+#ifdef DEBUG
+ DbgRegisterObjectDestruction(m_dwCookie);
+#endif
+}
+
+
+/* Constructor */
+
+// We know we use "this" in the initialization list, we also know we don't modify *phr.
+#pragma warning( disable : 4355 4100 )
+CUnknown::CUnknown(TCHAR *pName, LPUNKNOWN pUnk, HRESULT *phr)
+: CBaseObject(pName)
+/* Start the object with a reference count of zero - when the */
+/* object is queried for it's first interface this may be */
+/* incremented depending on whether or not this object is */
+/* currently being aggregated upon */
+, m_cRef(0)
+/* Set our pointer to our IUnknown interface. */
+/* If we have an outer, use its, otherwise use ours. */
+/* This pointer effectivly points to the owner of */
+/* this object and can be accessed by the GetOwner() method. */
+, m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast<LPUNKNOWN>( static_cast<PNDUNKNOWN>(this) ) )
+ /* Why the double cast? Well, the inner cast is a type-safe cast */
+ /* to pointer to a type from which we inherit. The second is */
+ /* type-unsafe but works because INonDelegatingUnknown "behaves */
+ /* like" IUnknown. (Only the names on the methods change.) */
+{
+ // Everything we need to do has been done in the initializer list
+}
+#pragma warning( default : 4355 4100 )
+
+/* QueryInterface */
+
+STDMETHODIMP CUnknown::NonDelegatingQueryInterface(REFIID riid, void ** ppv)
+{
+ CheckPointer(ppv,E_POINTER);
+ ValidateReadWritePtr(ppv,sizeof(PVOID));
+
+ /* We know only about IUnknown */
+
+ if (riid == IID_IUnknown) {
+ GetInterface((LPUNKNOWN) (PNDUNKNOWN) this, ppv);
+ return NOERROR;
+ } else {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+}
+
+/* We have to ensure that we DON'T use a max macro, since these will typically */
+/* lead to one of the parameters being evaluated twice. Since we are worried */
+/* about concurrency, we can't afford to access the m_cRef twice since we can't */
+/* afford to run the risk that its value having changed between accesses. */
+#ifdef max
+ #undef max
+#endif
+
+template<class T> inline static T max( const T & a, const T & b )
+{
+ return a > b ? a : b;
+}
+
+/* AddRef */
+
+STDMETHODIMP_(ULONG) CUnknown::NonDelegatingAddRef()
+{
+ LONG lRef = InterlockedIncrement( &m_cRef );
+ ASSERT(lRef > 0);
+ DbgLog((LOG_MEMORY,3,TEXT(" Obj %d ref++ = %d"),
+ m_dwCookie, m_cRef));
+ return max(ULONG(m_cRef), 1ul);
+}
+
+
+
+/* Release */
+
+STDMETHODIMP_(ULONG) CUnknown::NonDelegatingRelease()
+{
+ /* If the reference count drops to zero delete ourselves */
+
+ LONG lRef = InterlockedDecrement( &m_cRef );
+ ASSERT(lRef >= 0);
+
+ DbgLog((LOG_MEMORY,3,TEXT(" Object %d ref-- = %d"),
+ m_dwCookie, m_cRef));
+ if (lRef == 0) {
+
+ // COM rules say we must protect against re-entrancy.
+ // If we are an aggregator and we hold our own interfaces
+ // on the aggregatee, the QI for these interfaces will
+ // addref ourselves. So after doing the QI we must release
+ // a ref count on ourselves. Then, before releasing the
+ // private interface, we must addref ourselves. When we do
+ // this from the destructor here it will result in the ref
+ // count going to 1 and then back to 0 causing us to
+ // re-enter the destructor. Hence we add an extra refcount here
+ // once we know we will delete the object.
+ // for an example aggregator see filgraph\distrib.cpp.
+
+ m_cRef++;
+
+ delete this;
+ return ULONG(0);
+ } else {
+ return max(ULONG(m_cRef), 1ul);
+ }
+}
+
+
+/* Return an interface pointer to a requesting client
+ performing a thread safe AddRef as necessary */
+
+HRESULT CUnknown::GetInterface(LPUNKNOWN pUnk, void **ppv)
+{
+ CheckPointer(ppv, E_POINTER);
+ *ppv = pUnk;
+ pUnk->AddRef();
+ return NOERROR;
+}
+
+
+/* Compares two interfaces and returns TRUE if they are on the same object */
+
+BOOL IsEqualObject(IUnknown *pFirst, IUnknown *pSecond)
+{
+ /* Different objects can't have the same interface pointer for
+ any interface
+ */
+ if (pFirst == pSecond) {
+ return TRUE;
+ }
+ /* OK - do it the hard way - check if they have the same
+ IUnknown pointers - a single object can only have one of these
+ */
+ LPUNKNOWN pUnknown1; // Retrieve the IUnknown interface
+ LPUNKNOWN pUnknown2; // Retrieve the other IUnknown interface
+ HRESULT hr; // General OLE return code
+
+ ASSERT(pFirst);
+ ASSERT(pSecond);
+
+ /* See if the IUnknown pointers match */
+
+ hr = pFirst->QueryInterface(IID_IUnknown,(void **) &pUnknown1);
+ ASSERT(SUCCEEDED(hr));
+ ASSERT(pUnknown1);
+
+ hr = pSecond->QueryInterface(IID_IUnknown,(void **) &pUnknown2);
+ ASSERT(SUCCEEDED(hr));
+ ASSERT(pUnknown2);
+
+ /* Release the extra interfaces we hold */
+
+ pUnknown1->Release();
+ pUnknown2->Release();
+ return (pUnknown1 == pUnknown2);
+}
--- /dev/null
+//==========================================================================;
+//
+// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+// PURPOSE.
+//
+// Copyright (c) 1992 - 1996 Microsoft Corporation. All Rights Reserved.
+//
+//--------------------------------------------------------------------------;
+
+// Base class hierachy for creating COM objects, December 1994
+
+/*
+
+a. Derive your COM object from CUnknown
+
+b. Make a static CreateInstance function that takes an LPUNKNOWN, an HRESULT *
+ and a TCHAR *. The LPUNKNOWN defines the object to delegate IUnknown calls
+ to. The HRESULT * allows error codes to be passed around constructors and
+ the TCHAR * is a descriptive name that can be printed on the debugger.
+
+ It is important that constructors only change the HRESULT * if they have
+ to set an ERROR code, if it was successful then leave it alone or you may
+ overwrite an error code from an object previously created.
+
+ When you call a constructor the descriptive name should be in static store
+ as we do not copy the string. To stop large amounts of memory being used
+ in retail builds by all these static strings use the NAME macro,
+
+ CMyFilter = new CImplFilter(NAME("My filter"),pUnknown,phr);
+ if (FAILED(hr)) {
+ return hr;
+ }
+
+ In retail builds NAME(_x_) compiles to NULL, the base CBaseObject class
+ knows not to do anything with objects that don't have a name.
+
+c. Have a constructor for your object that passes the LPUNKNOWN, HRESULT * and
+ TCHAR * to the CUnknown constructor. You can set the HRESULT if you have an
+ error, or just simply pass it through to the constructor.
+
+ The object creation will fail in the class factory if the HRESULT indicates
+ an error (ie FAILED(HRESULT) == TRUE)
+
+d. Create a FactoryTemplate with your object's class id and CreateInstance
+ function.
+
+Then (for each interface) either
+
+Multiple inheritance
+
+1. Also derive it from ISomeInterface
+2. Include DECLARE_IUNKNOWN in your class definition to declare
+ implementations of QueryInterface, AddRef and Release that
+ call the outer unknown
+3. Override NonDelegatingQueryInterface to expose ISomeInterface by
+ code something like
+
+ if (riid == IID_ISomeInterface) {
+ return GetInterface((ISomeInterface *) this, ppv);
+ } else {
+ return CUnknown::NonDelegatingQueryInterface(riid, ppv);
+ }
+
+4. Declare and implement the member functions of ISomeInterface.
+
+or: Nested interfaces
+
+1. Declare a class derived from CUnknown
+2. Include DECLARE_IUNKNOWN in your class definition
+3. Override NonDelegatingQueryInterface to expose ISomeInterface by
+ code something like
+
+ if (riid == IID_ISomeInterface) {
+ return GetInterface((ISomeInterface *) this, ppv);
+ } else {
+ return CUnknown::NonDelegatingQueryInterface(riid, ppv);
+ }
+
+4. Implement the member functions of ISomeInterface. Use GetOwner() to
+ access the COM object class.
+
+And in your COM object class:
+
+5. Make the nested class a friend of the COM object class, and declare
+ an instance of the nested class as a member of the COM object class.
+
+ NOTE that because you must always pass the outer unknown and an hResult
+ to the CUnknown constructor you cannot use a default constructor, in
+ other words you will have to make the member variable a pointer to the
+ class and make a NEW call in your constructor to actually create it.
+
+6. override the NonDelegatingQueryInterface with code like this:
+
+ if (riid == IID_ISomeInterface) {
+ return m_pImplFilter->
+ NonDelegatingQueryInterface(IID_ISomeInterface, ppv);
+ } else {
+ return CUnknown::NonDelegatingQueryInterface(riid, ppv);
+ }
+
+You can have mixed classes which support some interfaces via multiple
+inheritance and some via nested classes
+
+*/
+
+#ifndef __COMBASE__
+#define __COMBASE__
+
+/* The DLLENTRY module initialises the module handle on loading */
+
+extern HINSTANCE g_hInst;
+
+/* On DLL load remember which platform we are running on */
+
+extern DWORD g_amPlatform;
+extern OSVERSIONINFO g_osInfo; // Filled in by GetVersionEx
+
+/* Version of IUnknown that is renamed to allow a class to support both
+ non delegating and delegating IUnknowns in the same COM object */
+
+DECLARE_INTERFACE(INonDelegatingUnknown)
+{
+ STDMETHOD(NonDelegatingQueryInterface) (THIS_ REFIID, LPVOID *) PURE;
+ STDMETHOD_(ULONG, NonDelegatingAddRef)(THIS) PURE;
+ STDMETHOD_(ULONG, NonDelegatingRelease)(THIS) PURE;
+};
+
+typedef INonDelegatingUnknown *PNDUNKNOWN;
+
+
+/* This is the base object class that supports active object counting. As
+ part of the debug facilities we trace every time a C++ object is created
+ or destroyed. The name of the object has to be passed up through the class
+ derivation list during construction as you cannot call virtual functions
+ in the constructor. The downside of all this is that every single object
+ constructor has to take an object name parameter that describes it */
+
+class CBaseObject
+{
+
+private:
+
+ // Disable the copy constructor and assignment by default so you will get
+ // compiler errors instead of unexpected behaviour if you pass objects
+ // by value or assign objects.
+ CBaseObject(const CBaseObject& objectSrc); // no implementation
+ void operator=(const CBaseObject& objectSrc); // no implementation
+
+private:
+ static LONG m_cObjects; /* Total number of objects active */
+
+protected:
+#ifdef DEBUG
+ DWORD m_dwCookie; /* Cookie identifying this object */
+#endif
+
+
+public:
+
+ /* These increment and decrement the number of active objects */
+
+ CBaseObject(TCHAR *pName);
+ ~CBaseObject();
+
+ /* Call this to find if there are any CUnknown derived objects active */
+
+ static LONG ObjectsActive() {
+ return m_cObjects;
+ };
+};
+
+
+/* An object that supports one or more COM interfaces will be based on
+ this class. It supports counting of total objects for DLLCanUnloadNow
+ support, and an implementation of the core non delegating IUnknown */
+
+class CUnknown : public INonDelegatingUnknown,
+ public CBaseObject
+{
+
+private:
+ const LPUNKNOWN m_pUnknown; /* Owner of this object */
+
+protected: /* So we can override NonDelegatingRelease() */
+ volatile LONG m_cRef; /* Number of reference counts */
+
+public:
+
+ CUnknown(TCHAR *pName, LPUNKNOWN pUnk, HRESULT *phr);
+ virtual ~CUnknown() {};
+
+ /* Return the owner of this object */
+
+ LPUNKNOWN GetOwner() const {
+ return m_pUnknown;
+ };
+
+ /* Called from the class factory to create a new instance, it is
+ pure virtual so it must be overriden in your derived class */
+
+ /* static CUnknown *CreateInstance(LPUNKNOWN, HRESULT *) */
+
+ /* Non delegating unknown implementation */
+
+ STDMETHODIMP NonDelegatingQueryInterface(REFIID, void **);
+ STDMETHODIMP_(ULONG) NonDelegatingAddRef();
+ STDMETHODIMP_(ULONG) NonDelegatingRelease();
+
+ /* Return an interface pointer to a requesting client
+ performing a thread safe AddRef as necessary */
+
+ HRESULT GetInterface(LPUNKNOWN pUnk, void **ppv);
+
+
+};
+
+#if WINVER < 0x0501
+
+/* The standard InterlockedXXX functions won't take volatiles */
+static inline LONG InterlockedIncrement( volatile LONG * plong )
+{ return InterlockedIncrement( const_cast<LONG*>( plong ) ); }
+
+static inline LONG InterlockedDecrement( volatile LONG * plong )
+{ return InterlockedDecrement( const_cast<LONG*>( plong ) ); }
+
+static inline LONG InterlockedExchange( volatile LONG * plong, LONG new_value )
+{ return InterlockedExchange( const_cast<LONG*>( plong ), new_value ); }
+
+#endif
+
+/* A function that can create a new COM object */
+
+typedef CUnknown *(*LPFNNewCOMObject)(LPUNKNOWN pUnkOuter, HRESULT *phr);
+
+/* A function (can be NULL) which is called from the DLL entrypoint
+ routine for each factory template:
+
+ bLoading - TRUE on DLL load, FALSE on DLL unload
+ rclsid - the m_ClsID of the entry
+*/
+typedef void (*LPFNInitRoutine)(BOOL bLoading, const CLSID *rclsid);
+
+/* Create one of these per object class in an array so that
+ the default class factory code can create new instances */
+
+class CFactoryTemplate {
+
+public:
+
+ const WCHAR *m_Name;
+ const CLSID *m_ClsID;
+ LPFNNewCOMObject m_lpfnNew;
+ LPFNInitRoutine m_lpfnInit;
+
+ BOOL IsClassID(REFCLSID rclsid) const {
+ return (IsEqualCLSID(*m_ClsID,rclsid));
+ };
+
+ CUnknown *CreateInstance(LPUNKNOWN pUnk, HRESULT *phr) const {
+ return m_lpfnNew(pUnk, phr);
+ };
+};
+
+
+/* You must override the (pure virtual) NonDelegatingQueryInterface to return
+ interface pointers (using GetInterface) to the interfaces your derived
+ class supports (the default implementation only supports IUnknown) */
+
+#define DECLARE_IUNKNOWN \
+ STDMETHODIMP QueryInterface(REFIID riid, void **ppv) { \
+ return GetOwner()->QueryInterface(riid,ppv); \
+ }; \
+ STDMETHODIMP_(ULONG) AddRef() { \
+ return GetOwner()->AddRef(); \
+ }; \
+ STDMETHODIMP_(ULONG) Release() { \
+ return GetOwner()->Release(); \
+ };
+
+#endif /* __COMBASE__ */
+
+
--- /dev/null
+#include "asiosys.h"
+
+#if DEBUG
+#if MAC
+#include <TextUtils.h>
+void DEBUGGERMESSAGE(char *string)
+{
+ c2pstr(string);
+ DebugStr((unsigned char *)string);
+}
+#else
+#error debugmessage
+#endif
+#endif
--- /dev/null
+//==========================================================================;
+//
+// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+// PURPOSE.
+//
+// Copyright (c) 1992 - 1996 Microsoft Corporation. All Rights Reserved.
+//
+//--------------------------------------------------------------------------;
+
+//
+// classes used to support dll entrypoints for COM objects.
+//
+// #include "switches.h"
+
+#include <windows.h>
+#include "wxdebug.h"
+#include "combase.h"
+#ifdef DEBUG
+#include <tchar.h>
+#endif
+
+#include <stdio.h>
+
+extern CFactoryTemplate g_Templates[];
+extern int g_cTemplates;
+
+HINSTANCE hinstance = 0;
+DWORD g_amPlatform; // VER_PLATFORM_WIN32_WINDOWS etc... (from GetVersionEx)
+OSVERSIONINFO g_osInfo;
+
+//
+// an instance of this is created by the DLLGetClassObject entrypoint
+// it uses the CFactoryTemplate object it is given to support the
+// IClassFactory interface
+
+class CClassFactory : public IClassFactory
+{
+
+private:
+ const CFactoryTemplate * m_pTemplate;
+
+ ULONG m_cRef;
+
+ static int m_cLocked;
+public:
+ CClassFactory(const CFactoryTemplate *);
+
+ // IUnknown
+ STDMETHODIMP QueryInterface(REFIID riid, void ** ppv);
+ STDMETHODIMP_(ULONG)AddRef();
+ STDMETHODIMP_(ULONG)Release();
+
+ // IClassFactory
+ STDMETHODIMP CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, void **pv);
+ STDMETHODIMP LockServer(BOOL fLock);
+
+ // allow DLLGetClassObject to know about global server lock status
+ static BOOL IsLocked() {
+ return (m_cLocked > 0);
+ };
+};
+
+// process-wide dll locked state
+int CClassFactory::m_cLocked = 0;
+
+CClassFactory::CClassFactory(const CFactoryTemplate *pTemplate)
+{
+ m_cRef = 0;
+ m_pTemplate = pTemplate;
+}
+
+
+STDMETHODIMP CClassFactory::QueryInterface(REFIID riid,void **ppv)
+{
+ CheckPointer(ppv,E_POINTER)
+ ValidateReadWritePtr(ppv,sizeof(PVOID));
+ *ppv = NULL;
+
+ // any interface on this object is the object pointer.
+ if ((riid == IID_IUnknown) || (riid == IID_IClassFactory)) {
+ *ppv = (LPVOID) this;
+ // AddRef returned interface pointer
+ ((LPUNKNOWN) *ppv)->AddRef();
+ return NOERROR;
+ }
+
+ return ResultFromScode(E_NOINTERFACE);
+}
+
+
+STDMETHODIMP_(ULONG) CClassFactory::AddRef()
+{
+ return ++m_cRef;
+}
+
+STDMETHODIMP_(ULONG) CClassFactory::Release()
+{
+ LONG rc;
+
+ if (--m_cRef == 0) {
+ delete this;
+ rc = 0;
+ } else rc = m_cRef;
+
+ return rc;
+}
+
+STDMETHODIMP CClassFactory::CreateInstance(LPUNKNOWN pUnkOuter,REFIID riid,void **pv)
+{
+ CheckPointer(pv,E_POINTER)
+ ValidateReadWritePtr(pv,sizeof(void *));
+
+ /* Enforce the normal OLE rules regarding interfaces and delegation */
+
+ if (pUnkOuter != NULL) {
+ if (IsEqualIID(riid,IID_IUnknown) == FALSE) {
+ return ResultFromScode(E_NOINTERFACE);
+ }
+ }
+
+ /* Create the new object through the derived class's create function */
+
+ HRESULT hr = NOERROR;
+ CUnknown *pObj = m_pTemplate->CreateInstance(pUnkOuter, &hr);
+
+ if (pObj == NULL) {
+ return E_OUTOFMEMORY;
+ }
+
+ /* Delete the object if we got a construction error */
+
+ if (FAILED(hr)) {
+ delete pObj;
+ return hr;
+ }
+
+ /* Get a reference counted interface on the object */
+
+ /* We wrap the non-delegating QI with NDAddRef & NDRelease. */
+ /* This protects any outer object from being prematurely */
+ /* released by an inner object that may have to be created */
+ /* in order to supply the requested interface. */
+ pObj->NonDelegatingAddRef();
+ hr = pObj->NonDelegatingQueryInterface(riid, pv);
+ pObj->NonDelegatingRelease();
+ /* Note that if NonDelegatingQueryInterface fails, it will */
+ /* not increment the ref count, so the NonDelegatingRelease */
+ /* will drop the ref back to zero and the object will "self-*/
+ /* destruct". Hence we don't need additional tidy-up code */
+ /* to cope with NonDelegatingQueryInterface failing. */
+
+ if (SUCCEEDED(hr)) {
+ ASSERT(*pv);
+ }
+
+ return hr;
+}
+
+STDMETHODIMP CClassFactory::LockServer(BOOL fLock)
+{
+ if (fLock) {
+ m_cLocked++;
+ } else {
+ m_cLocked--;
+ }
+ return NOERROR;
+}
+
+
+// --- COM entrypoints -----------------------------------------
+// DllRegisterServer
+
+//called by COM to get the class factory object for a given class
+STDAPI DllGetClassObject(REFCLSID rClsID,REFIID riid,void **pv)
+{
+ // DebugBreak();
+
+ if (!(riid == IID_IUnknown) && !(riid == IID_IClassFactory)) {
+ return E_NOINTERFACE;
+ }
+
+ // traverse the array of templates looking for one with this
+ // class id
+ for (int i = 0; i < g_cTemplates; i++) {
+ const CFactoryTemplate * pT = &g_Templates[i];
+ if (pT->IsClassID(rClsID)) {
+
+ // found a template - make a class factory based on this
+ // template
+
+ *pv = (LPVOID) (LPUNKNOWN) new CClassFactory(pT);
+ if (*pv == NULL) {
+ return E_OUTOFMEMORY;
+ }
+ ((LPUNKNOWN)*pv)->AddRef();
+ return NOERROR;
+ }
+ }
+ return CLASS_E_CLASSNOTAVAILABLE;
+}
+
+//
+// Call any initialization routines
+//
+void DllInitClasses(BOOL bLoading)
+{
+ int i;
+
+ // DebugBreak();
+
+ // traverse the array of templates calling the init routine
+ // if they have one
+ for (i = 0; i < g_cTemplates; i++) {
+ const CFactoryTemplate * pT = &g_Templates[i];
+ if (pT->m_lpfnInit != NULL) {
+ (*pT->m_lpfnInit)(bLoading, pT->m_ClsID);
+ }
+ }
+
+}
+
+// called by COM to determine if this dll can be unloaded
+// return ok unless there are outstanding objects or a lock requested
+// by IClassFactory::LockServer
+//
+// CClassFactory has a static function that can tell us about the locks,
+// and CCOMObject has a static function that can tell us about the active
+// object count
+STDAPI DllCanUnloadNow()
+{
+ // DebugBreak();
+
+ DbgLog((LOG_MEMORY,2,TEXT("DLLCanUnloadNow called - IsLocked = %d, Active objects = %d"),
+ CClassFactory::IsLocked(),
+ CBaseObject::ObjectsActive()));
+
+ if (CClassFactory::IsLocked() || CBaseObject::ObjectsActive()) {
+
+ return S_FALSE;
+ }
+ else {
+ return S_OK;
+ }
+}
+
+
+// --- standard WIN32 entrypoints --------------------------------------
+
+
+//extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
+//BOOL WINAPI DllEntryPoint(HINSTANCE hInstance,ULONG ulReason,LPVOID pv)
+//BOOL WINAPI DllMain (HINSTANCE hInstance,ULONG ulReason,LPVOID pv)
+BOOL WINAPI DllEntryPoint (HINSTANCE hInstance,ULONG ulReason,LPVOID pv)
+{
+
+ // DebugBreak();
+
+ switch (ulReason) {
+
+ case DLL_PROCESS_ATTACH:
+ DisableThreadLibraryCalls(hInstance);
+ DbgInitialise(hInstance);
+ {
+ // The platform identifier is used to work out whether
+ // full unicode support is available or not. Hence the
+ // default will be the lowest common denominator - i.e. N/A
+ g_amPlatform = VER_PLATFORM_WIN32_WINDOWS; // win95 assumed in case GetVersionEx fails
+
+ g_osInfo.dwOSVersionInfoSize = sizeof(g_osInfo);
+ if (GetVersionEx(&g_osInfo)) {
+ g_amPlatform = g_osInfo.dwPlatformId;
+ }
+ else {
+ DbgLog((LOG_ERROR, 1, "Failed to get the OS platform, assuming Win95"));
+ }
+ }
+ hinstance = hInstance;
+ DllInitClasses(TRUE);
+
+ break;
+
+ case DLL_PROCESS_DETACH:
+ DllInitClasses(FALSE);
+
+#ifdef DEBUG
+ if (CBaseObject::ObjectsActive()) {
+ DbgSetModuleLevel(LOG_MEMORY, 2);
+ TCHAR szInfo[512];
+ extern TCHAR m_ModuleName[]; // Cut down module name
+
+ TCHAR FullName[_MAX_PATH]; // Load the full path and module name
+ TCHAR *pName; // Searches from the end for a backslash
+
+ GetModuleFileName(NULL,FullName,_MAX_PATH);
+ pName = _tcsrchr(FullName,'\\');
+ if (pName == NULL) {
+ pName = FullName;
+ }
+ else {
+ pName++;
+ }
+
+ DWORD cch = wsprintf(szInfo, TEXT("Executable: %s Pid %x Tid %x. "),
+ pName, GetCurrentProcessId(), GetCurrentThreadId());
+
+ wsprintf(szInfo+cch, TEXT("Module %s, %d objects left active!"),
+ m_ModuleName, CBaseObject::ObjectsActive());
+ DbgAssert(szInfo, TEXT(__FILE__),__LINE__);
+
+ // If running remotely wait for the Assert to be acknowledged
+ // before dumping out the object register
+ DbgDumpObjectRegister();
+ }
+ DbgTerminate();
+#endif
+ break;
+ }
+ return TRUE;
+}
+
+
--- /dev/null
+#include "asiosys.h"
+#include "asio.h"
+
+/* Forward Declarations */
+
+#ifndef __ASIODRIVER_FWD_DEFINED__
+#define __ASIODRIVER_FWD_DEFINED__
+typedef interface IASIO IASIO;
+#endif /* __ASIODRIVER_FWD_DEFINED__ */
+
+interface IASIO : public IUnknown
+{
+
+ virtual ASIOBool init(void *sysHandle) = 0;
+ virtual void getDriverName(char *name) = 0;
+ virtual long getDriverVersion() = 0;
+ virtual void getErrorMessage(char *string) = 0;
+ virtual ASIOError start() = 0;
+ virtual ASIOError stop() = 0;
+ virtual ASIOError getChannels(long *numInputChannels, long *numOutputChannels) = 0;
+ virtual ASIOError getLatencies(long *inputLatency, long *outputLatency) = 0;
+ virtual ASIOError getBufferSize(long *minSize, long *maxSize,
+ long *preferredSize, long *granularity) = 0;
+ virtual ASIOError canSampleRate(ASIOSampleRate sampleRate) = 0;
+ virtual ASIOError getSampleRate(ASIOSampleRate *sampleRate) = 0;
+ virtual ASIOError setSampleRate(ASIOSampleRate sampleRate) = 0;
+ virtual ASIOError getClockSources(ASIOClockSource *clocks, long *numSources) = 0;
+ virtual ASIOError setClockSource(long reference) = 0;
+ virtual ASIOError getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp) = 0;
+ virtual ASIOError getChannelInfo(ASIOChannelInfo *info) = 0;
+ virtual ASIOError createBuffers(ASIOBufferInfo *bufferInfos, long numChannels,
+ long bufferSize, ASIOCallbacks *callbacks) = 0;
+ virtual ASIOError disposeBuffers() = 0;
+ virtual ASIOError controlPanel() = 0;
+ virtual ASIOError future(long selector,void *opt) = 0;
+ virtual ASIOError outputReady() = 0;
+};
--- /dev/null
+#include <windows.h>
+#include <stdio.h>
+
+typedef struct keylist
+{
+ HKEY mainKey;
+ HKEY subKey;
+ char *keyname;
+ struct keylist *next;
+} KEYLIST, *LPKEYLIST;
+
+#define CLSID_STRING_LEN 100
+#define MAX_PATH_LEN 360
+
+#define DEV_ERR_SELFREG -100
+#define ERRSREG_MODULE_NOT_FOUND DEV_ERR_SELFREG-1
+#define ERRSREG_MODPATH_NOT_FOUND DEV_ERR_SELFREG-2
+#define ERRSREG_STRING_FROM_CLSID DEV_ERR_SELFREG-3
+#define ERRSREG_CHAR_TO_MULTIBYTE DEV_ERR_SELFREG-4
+
+#define SZREGSTR_DESCRIPTION "Description"
+#define SZREGSTR_CLSID "CLSID"
+#define SZREGSTR_INPROCSERVER32 "InprocServer32"
+#define SZREGSTR_THREADINGMODEL "ThreadingModel"
+#define SZREGSTR_SOFTWARE "SOFTWARE"
+#define SZREGSTR_ASIO "ASIO"
+
+LONG RegisterAsioDriver (CLSID,char *,char *,char *,char *);
+LONG UnregisterAsioDriver (CLSID,char *,char *);
+
+static LONG findRegPath (HKEY,char *);
+static LONG createRegPath (HKEY,char *,char *);
+static LONG createRegStringValue (HKEY,char *,char *,char *);
+static LONG getRegString (HKEY,char *,char *,LPVOID,DWORD);
+static LPKEYLIST findAllSubKeys (HKEY,HKEY,DWORD,char *,LPKEYLIST);
+static LONG deleteRegPath (HKEY,char *,char *);
+
+static char subkeybuf[MAX_PATH_LEN];
+
+
+// ------------------------------------------
+// Global Functions
+// ------------------------------------------
+LONG RegisterAsioDriver (CLSID clsid,char *szdllname,char *szregname,char *szasiodesc,char *szthreadmodel)
+{
+ HMODULE hMod;
+ char szDLLPath[MAX_PATH_LEN];
+ char szModuleName[MAX_PATH_LEN];
+ char szregpath[MAX_PATH_LEN];
+ char szclsid[CLSID_STRING_LEN];
+ LPOLESTR wszCLSID = NULL;
+ BOOL newregentry = FALSE;
+ LONG rc;
+
+ hMod = GetModuleHandle(szdllname);
+ if (!hMod) return ERRSREG_MODULE_NOT_FOUND;
+ szModuleName[0] = 0;
+ GetModuleFileName(hMod,szModuleName,MAX_PATH_LEN);
+ if (!szModuleName[0]) return ERRSREG_MODPATH_NOT_FOUND;
+ CharLower((LPTSTR)szModuleName);
+
+ rc = (LONG)StringFromCLSID(clsid,&wszCLSID);
+ if (rc != S_OK) return ERRSREG_STRING_FROM_CLSID;
+ rc = (LONG)WideCharToMultiByte(CP_ACP,0,(LPWSTR)wszCLSID,-1,szclsid,CLSID_STRING_LEN,0,0);
+ if (!rc) return ERRSREG_CHAR_TO_MULTIBYTE;
+
+ sprintf(szregpath,"%s\\%s",SZREGSTR_CLSID,szclsid);
+ rc = findRegPath(HKEY_CLASSES_ROOT,szregpath);
+ if (rc) {
+ sprintf(szregpath,"%s\\%s\\%s",SZREGSTR_CLSID,szclsid,SZREGSTR_INPROCSERVER32);
+ getRegString (HKEY_CLASSES_ROOT,szregpath,0,(LPVOID)szDLLPath,MAX_PATH_LEN);
+ CharLower((LPTSTR)szDLLPath);
+ rc = (LONG)strcmp(szDLLPath,szModuleName);
+ if (rc) {
+ // delete old regentry
+ sprintf(szregpath,"%s",SZREGSTR_CLSID);
+ deleteRegPath(HKEY_CLASSES_ROOT,szregpath,szclsid);
+ newregentry = TRUE;
+ }
+ }
+ else newregentry = TRUE;
+
+ if (newregentry) {
+ // HKEY_CLASSES_ROOT\CLSID\{...}
+ sprintf(szregpath,"%s",SZREGSTR_CLSID);
+ createRegPath (HKEY_CLASSES_ROOT,szregpath,szclsid);
+ // HKEY_CLASSES_ROOT\CLSID\{...} -> Description
+ sprintf(szregpath,"%s\\%s",SZREGSTR_CLSID,szclsid);
+ createRegStringValue(HKEY_CLASSES_ROOT,szregpath,0,szasiodesc);
+ // HKEY_CLASSES_ROOT\CLSID\InProcServer32
+ sprintf(szregpath,"%s\\%s",SZREGSTR_CLSID,szclsid);
+ createRegPath (HKEY_CLASSES_ROOT,szregpath,SZREGSTR_INPROCSERVER32);
+ // HKEY_CLASSES_ROOT\CLSID\InProcServer32 -> DLL path
+ sprintf(szregpath,"%s\\%s\\%s",SZREGSTR_CLSID,szclsid,SZREGSTR_INPROCSERVER32);
+ createRegStringValue(HKEY_CLASSES_ROOT,szregpath,0,szModuleName);
+ // HKEY_CLASSES_ROOT\CLSID\InProcServer32 -> ThreadingModel
+ createRegStringValue(HKEY_CLASSES_ROOT,szregpath,SZREGSTR_THREADINGMODEL,szthreadmodel);
+ }
+
+ // HKEY_LOCAL_MACHINE\SOFTWARE\ASIO
+ sprintf(szregpath,"%s\\%s",SZREGSTR_SOFTWARE,SZREGSTR_ASIO);
+ rc = findRegPath(HKEY_LOCAL_MACHINE,szregpath);
+ if (rc) {
+ sprintf(szregpath,"%s\\%s\\%s",SZREGSTR_SOFTWARE,SZREGSTR_ASIO,szregname);
+ rc = findRegPath(HKEY_LOCAL_MACHINE,szregpath);
+ if (rc) {
+ sprintf(szregpath,"%s\\%s",SZREGSTR_SOFTWARE,SZREGSTR_ASIO);
+ deleteRegPath(HKEY_LOCAL_MACHINE,szregpath,szregname);
+ }
+ }
+ else {
+ // HKEY_LOCAL_MACHINE\SOFTWARE\ASIO
+ sprintf(szregpath,"%s",SZREGSTR_SOFTWARE);
+ createRegPath (HKEY_LOCAL_MACHINE,szregpath,SZREGSTR_ASIO);
+ }
+
+ // HKEY_LOCAL_MACHINE\SOFTWARE\ASIO\<szregname>
+ sprintf(szregpath,"%s\\%s",SZREGSTR_SOFTWARE,SZREGSTR_ASIO);
+ createRegPath (HKEY_LOCAL_MACHINE,szregpath,szregname);
+
+ // HKEY_LOCAL_MACHINE\SOFTWARE\ASIO\<szregname> -> CLSID
+ // HKEY_LOCAL_MACHINE\SOFTWARE\ASIO\<szregname> -> Description
+ sprintf(szregpath,"%s\\%s\\%s",SZREGSTR_SOFTWARE,SZREGSTR_ASIO,szregname);
+ createRegStringValue(HKEY_LOCAL_MACHINE,szregpath,SZREGSTR_CLSID,szclsid);
+ createRegStringValue(HKEY_LOCAL_MACHINE,szregpath,SZREGSTR_DESCRIPTION,szasiodesc);
+
+ return 0;
+}
+
+
+LONG UnregisterAsioDriver (CLSID clsid,char *szdllname,char *szregname)
+{
+ LONG rc;
+ HMODULE hMod;
+ char szregpath[MAX_PATH_LEN];
+ char szModuleName[MAX_PATH_LEN];
+ char szclsid[CLSID_STRING_LEN];
+ LPOLESTR wszCLSID = NULL;
+
+
+ hMod = GetModuleHandle(szdllname);
+ if (!hMod) return ERRSREG_MODULE_NOT_FOUND;
+ szModuleName[0] = 0;
+ GetModuleFileName(hMod,szModuleName,MAX_PATH_LEN);
+ if (!szModuleName[0]) return ERRSREG_MODPATH_NOT_FOUND;
+ CharLower((LPTSTR)szModuleName);
+
+ rc = (LONG)StringFromCLSID(clsid,&wszCLSID) ;
+ if (rc != S_OK) return ERRSREG_STRING_FROM_CLSID;
+ rc = (LONG)WideCharToMultiByte(CP_ACP,0,(LPWSTR)wszCLSID,-1,szclsid,CLSID_STRING_LEN,0,0);
+ if (!rc) return ERRSREG_CHAR_TO_MULTIBYTE;
+
+
+ sprintf(szregpath,"%s\\%s",SZREGSTR_CLSID,szclsid);
+ rc = findRegPath(HKEY_CLASSES_ROOT,szregpath);
+ if (rc) {
+ // delete old regentry
+ sprintf(szregpath,"%s",SZREGSTR_CLSID);
+ deleteRegPath(HKEY_CLASSES_ROOT,szregpath,szclsid);
+ }
+
+
+ // HKEY_LOCAL_MACHINE\SOFTWARE\ASIO
+ sprintf(szregpath,"%s\\%s",SZREGSTR_SOFTWARE,SZREGSTR_ASIO);
+ rc = findRegPath(HKEY_LOCAL_MACHINE,szregpath);
+ if (rc) {
+ sprintf(szregpath,"%s\\%s\\%s",SZREGSTR_SOFTWARE,SZREGSTR_ASIO,szregname);
+ rc = findRegPath(HKEY_LOCAL_MACHINE,szregpath);
+ if (rc) {
+ sprintf(szregpath,"%s\\%s",SZREGSTR_SOFTWARE,SZREGSTR_ASIO);
+ deleteRegPath(HKEY_LOCAL_MACHINE,szregpath,szregname);
+ }
+ }
+
+ return 0;
+}
+
+
+// ------------------------------------------
+// Local Functions
+// ------------------------------------------
+static LONG findRegPath (HKEY mainkey,char *szregpath)
+{
+ HKEY hkey;
+ LONG cr,rc = -1;
+
+ if (szregpath) {
+ if ((cr = RegOpenKey(mainkey,szregpath,&hkey)) == ERROR_SUCCESS) {
+ RegCloseKey(hkey);
+ rc = 1;
+ }
+ else rc = 0;
+ }
+
+ return rc;
+}
+
+static LONG createRegPath (HKEY mainkey,char *szregpath,char *sznewpath)
+{
+ HKEY hkey,hksub;
+ LONG cr,rc = -1;
+ char newregpath[MAX_PATH_LEN];
+
+ sprintf(newregpath,"%s\\%s",szregpath,sznewpath);
+ if (!(cr = findRegPath(mainkey,newregpath))) {
+ if ((cr = RegOpenKey(mainkey,szregpath,&hkey)) == ERROR_SUCCESS) {
+ if ((cr = RegCreateKey(hkey,sznewpath,&hksub)) == ERROR_SUCCESS) {
+ RegCloseKey(hksub);
+ rc = 0;
+ }
+ RegCloseKey(hkey);
+ }
+ }
+ else if (cr > 0) rc = 0;
+
+ return rc;
+}
+
+static LONG createRegStringValue (HKEY mainkey,char *szregpath,char *valname,char *szvalstr)
+{
+ LONG cr,rc = -1;
+ HKEY hkey;
+
+ if (szregpath) {
+ if ((cr = RegOpenKey(mainkey,szregpath,&hkey)) == ERROR_SUCCESS) {
+ cr = RegSetValueEx(hkey,(LPCTSTR)valname,0,REG_SZ,(const BYTE *)szvalstr,(DWORD)strlen(szvalstr));
+ RegCloseKey(hkey);
+ if (cr == ERROR_SUCCESS) rc = 0;
+ }
+ }
+
+ return rc;
+}
+
+
+static LONG getRegString (HKEY mainkey,char *szregpath,char *valname,LPVOID pval,DWORD vsize)
+{
+ HKEY hkey;
+ LONG cr,rc = -1;
+ DWORD hsize,htype;
+
+ if (szregpath) {
+ if ((cr = RegOpenKey(mainkey,szregpath,&hkey)) == ERROR_SUCCESS) {
+ cr = RegQueryValueEx(hkey,valname,0,&htype,0,&hsize);
+ if (cr == ERROR_SUCCESS) {
+ if (hsize <= vsize) {
+ cr = RegQueryValueEx(hkey,valname,0,&htype,(LPBYTE)pval,&hsize);
+ rc = 0;
+ }
+ }
+ RegCloseKey(hkey);
+ }
+ }
+ return rc;
+}
+
+static LPKEYLIST findAllSubKeys (HKEY hkey,HKEY hksub,DWORD index,char *keyname,LPKEYLIST kl)
+{
+ HKEY hknew = 0;
+ char *newkey;
+ LONG cr;
+
+ if (!hksub) {
+ cr = RegOpenKeyEx(hkey,(LPCTSTR)keyname,0,KEY_ALL_ACCESS,&hknew);
+ if (cr != ERROR_SUCCESS) return kl;
+ }
+ else hknew = hksub;
+
+ cr = RegEnumKey(hknew,index,(LPTSTR)subkeybuf,MAX_PATH_LEN);
+ if (cr == ERROR_SUCCESS) {
+ newkey = new char[strlen(subkeybuf)+1];
+ strcpy(newkey,subkeybuf);
+
+ kl = findAllSubKeys(hknew,0,0,newkey,kl);
+ kl = findAllSubKeys(hkey,hknew,index+1,keyname,kl);
+
+ return kl;
+
+ }
+
+ if (!kl->next) {
+ kl->next = new KEYLIST[1];
+ kl = kl->next;
+ kl->mainKey = hkey;
+ kl->subKey = hknew;
+ kl->keyname = keyname;
+ kl->next = 0;
+ }
+
+ return kl;
+}
+
+static LONG deleteRegPath (HKEY mainkey,char *szregpath,char *szdelpath)
+{
+ HKEY hkey;
+ LONG cr,rc = -1;
+ KEYLIST klist;
+ LPKEYLIST pkl,k;
+ char *keyname = 0;
+
+ if ((cr = RegOpenKey(mainkey,szregpath,&hkey)) == ERROR_SUCCESS) {
+
+ keyname = new char[strlen(szdelpath)+1];
+ if (!keyname) {
+ RegCloseKey(hkey);
+ return rc;
+ }
+ strcpy(keyname,szdelpath);
+ klist.next = 0;
+
+ findAllSubKeys(hkey,0,0,keyname,&klist);
+
+ if (klist.next) {
+ pkl = klist.next;
+
+ while (pkl) {
+ RegCloseKey(pkl->subKey);
+ cr = RegDeleteKey(pkl->mainKey,pkl->keyname);
+ delete pkl->keyname;
+ k = pkl;
+ pkl = pkl->next;
+ delete k;
+ }
+ rc = 0;
+ }
+
+ RegCloseKey(hkey);
+ }
+
+ return rc;
+}
+
--- /dev/null
+//==========================================================================;
+//
+// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+// PURPOSE.
+//
+// Copyright (c) 1992 - 1996 Microsoft Corporation. All Rights Reserved.
+//
+//--------------------------------------------------------------------------;
+
+// Debugging facilities, January 1995
+
+#ifndef __WXDEBUG__
+#define __WXDEBUG__
+
+// Avoid conflict with MFC
+#undef ASSERT
+
+// This library provides fairly straight forward debugging functionality, this
+// is split into two main sections. The first is assertion handling, there are
+// three types of assertions provided here. The most commonly used one is the
+// ASSERT(condition) macro which will pop up a message box including the file
+// and line number if the condition evaluates to FALSE. Then there is the
+// EXECUTE_ASSERT macro which is the same as ASSERT except the condition will
+// still be executed in NON debug builds. The final type of assertion is the
+// KASSERT macro which is more suitable for pure (perhaps kernel) filters as
+// the condition is printed onto the debugger rather than in a message box.
+//
+// The other part of the debug module facilties is general purpose logging.
+// This is accessed by calling DbgLog(). The function takes a type and level
+// field which define the type of informational string you are presenting and
+// it's relative importance. The type field can be a combination (one or more)
+// of LOG_TIMING, LOG_TRACE, LOG_MEMORY, LOG_LOCKING and LOG_ERROR. The level
+// is a DWORD value where zero defines highest important. Use of zero as the
+// debug logging level is to be encouraged ONLY for major errors or events as
+// they will ALWAYS be displayed on the debugger. Other debug output has it's
+// level matched against the current debug output level stored in the registry
+// for this module and if less than the current setting it will be displayed.
+//
+// Each module or executable has it's own debug output level for each of the
+// five types. These are read in when the DbgInitialise function is called
+// for DLLs linking to STRMBASE.LIB this is done automatically when the DLL
+// is loaded, executables must call it explicitely with the module instance
+// handle given to them through the WINMAIN entry point. An executable must
+// also call DbgTerminate when they have finished to clean up the resources
+// the debug library uses, once again this is done automatically for DLLs
+
+// These are the five different categories of logging information
+
+enum { LOG_TIMING = 0x01, // Timing and performance measurements
+ LOG_TRACE = 0x02, // General step point call tracing
+ LOG_MEMORY = 0x04, // Memory and object allocation/destruction
+ LOG_LOCKING = 0x08, // Locking/unlocking of critical sections
+ LOG_ERROR = 0x10 }; // Debug error notification
+
+enum { CDISP_HEX = 0x01,
+ CDISP_DEC = 0x02};
+
+// For each object created derived from CBaseObject (in debug builds) we
+// create a descriptor that holds it's name (statically allocated memory)
+// and a cookie we assign it. We keep a list of all the active objects
+// we have registered so that we can dump a list of remaining objects
+
+typedef struct tag_ObjectDesc {
+ TCHAR *m_pName;
+ DWORD m_dwCookie;
+ tag_ObjectDesc *m_pNext;
+} ObjectDesc;
+
+#define DLLIMPORT __declspec(dllimport)
+#define DLLEXPORT __declspec(dllexport)
+
+#ifdef DEBUG
+
+ #define NAME(x) TEXT(x)
+
+ // These are used internally by the debug library (PRIVATE)
+
+ void DbgInitKeyLevels(HKEY hKey);
+ void DbgInitGlobalSettings();
+ void DbgInitModuleSettings();
+ void DbgInitModuleName();
+ DWORD DbgRegisterObjectCreation(TCHAR *pObjectName);
+ BOOL DbgRegisterObjectDestruction(DWORD dwCookie);
+
+ // These are the PUBLIC entry points
+
+ BOOL DbgCheckModuleLevel(DWORD Type,DWORD Level);
+ void DbgSetModuleLevel(DWORD Type,DWORD Level);
+
+ // Initialise the library with the module handle
+
+ void DbgInitialise(HINSTANCE hInst);
+ void DbgTerminate();
+
+ void DbgDumpObjectRegister();
+
+ // Display error and logging to the user
+
+ void DbgAssert(const TCHAR *pCondition,const TCHAR *pFileName,INT iLine);
+ void DbgBreakPoint(const TCHAR *pCondition,const TCHAR *pFileName,INT iLine);
+ void DbgKernelAssert(const TCHAR *pCondition,const TCHAR *pFileName,INT iLine);
+ void DbgLogInfo(DWORD Type,DWORD Level,const TCHAR *pFormat,...);
+ void DbgOutString(LPCTSTR psz);
+
+ // Debug infinite wait stuff
+ DWORD DbgWaitForSingleObject(HANDLE h);
+ DWORD DbgWaitForMultipleObjects(DWORD nCount,
+ CONST HANDLE *lpHandles,
+ BOOL bWaitAll);
+ void DbgSetWaitTimeout(DWORD dwTimeout);
+
+#ifdef __strmif_h__
+ void DisplayType(LPSTR label, const AM_MEDIA_TYPE *pmtIn);
+#endif
+
+ #define KASSERT(_x_) if (!(_x_)) \
+ DbgKernelAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__)
+
+ // Break on the debugger without putting up a message box
+ // message goes to debugger instead
+
+ #define KDbgBreak(_x_) \
+ DbgKernelAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__)
+
+ #define ASSERT(_x_) if (!(_x_)) \
+ DbgAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__)
+
+ // Put up a message box informing the user of a halt
+ // condition in the program
+
+ #define DbgBreak(_x_) \
+ DbgBreakPoint(TEXT(#_x_),TEXT(__FILE__),__LINE__)
+
+ #define EXECUTE_ASSERT(_x_) ASSERT(_x_)
+ #define DbgLog(_x_) DbgLogInfo _x_
+
+ // MFC style trace macros
+
+ #define NOTE(_x_) DbgLog((LOG_TRACE,5,TEXT(_x_)));
+ #define NOTE1(_x_,a) DbgLog((LOG_TRACE,5,TEXT(_x_),a));
+ #define NOTE2(_x_,a,b) DbgLog((LOG_TRACE,5,TEXT(_x_),a,b));
+ #define NOTE3(_x_,a,b,c) DbgLog((LOG_TRACE,5,TEXT(_x_),a,b,c));
+ #define NOTE4(_x_,a,b,c,d) DbgLog((LOG_TRACE,5,TEXT(_x_),a,b,c,d));
+ #define NOTE5(_x_,a,b,c,d,e) DbgLog((LOG_TRACE,5,TEXT(_x_),a,b,c,d,e));
+
+#else
+
+ // Retail builds make public debug functions inert - WARNING the source
+ // files do not define or build any of the entry points in debug builds
+ // (public entry points compile to nothing) so if you go trying to call
+ // any of the private entry points in your source they won't compile
+
+ #define NAME(_x_) NULL
+
+ #define DbgInitialise(hInst)
+ #define DbgTerminate()
+ #define DbgLog(_x_)
+ #define DbgOutString(psz)
+
+ #define DbgRegisterObjectCreation(pObjectName)
+ #define DbgRegisterObjectDestruction(dwCookie)
+ #define DbgDumpObjectRegister()
+
+ #define DbgCheckModuleLevel(Type,Level)
+ #define DbgSetModuleLevel(Type,Level)
+
+ #define DbgWaitForSingleObject(h) WaitForSingleObject(h, INFINITE)
+ #define DbgWaitForMultipleObjects(nCount, lpHandles, bWaitAll) \
+ WaitForMultipleObjects(nCount, lpHandles, bWaitAll, INFINITE)
+ #define DbgSetWaitTimeout(dwTimeout)
+
+ #define KDbgBreak(_x_)
+ #define DbgBreak(_x_)
+
+ #define KASSERT(_x_)
+ #define ASSERT(_x_)
+ #define EXECUTE_ASSERT(_x_) _x_
+
+ // MFC style trace macros
+
+ #define NOTE(_x_)
+ #define NOTE1(_x_,a)
+ #define NOTE2(_x_,a,b)
+ #define NOTE3(_x_,a,b,c)
+ #define NOTE4(_x_,a,b,c,d)
+ #define NOTE5(_x_,a,b,c,d,e)
+
+ #define DisplayType(label, pmtIn)
+
+#endif
+
+
+// Checks a pointer which should be non NULL - can be used as follows.
+
+#define CheckPointer(p,ret) {if((p)==NULL) return (ret);}
+
+// HRESULT Foo(VOID *pBar)
+// {
+// CheckPointer(pBar,E_INVALIDARG)
+// }
+//
+// Or if the function returns a boolean
+//
+// BOOL Foo(VOID *pBar)
+// {
+// CheckPointer(pBar,FALSE)
+// }
+
+// These validate pointers when symbol VFWROBUST is defined
+// This will normally be defined in debug not retail builds
+
+#ifdef DEBUG
+ #define VFWROBUST
+#endif
+
+#ifdef VFWROBUST
+
+ #define ValidateReadPtr(p,cb) \
+ {if(IsBadReadPtr((PVOID)p,cb) == TRUE) \
+ DbgBreak("Invalid read pointer");}
+
+ #define ValidateWritePtr(p,cb) \
+ {if(IsBadWritePtr((PVOID)p,cb) == TRUE) \
+ DbgBreak("Invalid write pointer");}
+
+ #define ValidateReadWritePtr(p,cb) \
+ {ValidateReadPtr(p,cb) ValidateWritePtr(p,cb)}
+
+ #define ValidateStringPtr(p) \
+ {if(IsBadStringPtr((LPCTSTR)p,INFINITE) == TRUE) \
+ DbgBreak("Invalid string pointer");}
+
+ #define ValidateStringPtrA(p) \
+ {if(IsBadStringPtrA((LPCSTR)p,INFINITE) == TRUE) \
+ DbgBreak("Invalid ANSII string pointer");}
+
+ #define ValidateStringPtrW(p) \
+ {if(IsBadStringPtrW((LPCWSTR)p,INFINITE) == TRUE) \
+ DbgBreak("Invalid UNICODE string pointer");}
+
+#else
+ #define ValidateReadPtr(p,cb)
+ #define ValidateWritePtr(p,cb)
+ #define ValidateReadWritePtr(p,cb)
+ #define ValidateStringPtr(p)
+ #define ValidateStringPtrA(p)
+ #define ValidateStringPtrW(p)
+#endif
+
+
+#ifdef _OBJBASE_H_
+
+ // Outputting GUID names. If you want to include the name
+ // associated with a GUID (eg CLSID_...) then
+ //
+ // GuidNames[yourGUID]
+ //
+ // Returns the name defined in uuids.h as a string
+
+ typedef struct {
+ TCHAR *szName;
+ GUID guid;
+ } GUID_STRING_ENTRY;
+
+ class CGuidNameList {
+ public:
+ TCHAR *operator [] (const GUID& guid);
+ };
+
+ extern CGuidNameList GuidNames;
+
+#endif
+
+
+// REMIND macro - generates warning as reminder to complete coding
+// (eg) usage:
+//
+// #pragma message (REMIND("Add automation support"))
+
+
+#define QUOTE(x) #x
+#define QQUOTE(y) QUOTE(y)
+#define REMIND(str) __FILE__ "(" QQUOTE(__LINE__) ") : " str
+
+
+// Hack to display objects in a useful format
+//
+// eg If you want to display a LONGLONG ll in a debug string do (eg)
+//
+// DbgLog((LOG_TRACE, n, TEXT("Value is %s"), (LPCTSTR)CDisp(ll, CDISP_HEX)));
+
+
+class CDispBasic
+{
+public:
+ CDispBasic() { m_pString = m_String; };
+ ~CDispBasic();
+protected:
+ PTCHAR m_pString; // normally points to m_String... unless too much data
+ TCHAR m_String[50];
+};
+class CDisp : public CDispBasic
+{
+public:
+ CDisp(LONGLONG ll, int Format = CDISP_HEX); // Display a LONGLONG in CDISP_HEX or CDISP_DEC form
+ CDisp(REFCLSID clsid); // Display a GUID
+ CDisp(double d); // Display a floating point number
+#ifdef __strmif_h__
+#ifdef __STREAMS__
+ CDisp(CRefTime t); // Display a Reference Time
+#endif
+ CDisp(IPin *pPin); // Display a pin as {filter clsid}(pin name)
+#endif // __strmif_h__
+ ~CDisp();
+
+ // Implement cast to (LPCTSTR) as parameter to logger
+ operator LPCTSTR()
+ {
+ return (LPCTSTR)m_pString;
+ };
+};
+
+#endif // __WXDEBUG__
+
--- /dev/null
+LIBRARY ASIOSample
+DESCRIPTION 'ASIO Sample Driver'
+PROTMODE
+EXPORTS
+ DllMain
+ DllGetClassObject
+ DllCanUnloadNow
+ DllRegisterServer
+ DllUnregisterServer
--- /dev/null
+Asiosample
+
+This sample driver illustrates the implementation of an ASIO driver.
+
+
+
+Windows notes:
+
+For Windows a COM implementation is provided. The final driver can be
+installed in the system by dragging the asiosample.dll onto the
+regsvr32.exe in the windows\system directory.
+
+It is normal that the LNK4104 warning is issued for the following 4
+exported symbols:
+
+DllGetClassObject
+DllCanUnloadNow
+DllRegisterServer
+DllUnregisterServer
+
+
+Macintosh notes:
+The supplied project is created with CodeWarrior Pro 5.
--- /dev/null
+# Microsoft Developer Studio Project File - Name="asiosample" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=asiosample - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "asiosample.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "asiosample.mak" CFG="asiosample - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "asiosample - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "asiosample - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "asiosample - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\Common" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:windows /dll /machine:I386
+
+!ELSEIF "$(CFG)" == "asiosample - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c
+# ADD CPP /nologo /G5 /MTd /W3 /Gm /GX /Zi /Od /I "..\..\..\Common" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "asiosample - Win32 Release"
+# Name "asiosample - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\asiosample.def
+# End Source File
+# Begin Source File
+
+SOURCE=..\asiosmpl.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\common\combase.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\common\dllentry.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\common\register.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\wintimer.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\common\asio.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\Asiodrvr.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\asiosmpl.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\common\asiosys.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\common\combase.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\common\iasiodrv.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
--- /dev/null
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="asiosample"
+ ProjectGUID="{D514DF49-CE45-4F09-9BAD-8FDA4BEF4DE3}"
+ RootNamespace="asiosample"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Debug/asiosample.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\..\Common"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib winmm.lib"
+ OutputFile="$(PlatformName)\$(ConfigurationName)\asiosample.dll"
+ LinkIncremental="2"
+ SuppressStartupBanner="true"
+ ModuleDefinitionFile="..\asiosample.def"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="3"
+ TypeLibraryName=".\Debug/asiosample.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\..\Common"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib winmm.lib"
+ OutputFile="$(PlatformName)\$(ConfigurationName)\asiosample.dll"
+ LinkIncremental="2"
+ SuppressStartupBanner="true"
+ ModuleDefinitionFile="..\asiosample.def"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Release/asiosample.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="..\..\..\Common"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib winmm.lib"
+ OutputFile="$(PlatformName)\$(ConfigurationName)\asiosample.dll"
+ LinkIncremental="1"
+ SuppressStartupBanner="true"
+ ModuleDefinitionFile="..\asiosample.def"
+ SubSystem="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="3"
+ TypeLibraryName=".\Release/asiosample.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="..\..\..\Common"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib winmm.lib"
+ OutputFile="$(PlatformName)\$(ConfigurationName)\asiosample.dll"
+ LinkIncremental="1"
+ SuppressStartupBanner="true"
+ ModuleDefinitionFile="..\asiosample.def"
+ SubSystem="2"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="..\asiosample.def"
+ >
+ </File>
+ <File
+ RelativePath="..\asiosmpl.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\..\common\combase.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\..\common\dllentry.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\..\common\register.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\wintimer.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="..\..\..\common\asio.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\Common\Asiodrvr.h"
+ >
+ </File>
+ <File
+ RelativePath="..\asiosmpl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\asiosys.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\combase.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\iasiodrv.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
--- /dev/null
+/*
+ Steinberg Audio Stream I/O API
+ (c) 1996, Steinberg Soft- und Hardware GmbH
+ charlie (May 1996)
+
+ asiosmpl.cpp
+
+ sample implementation of asio. can be set to simulate input with some
+ stupid oscillators.
+ this driver doesn't output sound at all...
+ timing is done via the extended time manager on the mac, and
+ a simple thread on pc.
+ you may test various configurations by changing the kNumInputs/Outputs,
+ and kBlockFrames. note that when using wave generation, as i/o is not optimized
+ at all, it moves quite a bit of memory, too many i/o channels may make it
+ pretty slow.
+
+ if you use this file as a template, make sure to resolve places where the
+ search string !!! can be found...
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include "asiosmpl.h"
+//#include "virtape.h"
+
+//------------------------------------------------------------------------------------------
+
+// extern
+void getNanoSeconds(ASIOTimeStamp *time);
+
+// local
+
+double AsioSamples2double (ASIOSamples* samples);
+
+static const double twoRaisedTo32 = 4294967296.;
+static const double twoRaisedTo32Reciprocal = 1. / twoRaisedTo32;
+
+//------------------------------------------------------------------------------------------
+// on windows, we do the COM stuff.
+
+#if WINDOWS
+#include "windows.h"
+#include "mmsystem.h"
+
+// class id. !!! NOTE: !!! you will obviously have to create your own class id!
+// {188135E1-D565-11d2-854F-00A0C99F5D19}
+CLSID IID_ASIO_DRIVER = { 0x188135e1, 0xd565, 0x11d2, { 0x85, 0x4f, 0x0, 0xa0, 0xc9, 0x9f, 0x5d, 0x19 } };
+
+CFactoryTemplate g_Templates[1] = {
+ {L"ASIOSAMPLE", &IID_ASIO_DRIVER, AsioSample::CreateInstance}
+};
+int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
+
+CUnknown* AsioSample::CreateInstance (LPUNKNOWN pUnk, HRESULT *phr)
+{
+ return (CUnknown*)new AsioSample (pUnk,phr);
+};
+
+STDMETHODIMP AsioSample::NonDelegatingQueryInterface (REFIID riid, void ** ppv)
+{
+ if (riid == IID_ASIO_DRIVER)
+ {
+ return GetInterface (this, ppv);
+ }
+ return CUnknown::NonDelegatingQueryInterface (riid, ppv);
+}
+
+// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// Register ASIO Driver
+// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+extern LONG RegisterAsioDriver (CLSID,char *,char *,char *,char *);
+extern LONG UnregisterAsioDriver (CLSID,char *,char *);
+
+//
+// Server registration, called on REGSVR32.EXE "the dllname.dll"
+//
+HRESULT _stdcall DllRegisterServer()
+{
+ LONG rc;
+ char errstr[128];
+
+ rc = RegisterAsioDriver (IID_ASIO_DRIVER,"ASIOSample.dll","ASIO Sample Driver","ASIO Sample","Apartment");
+
+ if (rc) {
+ memset(errstr,0,128);
+ sprintf(errstr,"Register Server failed ! (%d)",rc);
+ MessageBox(0,(LPCTSTR)errstr,(LPCTSTR)"ASIO sample Driver",MB_OK);
+ return -1;
+ }
+
+ return S_OK;
+}
+
+//
+// Server unregistration
+//
+HRESULT _stdcall DllUnregisterServer()
+{
+ LONG rc;
+ char errstr[128];
+
+ rc = UnregisterAsioDriver (IID_ASIO_DRIVER,"ASIOSample.dll","ASIO Sample Driver");
+
+ if (rc) {
+ memset(errstr,0,128);
+ sprintf(errstr,"Unregister Server failed ! (%d)",rc);
+ MessageBox(0,(LPCTSTR)errstr,(LPCTSTR)"ASIO Korg1212 I/O Driver",MB_OK);
+ return -1;
+ }
+
+ return S_OK;
+}
+
+//------------------------------------------------------------------------------------------
+//------------------------------------------------------------------------------------------
+AsioSample::AsioSample (LPUNKNOWN pUnk, HRESULT *phr)
+ : CUnknown("ASIOSAMPLE", pUnk, phr)
+
+//------------------------------------------------------------------------------------------
+
+#else
+
+// when not on windows, we derive from AsioDriver
+AsioSample::AsioSample () : AsioDriver ()
+
+#endif
+{
+ long i;
+
+ blockFrames = kBlockFrames;
+ inputLatency = blockFrames; // typically
+ outputLatency = blockFrames * 2;
+ // typically blockFrames * 2; try to get 1 by offering direct buffer
+ // access, and using asioPostOutput for lower latency
+ samplePosition = 0;
+ sampleRate = 44100.;
+ milliSeconds = (long)((double)(kBlockFrames * 1000) / sampleRate);
+ active = false;
+ started = false;
+ timeInfoMode = false;
+ tcRead = false;
+ for (i = 0; i < kNumInputs; i++)
+ {
+ inputBuffers[i] = 0;
+ inMap[i] = 0;
+ }
+#if TESTWAVES
+ sawTooth = sineWave = 0;
+#endif
+ for (i = 0; i < kNumOutputs; i++)
+ {
+ outputBuffers[i] = 0;
+ outMap[i] = 0;
+ }
+ callbacks = 0;
+ activeInputs = activeOutputs = 0;
+ toggle = 0;
+}
+
+//------------------------------------------------------------------------------------------
+AsioSample::~AsioSample ()
+{
+ stop ();
+ outputClose ();
+ inputClose ();
+ disposeBuffers ();
+}
+
+//------------------------------------------------------------------------------------------
+void AsioSample::getDriverName (char *name)
+{
+ strcpy (name, "Sample ASIO");
+}
+
+//------------------------------------------------------------------------------------------
+long AsioSample::getDriverVersion ()
+{
+ return 0x00000001L;
+}
+
+//------------------------------------------------------------------------------------------
+void AsioSample::getErrorMessage (char *string)
+{
+ strcpy (string, errorMessage);
+}
+
+//------------------------------------------------------------------------------------------
+ASIOBool AsioSample::init (void* sysRef)
+{
+ sysRef = sysRef;
+ if (active)
+ return true;
+ strcpy (errorMessage, "ASIO Driver open Failure!");
+ if (inputOpen ())
+ {
+ if (outputOpen ())
+ {
+ active = true;
+ return true;
+ }
+ }
+ timerOff (); // de-activate 'hardware'
+
+ outputClose ();
+ inputClose ();
+ return false;
+}
+
+//------------------------------------------------------------------------------------------
+ASIOError AsioSample::start ()
+{
+ if (callbacks)
+ {
+ started = false;
+ samplePosition = 0;
+ theSystemTime.lo = theSystemTime.hi = 0;
+ toggle = 0;
+
+ timerOn (); // activate 'hardware'
+ started = true;
+
+ return ASE_OK;
+ }
+ return ASE_NotPresent;
+}
+
+//------------------------------------------------------------------------------------------
+ASIOError AsioSample::stop ()
+{
+ started = false;
+ timerOff (); // de-activate 'hardware'
+ return ASE_OK;
+}
+
+//------------------------------------------------------------------------------------------
+ASIOError AsioSample::getChannels (long *numInputChannels, long *numOutputChannels)
+{
+ *numInputChannels = kNumInputs;
+ *numOutputChannels = kNumOutputs;
+ return ASE_OK;
+}
+
+//------------------------------------------------------------------------------------------
+ASIOError AsioSample::getLatencies (long *_inputLatency, long *_outputLatency)
+{
+ *_inputLatency = inputLatency;
+ *_outputLatency = outputLatency;
+ return ASE_OK;
+}
+
+//------------------------------------------------------------------------------------------
+ASIOError AsioSample::getBufferSize (long *minSize, long *maxSize,
+ long *preferredSize, long *granularity)
+{
+ *minSize = *maxSize = *preferredSize = blockFrames; // allow this size only
+ *granularity = 0;
+ return ASE_OK;
+}
+
+//------------------------------------------------------------------------------------------
+ASIOError AsioSample::canSampleRate (ASIOSampleRate sampleRate)
+{
+ if (sampleRate == 44100. || sampleRate == 48000.) // allow these rates only
+ return ASE_OK;
+ return ASE_NoClock;
+}
+
+//------------------------------------------------------------------------------------------
+ASIOError AsioSample::getSampleRate (ASIOSampleRate *sampleRate)
+{
+ *sampleRate = this->sampleRate;
+ return ASE_OK;
+}
+
+//------------------------------------------------------------------------------------------
+ASIOError AsioSample::setSampleRate (ASIOSampleRate sampleRate)
+{
+ if (sampleRate != 44100. && sampleRate != 48000.)
+ return ASE_NoClock;
+ if (sampleRate != this->sampleRate)
+ {
+ this->sampleRate = sampleRate;
+ asioTime.timeInfo.sampleRate = sampleRate;
+ asioTime.timeInfo.flags |= kSampleRateChanged;
+ milliSeconds = (long)((double)(kBlockFrames * 1000) / this->sampleRate);
+ if (callbacks && callbacks->sampleRateDidChange)
+ callbacks->sampleRateDidChange (this->sampleRate);
+ }
+ return ASE_OK;
+}
+
+//------------------------------------------------------------------------------------------
+ASIOError AsioSample::getClockSources (ASIOClockSource *clocks, long *numSources)
+{
+ // internal
+ clocks->index = 0;
+ clocks->associatedChannel = -1;
+ clocks->associatedGroup = -1;
+ clocks->isCurrentSource = ASIOTrue;
+ strcpy(clocks->name, "Internal");
+ *numSources = 1;
+ return ASE_OK;
+}
+
+//------------------------------------------------------------------------------------------
+ASIOError AsioSample::setClockSource (long index)
+{
+ if (!index)
+ {
+ asioTime.timeInfo.flags |= kClockSourceChanged;
+ return ASE_OK;
+ }
+ return ASE_NotPresent;
+}
+
+//------------------------------------------------------------------------------------------
+ASIOError AsioSample::getSamplePosition (ASIOSamples *sPos, ASIOTimeStamp *tStamp)
+{
+ tStamp->lo = theSystemTime.lo;
+ tStamp->hi = theSystemTime.hi;
+ if (samplePosition >= twoRaisedTo32)
+ {
+ sPos->hi = (unsigned long)(samplePosition * twoRaisedTo32Reciprocal);
+ sPos->lo = (unsigned long)(samplePosition - (sPos->hi * twoRaisedTo32));
+ }
+ else
+ {
+ sPos->hi = 0;
+ sPos->lo = (unsigned long)samplePosition;
+ }
+ return ASE_OK;
+}
+
+//------------------------------------------------------------------------------------------
+ASIOError AsioSample::getChannelInfo (ASIOChannelInfo *info)
+{
+ if (info->channel < 0 || (info->isInput ? info->channel >= kNumInputs : info->channel >= kNumOutputs))
+ return ASE_InvalidParameter;
+#if WINDOWS
+ info->type = ASIOSTInt16LSB;
+#else
+ info->type = ASIOSTInt16MSB;
+#endif
+ info->channelGroup = 0;
+ info->isActive = ASIOFalse;
+ long i;
+ if (info->isInput)
+ {
+ for (i = 0; i < activeInputs; i++)
+ {
+ if (inMap[i] == info->channel)
+ {
+ info->isActive = ASIOTrue;
+ break;
+ }
+ }
+ }
+ else
+ {
+ for (i = 0; i < activeOutputs; i++)
+ {
+ if (outMap[i] == info->channel)
+ {
+ info->isActive = ASIOTrue;
+ break;
+ }
+ }
+ }
+ strcpy(info->name, "Sample ");
+ return ASE_OK;
+}
+
+//------------------------------------------------------------------------------------------
+ASIOError AsioSample::createBuffers (ASIOBufferInfo *bufferInfos, long numChannels,
+ long bufferSize, ASIOCallbacks *callbacks)
+{
+ ASIOBufferInfo *info = bufferInfos;
+ long i;
+ bool notEnoughMem = false;
+
+ activeInputs = 0;
+ activeOutputs = 0;
+ blockFrames = bufferSize;
+ for (i = 0; i < numChannels; i++, info++)
+ {
+ if (info->isInput)
+ {
+ if (info->channelNum < 0 || info->channelNum >= kNumInputs)
+ goto error;
+ inMap[activeInputs] = info->channelNum;
+ inputBuffers[activeInputs] = new short[blockFrames * 2]; // double buffer
+ if (inputBuffers[activeInputs])
+ {
+ info->buffers[0] = inputBuffers[activeInputs];
+ info->buffers[1] = inputBuffers[activeInputs] + blockFrames;
+ }
+ else
+ {
+ info->buffers[0] = info->buffers[1] = 0;
+ notEnoughMem = true;
+ }
+ activeInputs++;
+ if (activeInputs > kNumInputs)
+ {
+error:
+ disposeBuffers();
+ return ASE_InvalidParameter;
+ }
+ }
+ else // output
+ {
+ if (info->channelNum < 0 || info->channelNum >= kNumOutputs)
+ goto error;
+ outMap[activeOutputs] = info->channelNum;
+ outputBuffers[activeOutputs] = new short[blockFrames * 2]; // double buffer
+ if (outputBuffers[activeOutputs])
+ {
+ info->buffers[0] = outputBuffers[activeOutputs];
+ info->buffers[1] = outputBuffers[activeOutputs] + blockFrames;
+ }
+ else
+ {
+ info->buffers[0] = info->buffers[1] = 0;
+ notEnoughMem = true;
+ }
+ activeOutputs++;
+ if (activeOutputs > kNumOutputs)
+ {
+ activeOutputs--;
+ disposeBuffers();
+ return ASE_InvalidParameter;
+ }
+ }
+ }
+ if (notEnoughMem)
+ {
+ disposeBuffers();
+ return ASE_NoMemory;
+ }
+
+ this->callbacks = callbacks;
+ if (callbacks->asioMessage (kAsioSupportsTimeInfo, 0, 0, 0))
+ {
+ timeInfoMode = true;
+ asioTime.timeInfo.speed = 1.;
+ asioTime.timeInfo.systemTime.hi = asioTime.timeInfo.systemTime.lo = 0;
+ asioTime.timeInfo.samplePosition.hi = asioTime.timeInfo.samplePosition.lo = 0;
+ asioTime.timeInfo.sampleRate = sampleRate;
+ asioTime.timeInfo.flags = kSystemTimeValid | kSamplePositionValid | kSampleRateValid;
+
+ asioTime.timeCode.speed = 1.;
+ asioTime.timeCode.timeCodeSamples.lo = asioTime.timeCode.timeCodeSamples.hi = 0;
+ asioTime.timeCode.flags = kTcValid | kTcRunning ;
+ }
+ else
+ timeInfoMode = false;
+ return ASE_OK;
+}
+
+//---------------------------------------------------------------------------------------------
+ASIOError AsioSample::disposeBuffers()
+{
+ long i;
+
+ callbacks = 0;
+ stop();
+ for (i = 0; i < activeInputs; i++)
+ delete inputBuffers[i];
+ activeInputs = 0;
+ for (i = 0; i < activeOutputs; i++)
+ delete outputBuffers[i];
+ activeOutputs = 0;
+ return ASE_OK;
+}
+
+//---------------------------------------------------------------------------------------------
+ASIOError AsioSample::controlPanel()
+{
+ return ASE_NotPresent;
+}
+
+//---------------------------------------------------------------------------------------------
+ASIOError AsioSample::future (long selector, void* opt) // !!! check properties
+{
+ ASIOTransportParameters* tp = (ASIOTransportParameters*)opt;
+ switch (selector)
+ {
+ case kAsioEnableTimeCodeRead: tcRead = true; return ASE_SUCCESS;
+ case kAsioDisableTimeCodeRead: tcRead = false; return ASE_SUCCESS;
+ case kAsioSetInputMonitor: return ASE_SUCCESS; // for testing!!!
+ case kAsioCanInputMonitor: return ASE_SUCCESS; // for testing!!!
+ case kAsioCanTimeInfo: return ASE_SUCCESS;
+ case kAsioCanTimeCode: return ASE_SUCCESS;
+ }
+ return ASE_NotPresent;
+}
+
+//--------------------------------------------------------------------------------------------------------
+// private methods
+//--------------------------------------------------------------------------------------------------------
+
+//--------------------------------------------------------------------------------------------------------
+// input
+//--------------------------------------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------------------------
+bool AsioSample::inputOpen ()
+{
+#if TESTWAVES
+ sineWave = new short[blockFrames];
+ if (!sineWave)
+ {
+ strcpy (errorMessage, "ASIO Sample Driver: Out of Memory!");
+ return false;
+ }
+ makeSine (sineWave);
+
+ sawTooth = new short[blockFrames];
+ if (!sawTooth)
+ {
+ strcpy(errorMessage, "ASIO Sample Driver: Out of Memory!");
+ return false;
+ }
+ makeSaw(sawTooth);
+#endif
+ return true;
+}
+
+#if TESTWAVES
+
+#include <math.h>
+
+const double pi = 0.3141592654;
+
+//---------------------------------------------------------------------------------------------
+void AsioSample::makeSine (short *wave)
+{
+ double frames = (double)blockFrames;
+ double i, f = (pi * 2.) / frames;
+
+ for (i = 0; i < frames; i++)
+ *wave++ = (short)((double)0x7fff * sin(f * i));
+}
+
+//---------------------------------------------------------------------------------------------
+void AsioSample::makeSaw(short *wave)
+{
+ double frames = (double)blockFrames;
+ double i, f = 2. / frames;
+
+ for (i = 0; i < frames; i++)
+ *wave++ = (short)((double)0x7fff * (-1. + f * i));
+}
+#endif
+
+//---------------------------------------------------------------------------------------------
+void AsioSample::inputClose ()
+{
+#if TESTWAVES
+ if (sineWave)
+ delete sineWave;
+ sineWave = 0;
+ if (sawTooth)
+ delete sawTooth;
+ sawTooth = 0;
+#endif
+}
+
+//---------------------------------------------------------------------------------------------
+void AsioSample::input()
+{
+#if TESTWAVES
+ long i;
+ short *in = 0;
+
+ for (i = 0; i < activeInputs; i++)
+ {
+ in = inputBuffers[i];
+ if (in)
+ {
+ if (toggle)
+ in += blockFrames;
+ if ((i & 1) && sawTooth)
+ memcpy(in, sawTooth, (unsigned long)(blockFrames * 2));
+ else if (sineWave)
+ memcpy(in, sineWave, (unsigned long)(blockFrames * 2));
+ }
+ }
+#endif
+}
+
+//------------------------------------------------------------------------------------------------------------------
+// output
+//------------------------------------------------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------------------------
+bool AsioSample::outputOpen()
+{
+ return true;
+}
+
+//---------------------------------------------------------------------------------------------
+void AsioSample::outputClose ()
+{
+}
+
+//---------------------------------------------------------------------------------------------
+void AsioSample::output ()
+{
+}
+
+//---------------------------------------------------------------------------------------------
+void AsioSample::bufferSwitch ()
+{
+ if (started && callbacks)
+ {
+ getNanoSeconds(&theSystemTime); // latch system time
+ input();
+ output();
+ samplePosition += blockFrames;
+ if (timeInfoMode)
+ bufferSwitchX ();
+ else
+ callbacks->bufferSwitch (toggle, ASIOFalse);
+ toggle = toggle ? 0 : 1;
+ }
+}
+
+//---------------------------------------------------------------------------------------------
+// asio2 buffer switch
+void AsioSample::bufferSwitchX ()
+{
+ getSamplePosition (&asioTime.timeInfo.samplePosition, &asioTime.timeInfo.systemTime);
+ long offset = toggle ? blockFrames : 0;
+ if (tcRead)
+ { // Create a fake time code, which is 10 minutes ahead of the card's sample position
+ // Please note that for simplicity here time code will wrap after 32 bit are reached
+ asioTime.timeCode.timeCodeSamples.lo = asioTime.timeInfo.samplePosition.lo + 600.0 * sampleRate;
+ asioTime.timeCode.timeCodeSamples.hi = 0;
+ }
+ callbacks->bufferSwitchTimeInfo (&asioTime, toggle, ASIOFalse);
+ asioTime.timeInfo.flags &= ~(kSampleRateChanged | kClockSourceChanged);
+}
+
+//---------------------------------------------------------------------------------------------
+ASIOError AsioSample::outputReady ()
+{
+ return ASE_NotPresent;
+}
+
+//---------------------------------------------------------------------------------------------
+double AsioSamples2double (ASIOSamples* samples)
+{
+ double a = (double)(samples->lo);
+ if (samples->hi)
+ a += (double)(samples->hi) * twoRaisedTo32;
+ return a;
+}
+
--- /dev/null
+/*
+ Steinberg Audio Stream I/O API
+ (c) 1999, Steinberg Soft- und Hardware GmbH
+
+ asiosmpl.h
+
+ test implementation of asio
+*/
+
+#ifndef _asiosmpl_
+#define _asiosmpl_
+
+#include "asiosys.h"
+
+#define TESTWAVES 1
+// when true, will feed the left input (to host) with
+// a sine wave, and the right one with a sawtooth
+
+enum
+{
+ kBlockFrames = 256,
+ kNumInputs = 16,
+ kNumOutputs = 16
+};
+
+#if WINDOWS
+
+#include "rpc.h"
+#include "rpcndr.h"
+#ifndef COM_NO_WINDOWS_H
+#include <windows.h>
+#include "ole2.h"
+#endif
+
+#include "combase.h"
+#include "iasiodrv.h"
+
+class AsioSample : public IASIO, public CUnknown
+{
+public:
+ AsioSample(LPUNKNOWN pUnk, HRESULT *phr);
+ ~AsioSample();
+
+ DECLARE_IUNKNOWN
+ //STDMETHODIMP QueryInterface(REFIID riid, void **ppv) { \
+ // return GetOwner()->QueryInterface(riid,ppv); \
+ //}; \
+ //STDMETHODIMP_(ULONG) AddRef() { \
+ // return GetOwner()->AddRef(); \
+ //}; \
+ //STDMETHODIMP_(ULONG) Release() { \
+ // return GetOwner()->Release(); \
+ //};
+
+ // Factory method
+ static CUnknown *CreateInstance(LPUNKNOWN pUnk, HRESULT *phr);
+ // IUnknown
+ virtual HRESULT STDMETHODCALLTYPE NonDelegatingQueryInterface(REFIID riid,void **ppvObject);
+#else
+
+#include "asiodrvr.h"
+
+//---------------------------------------------------------------------------------------------
+class AsioSample : public AsioDriver
+{
+public:
+ AsioSample ();
+ ~AsioSample ();
+#endif
+
+ ASIOBool init (void* sysRef);
+ void getDriverName (char *name); // max 32 bytes incl. terminating zero
+ long getDriverVersion ();
+ void getErrorMessage (char *string); // max 128 bytes incl.
+
+ ASIOError start ();
+ ASIOError stop ();
+
+ ASIOError getChannels (long *numInputChannels, long *numOutputChannels);
+ ASIOError getLatencies (long *inputLatency, long *outputLatency);
+ ASIOError getBufferSize (long *minSize, long *maxSize,
+ long *preferredSize, long *granularity);
+
+ ASIOError canSampleRate (ASIOSampleRate sampleRate);
+ ASIOError getSampleRate (ASIOSampleRate *sampleRate);
+ ASIOError setSampleRate (ASIOSampleRate sampleRate);
+ ASIOError getClockSources (ASIOClockSource *clocks, long *numSources);
+ ASIOError setClockSource (long index);
+
+ ASIOError getSamplePosition (ASIOSamples *sPos, ASIOTimeStamp *tStamp);
+ ASIOError getChannelInfo (ASIOChannelInfo *info);
+
+ ASIOError createBuffers (ASIOBufferInfo *bufferInfos, long numChannels,
+ long bufferSize, ASIOCallbacks *callbacks);
+ ASIOError disposeBuffers ();
+
+ ASIOError controlPanel ();
+ ASIOError future (long selector, void *opt);
+ ASIOError outputReady ();
+
+ void bufferSwitch ();
+ long getMilliSeconds () {return milliSeconds;}
+
+private:
+friend void myTimer();
+
+ bool inputOpen ();
+#if TESTWAVES
+ void makeSine (short *wave);
+ void makeSaw (short *wave);
+#endif
+ void inputClose ();
+ void input ();
+
+ bool outputOpen ();
+ void outputClose ();
+ void output ();
+
+ void timerOn ();
+ void timerOff ();
+ void bufferSwitchX ();
+
+ double samplePosition;
+ double sampleRate;
+ ASIOCallbacks *callbacks;
+ ASIOTime asioTime;
+ ASIOTimeStamp theSystemTime;
+ short *inputBuffers[kNumInputs * 2];
+ short *outputBuffers[kNumOutputs * 2];
+#if TESTWAVES
+ short *sineWave, *sawTooth;
+#endif
+ long inMap[kNumInputs];
+ long outMap[kNumOutputs];
+ long blockFrames;
+ long inputLatency;
+ long outputLatency;
+ long activeInputs;
+ long activeOutputs;
+ long toggle;
+ long milliSeconds;
+ bool active, started;
+ bool timeInfoMode, tcRead;
+ char errorMessage[128];
+};
+
+#endif
+
--- /dev/null
+#include "asio.h"
+#include <Timer.h>
+
+void getNanoSeconds(ASIOTimeStamp *time);
+
+static const double twoRaisedTo32 = 4294967296.;
+
+void getNanoSeconds(ASIOTimeStamp *time)
+{
+ UnsignedWide ys;
+ Microseconds(&ys);
+ double r = 1000. * ((double)ys.hi * twoRaisedTo32 + (double)ys.lo);
+ time->hi = (unsigned long)(r / twoRaisedTo32);
+ time->lo = (unsigned long)(r - (double)time->hi * twoRaisedTo32);
+}
--- /dev/null
+/*
+ Steinberg Audio Stream I/O API
+ (c) 1996, Steinberg Soft- und Hardware GmbH
+ charlie (May 1996)
+
+ asiosmpl.cpp
+
+ sample implementation of asio.
+ time manager irq
+ **** mac os specific ****
+*/
+
+#include <macheaders.h>
+#include <Timer.h>
+#include <string.h>
+#include "asiosmpl.h"
+
+static TMTask myTmTask;
+static bool tmTaskOn = false;
+static AsioSample *theSound = 0;
+
+void myTimer();
+void myTimer()
+{
+ if(theSound)
+ theSound->bufferSwitch();
+ PrimeTime((QElemPtr)&myTmTask, theSound->milliSeconds);
+}
+
+void AsioSample::timerOn()
+{
+ theSound = this; // for irq
+ if(!tmTaskOn)
+ {
+ memset(&myTmTask, 0, sizeof(TMTask));
+ myTmTask.tmAddr = NewTimerProc(myTimer);
+ myTmTask.tmWakeUp = 0;
+ tmTaskOn = true;
+ InsXTime((QElemPtr)&myTmTask);
+ PrimeTime((QElemPtr)&myTmTask, theSound->milliSeconds);
+ }
+}
+
+void AsioSample::timerOff()
+{
+ if(tmTaskOn)
+ {
+ RmvTime((QElemPtr)&myTmTask);
+ tmTaskOn = false;
+ }
+ theSound = 0;
+}
--- /dev/null
+#include "asiosmpl.h"
+
+AsioDriver *getDriver()
+{
+ return new AsioSample();
+}
--- /dev/null
+#include <windows.h>
+#include "asiosmpl.h"
+
+static DWORD __stdcall ASIOThread (void *param);
+static HANDLE ASIOThreadHandle = 0;
+static bool done = false;
+const double twoRaisedTo32 = 4294967296.;
+
+AsioSample* theDriver = 0;
+
+//------------------------------------------------------------------------------------------
+void getNanoSeconds (ASIOTimeStamp* ts)
+{
+ double nanoSeconds = (double)((unsigned long)timeGetTime ()) * 1000000.;
+ ts->hi = (unsigned long)(nanoSeconds / twoRaisedTo32);
+ ts->lo = (unsigned long)(nanoSeconds - (ts->hi * twoRaisedTo32));
+}
+
+//------------------------------------------------------------------------------------------
+void AsioSample::timerOn ()
+{
+ theDriver = this;
+ DWORD asioId;
+ done = false;
+ ASIOThreadHandle = CreateThread (0, 0, &ASIOThread, 0, 0, &asioId);
+}
+
+//------------------------------------------------------------------------------------------
+void AsioSample::timerOff ()
+{
+ done = true;
+ if (ASIOThreadHandle)
+ WaitForSingleObject(ASIOThreadHandle, 1000);
+ ASIOThreadHandle = 0;
+}
+
+//------------------------------------------------------------------------------------------
+static DWORD __stdcall ASIOThread (void *param)
+{
+ do
+ {
+ if (theDriver)
+ {
+ theDriver->bufferSwitch ();
+ Sleep (theDriver->getMilliSeconds ());
+ }
+ else
+ {
+ double a = 1000. / 44100.;
+ Sleep ((long)(a * (double)kBlockFrames));
+
+ }
+ } while (!done);
+ return 0;
+}
--- /dev/null
+#include "ginclude.h"
+#include "ASIOConvertSamples.h"
+#include <math.h>
+
+#if MAC
+#define TRUNCATE 0
+
+#elif ASIO_CPU_X86 || ASIO_CPU_SPARC || ASIO_CPU_MIPS
+#define TRUNCATE 1
+#undef MAXFLOAT
+#define MAXFLOAT 0x7fffff00L
+#endif
+
+ASIOConvertSamples::ASIOConvertSamples()
+{
+}
+
+
+//-------------------------------------------------------------------------------------------
+// mono
+
+void ASIOConvertSamples::convertMono8Unsigned(long *source, char *dest, long frames)
+{
+ unsigned char *c = (unsigned char *)source;
+ unsigned char a;
+
+ dest--;
+ while(--frames >= 0)
+ {
+#if ASIO_LITTLE_ENDIAN
+ a = c[3];
+#else
+ a = c[0];
+#endif
+ c += 4;
+ a -= 0x80U;
+ *++dest = a;
+ }
+}
+
+void ASIOConvertSamples::convertMono8(long *source, char *dest, long frames)
+{
+ char *c = (char *)source;
+ char a;
+
+ dest--;
+ while(--frames >= 0)
+ {
+#if ASIO_LITTLE_ENDIAN
+ a = c[3];
+#else
+ a = c[0];
+#endif
+ c += 4;
+ *++dest = a;
+ }
+}
+
+void ASIOConvertSamples::convertMono16(long *source, short *dest, long frames)
+{
+#if ASIO_LITTLE_ENDIAN
+ char* s = (char*)source;
+ char* d = (char*)dest;
+ while(--frames >= 0)
+ {
+ *d++ = s[3]; // dest big endian, msb first
+ *d++ = s[2];
+ s += 4;
+ }
+#else
+ long l;
+
+ source--;
+ dest--;
+ while(--frames >= 0)
+ {
+ l = *++source;
+ *++dest = (short)(l >> 16);
+ }
+#endif
+}
+
+void ASIOConvertSamples::convertMono24(long *source, char *dest, long frames)
+{
+ // work with chars in order to prevent misalignments
+ char *s = (char *)source;
+ char a, b, c;
+
+ dest--;
+ while(--frames >= 0)
+ {
+#if ASIO_LITTLE_ENDIAN
+ a = s[3]; // msb
+ b = s[2];
+ c = s[1]; // lsb
+#else
+ a = s[0];
+ b = s[1];
+ c = s[2];
+#endif
+ s += 4;
+ *++dest = a; // big endian, msb first
+ *++dest = b;
+ *++dest = c;
+ }
+}
+
+// small endian
+
+void ASIOConvertSamples::convertMono16SmallEndian(long *source, short *dest, long frames)
+{
+ char *s = (char *)source;
+ char *d = (char *)dest;
+ char a, b;
+
+ d--;
+ while(--frames >= 0)
+ {
+#if ASIO_LITTLE_ENDIAN
+ a = s[3];
+ b = s[2];
+#else
+ a = s[0];
+ b = s[1];
+#endif
+ s += 4;
+ *++d = b; // dest small endian, lsb first
+ *++d = a;
+ }
+}
+
+void ASIOConvertSamples::convertMono24SmallEndian(long *source, char *dest, long frames)
+{
+ // work with chars in order to prevent misalignments
+ char *s = (char *)source;
+ char a, b, c;
+
+ dest--;
+ while(--frames >= 0)
+ {
+#if ASIO_LITTLE_ENDIAN
+ a = s[3];
+ b = s[2];
+ c = s[1];
+#else
+ a = s[0];
+ b = s[1];
+ c = s[2];
+#endif
+ s += 4;
+ *++dest = c; // lsb first
+ *++dest = b;
+ *++dest = a;
+ }
+}
+
+
+//-------------------------------------------------------------------------------------------
+// stereo interleaved
+
+void ASIOConvertSamples::convertStereo8InterleavedUnsigned(long *left, long *right, char *dest, long frames)
+{
+ unsigned char *cl = (unsigned char *)left;
+ unsigned char *cr = (unsigned char *)right;
+ unsigned char a, b;
+
+ dest--;
+ while(--frames >= 0)
+ {
+#if ASIO_LITTLE_ENDIAN
+ a = cl[3];
+ b = cr[3];
+#else
+ a = cl[0];
+ b = cr[0];
+#endif
+ cl += 4;
+ cr += 4;
+ a -= 0x80U;
+ b -= 0x80U;
+ *++dest = a;
+ *++dest = b;
+ }
+}
+
+void ASIOConvertSamples::convertStereo8Interleaved(long *left, long *right, char *dest, long frames)
+{
+ unsigned char *cl = (unsigned char *)left;
+ unsigned char *cr = (unsigned char *)right;
+ unsigned char a, b;
+
+ dest--;
+ while(--frames >= 0)
+ {
+#if ASIO_LITTLE_ENDIAN
+ a = cl[3];
+ b = cr[3];
+#else
+ a = cl[0];
+ b = cr[0];
+#endif
+ cl += 4;
+ cr += 4;
+ *++dest = a;
+ *++dest = b;
+ }
+}
+
+void ASIOConvertSamples::convertStereo16Interleaved(long *left, long *right, short *dest, long frames)
+{
+#if ASIO_LITTLE_ENDIAN
+ char* sl = (char*)left;
+ char* sr = (char*)right;
+ char* d = (char*)dest;
+ while(--frames >= 0)
+ {
+ *d++ = sl[3]; // msb first
+ *d++ = sl[2];
+ *d++ = sr[3];
+ *d++ = sr[2];
+ sl += 4;
+ sr += 4;
+ }
+#else
+ long l, r;
+
+ left--;
+ right--;
+ dest--;
+ while(--frames >= 0)
+ {
+ l = *++left;
+ r = *++right;
+ *++dest = (short)(l >> 16);
+ *++dest = (short)(r >> 16);
+ }
+#endif
+}
+
+void ASIOConvertSamples::convertStereo24Interleaved(long *left, long *right, char *dest, long frames)
+{
+ // work with chars in order to prevent misalignments
+ char *sl = (char *)left;
+ char *sr = (char *)right;
+ char al, bl, cl, ar, br, cr;
+
+ dest--;
+ while(--frames >= 0)
+ {
+#if ASIO_LITTLE_ENDIAN
+ al = sl[3];
+ bl = sl[2];
+ cl = sl[1];
+ ar = sr[3];
+ br = sr[2];
+ cr = sr[1];
+#else
+ al = sl[0];
+ bl = sl[1];
+ cl = sl[2];
+ ar = sr[0];
+ br = sr[1];
+ cr = sr[2];
+#endif
+ sl += 4;
+ sr += 4;
+ *++dest = al;
+ *++dest = bl;
+ *++dest = cl;
+ *++dest = ar;
+ *++dest = br;
+ *++dest = cr;
+ }
+}
+
+void ASIOConvertSamples::convertStereo16InterleavedSmallEndian(long *left, long *right, short *dest, long frames)
+{
+ char *sl = (char *)left;
+ char *sr = (char *)right;
+ char *d = (char *)dest;
+ char al, bl, ar, br;
+
+ d--;
+ while(--frames >= 0)
+ {
+#if ASIO_LITTLE_ENDIAN
+ al = sl[3];
+ bl = sl[2];
+ ar = sr[3];
+ br = sr[2];
+#else
+ al = sl[0];
+ bl = sl[1];
+ ar = sr[0];
+ br = sr[1];
+#endif
+ sl += 4;
+ sr += 4;
+ *++d = bl; // lsb first
+ *++d = al;
+ *++d = br;
+ *++d = ar;
+ }
+}
+
+void ASIOConvertSamples::convertStereo24InterleavedSmallEndian(long *left, long *right, char *dest, long frames)
+{
+ // work with chars in order to prevent misalignments
+ char *sl = (char *)left;
+ char *sr = (char *)right;
+ char al, bl, cl, ar, br, cr;
+
+ dest--;
+ while(--frames >= 0)
+ {
+#if ASIO_LITTLE_ENDIAN
+ al = sl[3];
+ bl = sl[2];
+ cl = sl[1];
+ ar = sr[3];
+ br = sr[2];
+ cr = sr[1];
+#else
+ al = sl[0];
+ bl = sl[1];
+ cl = sl[2];
+ ar = sr[0];
+ br = sr[1];
+ cr = sr[2];
+#endif
+ sl += 4;
+ sr += 4;
+ *++dest = cl;
+ *++dest = bl;
+ *++dest = al;
+ *++dest = cr;
+ *++dest = br;
+ *++dest = ar;
+ }
+}
+
+
+//-------------------------------------------------------------------------------------------
+// stereo split
+
+void ASIOConvertSamples::convertStereo8Unsigned(long *left, long *right, char *dLeft, char *dRight, long frames)
+{
+ unsigned char *cl = (unsigned char *)left;
+ unsigned char *cr = (unsigned char *)right;
+ unsigned char a, b;
+
+ dLeft--;
+ dRight--;
+ while(--frames >= 0)
+ {
+#if ASIO_LITTLE_ENDIAN
+ a = cl[3];
+ b = cr[3];
+#else
+ a = cl[0];
+ b = cr[0];
+#endif
+ cl += 4;
+ cr += 4;
+ a -= 0x80U;
+ b -= 0x80U;
+ *++dLeft = a;
+ *++dRight = b;
+ }
+}
+
+void ASIOConvertSamples::convertStereo8(long *left, long *right, char *dLeft, char *dRight, long frames)
+{
+ unsigned char *cl = (unsigned char *)left;
+ unsigned char *cr = (unsigned char *)right;
+ unsigned char a, b;
+
+ dLeft--;
+ dRight--;
+ while(--frames >= 0)
+ {
+#if ASIO_LITTLE_ENDIAN
+ a = cl[3];
+ b = cr[3];
+#else
+ a = cl[0];
+ b = cr[0];
+#endif
+ cl += 4;
+ cr += 4;
+ *++dLeft = a;
+ *++dRight = b;
+ }
+}
+
+void ASIOConvertSamples::convertStereo16(long *left, long *right, short *dLeft, short *dRight, long frames)
+{
+#if ASIO_LITTLE_ENDIAN
+ char* sl = (char*)left;
+ char* sr = (char*)right;
+ char* dl = (char*)dLeft;
+ char* dr = (char*)dRight;
+ while(--frames >= 0)
+ {
+ *dl++ = sl[3]; // msb first
+ *dl++ = sl[2];
+ *dr++ = sr[3];
+ *dr++ = sr[2];
+ sl += 4;
+ sr += 4;
+ }
+#else
+ long l, r;
+
+ left--;
+ right--;
+ dLeft--;
+ dRight--;
+ while(--frames >= 0)
+ {
+ l = *++left;
+ r = *++right;
+ *++dLeft = (short)(l >> 16);
+ *++dRight = (short)(r >> 16);
+ }
+#endif
+}
+
+void ASIOConvertSamples::convertStereo24(long *left, long *right, char *dLeft, char *dRight, long frames)
+{
+ // work with chars in order to prevent misalignments
+ char *sl = (char *)left;
+ char *sr = (char *)right;
+ char al, bl, cl, ar, br, cr;
+
+ dLeft--;
+ dRight--;
+ while(--frames >= 0)
+ {
+#if ASIO_LITTLE_ENDIAN
+ al = sl[3];
+ bl = sl[2];
+ cl = sl[1];
+ ar = sr[3];
+ br = sr[2];
+ cr = sr[1];
+#else
+ al = sl[0];
+ bl = sl[1];
+ cl = sl[2];
+ ar = sr[0];
+ br = sr[1];
+ cr = sr[2];
+#endif
+ sl += 4;
+ sr += 4;
+ *++dLeft = al;
+ *++dLeft = bl;
+ *++dLeft = cl;
+ *++dRight = ar;
+ *++dRight = br;
+ *++dRight = cr;
+ }
+}
+
+// small endian
+void ASIOConvertSamples::convertStereo16SmallEndian(long *left, long *right, short *dLeft, short *dRight, long frames)
+{
+ char *sl = (char *)left;
+ char *sr = (char *)right;
+ char *dl = (char *)dLeft;
+ char *dr = (char *)dRight;
+ char al, bl, ar, br;
+
+ dl--;
+ dr--;
+ while(--frames >= 0)
+ {
+#if ASIO_LITTLE_ENDIAN
+ al = sl[3];
+ bl = sl[2];
+ ar = sr[3];
+ br = sr[2];
+#else
+ al = sl[0];
+ bl = sl[1];
+ ar = sr[0];
+ br = sr[1];
+#endif
+ sl += 4;
+ sr += 4;
+ *++dl = bl;
+ *++dl = al;
+ *++dr = br;
+ *++dr = ar;
+ }
+}
+
+void ASIOConvertSamples::convertStereo24SmallEndian(long *left, long *right, char *dLeft, char *dRight, long frames)
+{
+ // work with chars in order to prevent misalignments
+ char *sl = (char *)left;
+ char *sr = (char *)right;
+ char al, bl, cl, ar, br, cr;
+
+ dLeft--;
+ dRight--;
+ while(--frames >= 0)
+ {
+#if ASIO_LITTLE_ENDIAN
+ al = sl[3];
+ bl = sl[2];
+ cl = sl[1];
+ ar = sr[3];
+ br = sr[2];
+ cr = sr[1];
+#else
+ al = sl[0];
+ bl = sl[1];
+ cl = sl[2];
+ ar = sr[0];
+ br = sr[1];
+ cr = sr[2];
+#endif
+ sl += 4;
+ sr += 4;
+ *++dLeft = cl;
+ *++dLeft = bl;
+ *++dLeft = al;
+ *++dRight = cr;
+ *++dRight = br;
+ *++dRight = ar;
+ }
+}
+
+//------------------------------------------------------------------------------------------
+// in place integer conversions
+
+void ASIOConvertSamples::int32msb16to16inPlace(long *in, long frames)
+{
+ short *d1 = (short *)in;
+ short* out = d1;
+#if ASIO_LITTLE_ENDIAN
+ d1++;
+#endif
+ while(--frames >= 0)
+ {
+ *out++ = *d1;
+ d1 += 2;
+ }
+}
+
+void ASIOConvertSamples::int32lsb16to16inPlace(long *in, long frames)
+{
+ short *d1 = (short *)in;
+ short* out = d1;
+#if !ASIO_LITTLE_ENDIAN
+ d1++;
+#endif
+ while(--frames >= 0)
+ {
+ *out++ = *d1;
+ d1 += 2;
+ }
+}
+
+void ASIOConvertSamples::int32msb16shiftedTo16inPlace(long *in, long frames, long shift)
+{
+ short* out = (short*)in;
+ while(--frames >= 0)
+ *out++ = (short)(*in++ >> shift);
+}
+
+void ASIOConvertSamples::int24msbto16inPlace(unsigned char *in, long frames)
+{
+ short a;
+ short* out = (short*)in;
+ while(--frames >= 0)
+ {
+#if ASIO_LITTLE_ENDIAN
+ a = (short)in[2];
+ a <<= 8;
+ a |= (in[1] & 0xff);
+#else
+ a = (short)in[0];
+ a <<= 8;
+ a |= (in[1] & 0xff);
+#endif
+ *out++ = a;
+ in += 3;
+ }
+}
+
+//-----------------------------------------------------------------------------------------
+
+void ASIOConvertSamples::shift32(void* buffer, long shiftAmount, long targetByteWidth,
+ bool revertEndian, long sampleFrames)
+{
+ long a;
+ long frames = sampleFrames;
+ long* source = (long*)buffer;
+ if(revertEndian)
+ {
+ reverseEndian(buffer, 4, sampleFrames);
+ revertEndian = false;
+ }
+
+ if(targetByteWidth == 2)
+ {
+ short* dest = (short*)buffer;
+ short* al = (short*)&a;
+#if ASIO_LITTLE_ENDIAN
+ al++;
+#endif
+ while(--frames >= 0)
+ {
+ a = *source++;
+ a <<= shiftAmount;
+ *dest++ = *al;
+ }
+ }
+
+ else if(targetByteWidth == 3)
+ {
+ char* dest = (char*)buffer;
+ long* source = (long*)buffer;
+ char* aa = (char*)&a;
+ while(--frames >= 0)
+ {
+ a = *source++;
+ a <<= shiftAmount;
+#if ASIO_LITTLE_ENDIAN
+ dest[0] = aa[1]; // lsb
+ dest[1] = aa[2];
+ dest[2] = aa[3]; // msb
+#else
+ dest[0] = aa[0]; // msb
+ dest[1] = aa[1];
+ dest[2] = aa[2]; // lsb
+#endif
+ dest += 3;
+ }
+ }
+
+ else if(targetByteWidth == 4)
+ {
+ long* dest = source;
+ while(--frames >= 0)
+ *dest++ = *source++ << shiftAmount;
+ }
+}
+
+void ASIOConvertSamples::reverseEndian(void* buffer, long byteWidth, long frames)
+{
+ char* a = (char*)buffer;
+ char* b = a;
+ char c;
+ if(byteWidth == 2)
+ {
+ while(--frames >= 0)
+ {
+ c = a[0];
+ a[0] = a[1];
+ a[1] = c;
+ a += 2;
+ }
+ }
+ else if(byteWidth == 3)
+ {
+ while(--frames >= 0)
+ {
+ c = a[0];
+ a[0] = a[2];
+ a[2] = c;
+ a += 3;
+ }
+ }
+ else if(byteWidth == 4)
+ {
+ while(--frames >= 0)
+ {
+ c = a[0];
+ a[0] = a[3];
+ a[3] = c;
+ c = a[1];
+ a[1] = a[2];
+ a[2] = c;
+ a += 4;
+ }
+ }
+}
+
+//-------------------------------------------------------------------------------------------------
+
+void ASIOConvertSamples::int32to16inPlace(void* buffer, long frames)
+{
+ short* in = (short*)buffer;
+ short* out = in;
+#if ASIO_LITTLE_ENDIAN
+ in++;
+#endif
+ while(--frames >= 0)
+ {
+ *out++ = *in;
+ in += 2;
+ }
+}
+
+void ASIOConvertSamples::int24to16inPlace(void* buffer, long frames)
+{
+ char* from = (char*)buffer;
+ char* to = from;
+ while(--frames >= 0)
+ {
+#if ASIO_LITTLE_ENDIAN
+ to[0] = from[1];
+ to[1] = from[2];
+#else
+ to[0] = from[0];
+ to[1] = from[1];
+#endif
+ from += 3;
+ to += 2;
+ }
+}
+
+void ASIOConvertSamples::int32to24inPlace(void* buffer, long frames)
+{
+ long* in = (long*)buffer;
+ char* out = (char*)buffer;
+ long a;
+ while(--frames >= 0)
+ {
+ a = *in++;
+ a >>= 8; // 32->24
+#if ASIO_LITTLE_ENDIAN
+ out[0] = (char)a; // lsb
+ a >>= 8;
+ out[1] = (char)a;
+ a >>= 8;
+ out[2] = (char)a;
+#else
+ out[2] = (char)a; // lsb
+ a >>= 8;
+ out[1] = (char)a;
+ a >>= 8;
+ out[0] = (char)a;
+#endif
+ out += 3;
+ }
+}
+
+void ASIOConvertSamples::int16to24inPlace(void* buffer, long frames)
+{
+ char* in = (char*)buffer;
+ char* out = (char*)buffer;
+ in += frames * 2;
+ out += frames * 3;
+ while(--frames >= 0)
+ {
+ out -= 3;
+ in -= 2;
+#if ASIO_LITTLE_ENDIAN
+ out[2] = in[1]; // msb
+ out[1] = in[0]; // lsb
+ out[0] = 0;
+#else
+ out[2] = 0;
+ out[1] = in[1]; // lsb
+ out[0] = in[0]; // msb
+#endif
+ }
+}
+
+void ASIOConvertSamples::int24to32inPlace(void* buffer, long frames)
+{
+ long a, b, c;
+ char* in = (char*)buffer;
+ long* out = (long*)buffer;
+ in += (frames * 3);
+ out += frames;
+ while(--frames >= 0)
+ {
+#if ASIO_LITTLE_ENDIAN
+ a = (long)in[-1]; // msb
+ b = (long)in[-2];
+ c = (long)in[-3];
+#else
+ a = (long)in[-3]; // msb
+ b = (long)in[-2];
+ c = (long)in[-1];
+#endif
+ a <<= 24;
+ b <<= 16;
+ b &= 0x00ff0000;
+ a |= b;
+ c <<= 8;
+ c &= 0x0000ff00;
+ a |= c;
+ *--out = a;
+ in -= 3;
+ }
+}
+
+void ASIOConvertSamples::int16to32inPlace(void* buffer, long frames)
+{
+ short* in = (short*)buffer;
+ long* out = (long*)buffer;
+ in += frames;
+ out += frames;
+ while(--frames >= 0)
+ *--out = ((long)(*--in)) << 16;
+}
+
+//------------------------------------------------------------------------------------------
+// float to int
+
+const double fScaler16 = (double)0x7fffL;
+const double fScaler24 = (double)0x7fffffL;
+const double fScaler32 = (double)0x7fffffffL;
+
+void ASIOConvertSamples::float32toInt16inPlace(float* buffer, long frames)
+{
+ double sc = fScaler16 + .49999;
+ short* b = (short*)buffer;
+ while(--frames >= 0)
+ *b++ = (short)((double)(*buffer++) * sc);
+}
+
+void ASIOConvertSamples::float32toInt24inPlace(float* buffer, long frames)
+{
+ double sc = fScaler24 + .49999;
+ long a;
+ char* b = (char*)buffer;
+ char* aa = (char*)&a;
+
+ while(--frames >= 0)
+ {
+ a = (long)((double)(*buffer++) * sc);
+#if ASIO_LITTLE_ENDIAN
+ *b++ = aa[3];
+ *b++ = aa[2];
+ *b++ = aa[1];
+#else
+ *b++ = aa[1];
+ *b++ = aa[2];
+ *b++ = aa[3];
+#endif
+ }
+}
+
+void ASIOConvertSamples::float32toInt32inPlace(float* buffer, long frames)
+{
+ double sc = fScaler32 + .49999;
+ long* b = (long*)buffer;
+ while(--frames >= 0)
+ *b++ = (long)((double)(*buffer++) * sc);
+}
+
--- /dev/null
+#ifndef __ASIOConvertSamples__
+#define __ASIOConvertSamples__
+
+class ASIOConvertSamples
+{
+public:
+ ASIOConvertSamples();
+ ~ASIOConvertSamples() {}
+
+ // format converters, input 32 bit integer
+ // mono
+ void convertMono8(long *source, char *dest, long frames);
+ void convertMono8Unsigned(long *source, char *dest, long frames);
+ void convertMono16(long *source, short *dest, long frames);
+ void convertMono16SmallEndian(long *source, short *dest, long frames);
+ void convertMono24(long *source, char *dest, long frames);
+ void convertMono24SmallEndian(long *source, char *dest, long frames);
+
+ // stereo interleaved
+ void convertStereo8Interleaved(long *left, long *right, char *dest, long frames);
+ void convertStereo8InterleavedUnsigned(long *left, long *right, char *dest, long frames);
+ void convertStereo16Interleaved(long *left, long *right, short *dest, long frames);
+ void convertStereo16InterleavedSmallEndian(long *left, long *right, short *dest, long frames);
+ void convertStereo24Interleaved(long *left, long *right, char *dest, long frames);
+ void convertStereo24InterleavedSmallEndian(long *left, long *right, char *dest, long frames);
+
+ // stereo split
+ void convertStereo8(long *left, long *right, char *dLeft, char *dRight, long frames);
+ void convertStereo8Unsigned(long *left, long *right, char *dLeft, char *dRight, long frames);
+ void convertStereo16(long *left, long *right, short *dLeft, short *dRight, long frames);
+ void convertStereo16SmallEndian(long *left, long *right, short *dLeft, short *dRight, long frames);
+ void convertStereo24(long *left, long *right, char *dLeft, char *dRight, long frames);
+ void convertStereo24SmallEndian(long *left, long *right, char *dLeft, char *dRight, long frames);
+
+ // integer in place conversions
+
+ void int32msb16to16inPlace(long *in, long frames);
+ void int32lsb16to16inPlace(long *in, long frames);
+ void int32msb16shiftedTo16inPlace(long *in1, long frames, long shift);
+ void int24msbto16inPlace(unsigned char *in, long frames);
+
+ // integer to integer
+
+ void shift32(void* buffer, long shiftAmount, long targetByteWidth,
+ bool reverseEndian, long frames);
+ void reverseEndian(void* buffer, long byteWidth, long frames);
+
+ void int32to16inPlace(void* buffer, long frames);
+ void int24to16inPlace(void* buffer, long frames);
+ void int32to24inPlace(void* buffer, long frames);
+ void int16to24inPlace(void* buffer, long frames);
+ void int24to32inPlace(void* buffer, long frames);
+ void int16to32inPlace(void* buffer, long frames);
+
+ // float to integer
+
+ void float32toInt16inPlace(float* buffer, long frames);
+ void float32toInt24inPlace(float* buffer, long frames);
+ void float32toInt32inPlace(float* buffer, long frames);
+};
+
+#endif
--- /dev/null
+#include <string.h>
+#include "asiodrivers.h"
+
+AsioDrivers* asioDrivers = 0;
+
+bool loadAsioDriver(char *name);
+
+bool loadAsioDriver(char *name)
+{
+ if(!asioDrivers)
+ asioDrivers = new AsioDrivers();
+ if(asioDrivers)
+ return asioDrivers->loadDriver(name);
+ return false;
+}
+
+//------------------------------------------------------------------------------------
+
+#if MAC
+
+bool resolveASIO(unsigned long aconnID);
+
+AsioDrivers::AsioDrivers() : CodeFragments("ASIO Drivers", 'AsDr', 'Asio')
+{
+ connID = -1;
+ curIndex = -1;
+}
+
+AsioDrivers::~AsioDrivers()
+{
+ removeCurrentDriver();
+}
+
+bool AsioDrivers::getCurrentDriverName(char *name)
+{
+ if(curIndex >= 0)
+ return getName(curIndex, name);
+ return false;
+}
+
+long AsioDrivers::getDriverNames(char **names, long maxDrivers)
+{
+ for(long i = 0; i < getNumFragments() && i < maxDrivers; i++)
+ getName(i, names[i]);
+ return getNumFragments() < maxDrivers ? getNumFragments() : maxDrivers;
+}
+
+bool AsioDrivers::loadDriver(char *name)
+{
+ char dname[64];
+ unsigned long newID;
+
+ for(long i = 0; i < getNumFragments(); i++)
+ {
+ if(getName(i, dname) && !strcmp(name, dname))
+ {
+ if(newInstance(i, &newID))
+ {
+ if(resolveASIO(newID))
+ {
+ if(connID != -1)
+ removeInstance(curIndex, connID);
+ curIndex = i;
+ connID = newID;
+ return true;
+ }
+ }
+ break;
+ }
+ }
+ return false;
+}
+
+void AsioDrivers::removeCurrentDriver()
+{
+ if(connID != -1)
+ removeInstance(curIndex, connID);
+ connID = -1;
+ curIndex = -1;
+}
+
+//------------------------------------------------------------------------------------
+
+#elif WINDOWS
+
+#include "iasiodrv.h"
+
+extern IASIO* theAsioDriver;
+
+AsioDrivers::AsioDrivers() : AsioDriverList()
+{
+ curIndex = -1;
+}
+
+AsioDrivers::~AsioDrivers()
+{
+}
+
+bool AsioDrivers::getCurrentDriverName(char *name)
+{
+ if(curIndex >= 0)
+ return asioGetDriverName(curIndex, name, 32) == 0 ? true : false;
+ name[0] = 0;
+ return false;
+}
+
+long AsioDrivers::getDriverNames(char **names, long maxDrivers)
+{
+ for(long i = 0; i < asioGetNumDev() && i < maxDrivers; i++)
+ asioGetDriverName(i, names[i], 32);
+ return asioGetNumDev() < maxDrivers ? asioGetNumDev() : maxDrivers;
+}
+
+bool AsioDrivers::loadDriver(char *name)
+{
+ char dname[64];
+ char curName[64];
+
+ for(long i = 0; i < asioGetNumDev(); i++)
+ {
+ if(!asioGetDriverName(i, dname, 32) && !strcmp(name, dname))
+ {
+ curName[0] = 0;
+ getCurrentDriverName(curName); // in case we fail...
+ removeCurrentDriver();
+
+ if(!asioOpenDriver(i, (void **)&theAsioDriver))
+ {
+ curIndex = i;
+ return true;
+ }
+ else
+ {
+ theAsioDriver = 0;
+ if(curName[0] && strcmp(dname, curName))
+ loadDriver(curName); // try restore
+ }
+ break;
+ }
+ }
+ return false;
+}
+
+void AsioDrivers::removeCurrentDriver()
+{
+ if(curIndex != -1)
+ asioCloseDriver(curIndex);
+ curIndex = -1;
+}
+
+#elif SGI || BEOS
+
+#include "asiolist.h"
+
+AsioDrivers::AsioDrivers()
+ : AsioDriverList()
+{
+ curIndex = -1;
+}
+
+AsioDrivers::~AsioDrivers()
+{
+}
+
+bool AsioDrivers::getCurrentDriverName(char *name)
+{
+ return false;
+}
+
+long AsioDrivers::getDriverNames(char **names, long maxDrivers)
+{
+ return 0;
+}
+
+bool AsioDrivers::loadDriver(char *name)
+{
+ return false;
+}
+
+void AsioDrivers::removeCurrentDriver()
+{
+}
+
+#else
+#error implement me
+#endif
--- /dev/null
+#ifndef __AsioDrivers__
+#define __AsioDrivers__
+
+#include "ginclude.h"
+
+#if MAC
+#include "CodeFragments.hpp"
+
+class AsioDrivers : public CodeFragments
+
+#elif WINDOWS
+#include <windows.h>
+#include "asiolist.h"
+
+class AsioDrivers : public AsioDriverList
+
+#elif SGI || BEOS
+#include "asiolist.h"
+
+class AsioDrivers : public AsioDriverList
+
+#else
+#error implement me
+#endif
+
+{
+public:
+ AsioDrivers();
+ ~AsioDrivers();
+
+ bool getCurrentDriverName(char *name);
+ long getDriverNames(char **names, long maxDrivers);
+ bool loadDriver(char *name);
+ void removeCurrentDriver();
+ long getCurrentDriverIndex() {return curIndex;}
+protected:
+ unsigned long connID;
+ long curIndex;
+};
+
+#endif
--- /dev/null
+#ifndef __gInclude__
+#define __gInclude__
+
+#if SGI
+ #undef BEOS
+ #undef MAC
+ #undef WINDOWS
+ //
+ #define ASIO_BIG_ENDIAN 1
+ #define ASIO_CPU_MIPS 1
+#elif defined(_WIN32) || defined(_WIN64)
+ #undef BEOS
+ #undef MAC
+ #undef SGI
+ #define WINDOWS 1
+ #define ASIO_LITTLE_ENDIAN 1
+ #define ASIO_CPU_X86 1
+#elif BEOS
+ #undef MAC
+ #undef SGI
+ #undef WINDOWS
+ #define ASIO_LITTLE_ENDIAN 1
+ #define ASIO_CPU_X86 1
+ //
+#else
+ #define MAC 1
+ #undef BEOS
+ #undef WINDOWS
+ #undef SGI
+ #define ASIO_BIG_ENDIAN 1
+ #define ASIO_CPU_PPC 1
+#endif
+
+// always
+#define NATIVE_INT64 0
+#define IEEE754_64FLOAT 1
+
+#endif // __gInclude__
--- /dev/null
+// asio code fragment 'linker'
+// mac specific
+// loads the symbols via the fragment manager, and
+// translates them into function pointers. this
+// means no asio lib must be linked, as the
+// 'real' asio functions are here
+
+#include "ginclude.h"
+#include <macheaders.c>
+#include <string.h>
+#include <CodeFragments.h>
+#include "asio.h"
+
+// Macro below has to 0 if external drivers will be used.
+// Can be set to 1 if a specific ASIO driver should be linked into the program
+#define ASIOINCLUDED 0
+
+
+
+// export
+bool resolveASIO(unsigned long aconnID);
+
+//------------------------------------------------------------------------------------------------------
+// private
+
+#if ASIOINCLUDED
+bool resolveASIO(unsigned long aconnID) {aconnID = aconnID; return true;}
+#else
+
+enum
+{
+ kASIOInit = 0,
+ kASIOExit,
+ kASIOStart,
+ kASIOStop,
+ kASIOGetChannels,
+ kASIOGetLatencies,
+ kASIOGetBufferSize,
+ kASIOCanSampleRate,
+ kASIOGetSampleRate,
+ kASIOSetSampleRate,
+ kASIOGetClockSources,
+ kASIOSetClockSource,
+ kASIOGetSamplePosition,
+ kASIOGetChannelInfo,
+ kASIOCreateBuffers,
+ kASIODisposeBuffers,
+ kASIOControlPanel,
+ kASIOFuture,
+
+ kASIOOutputReady,
+
+ kNumSymbols,
+ kRequiredSymbols = kNumSymbols - 1
+};
+
+static char *asioTable[kNumSymbols] =
+{
+ "ASIOInit",
+ "ASIOExit",
+ "ASIOStart",
+ "ASIOStop",
+ "ASIOGetChannels",
+ "ASIOGetLatencies",
+ "ASIOGetBufferSize",
+ "ASIOCanSampleRate",
+ "ASIOGetSampleRate",
+ "ASIOSetSampleRate",
+ "ASIOGetClockSources",
+ "ASIOSetClockSource",
+ "ASIOGetSamplePosition",
+ "ASIOGetChannelInfo",
+ "ASIOCreateBuffers",
+ "ASIODisposeBuffers",
+ "ASIOControlPanel",
+ "ASIOFuture",
+ "ASIOOutputReady"
+};
+
+typedef ASIOError (*fasioInit) (ASIODriverInfo *info);
+typedef ASIOError (*fasioExit) (void);
+typedef ASIOError (*fasioStart) (void);
+typedef ASIOError (*fasioStop) (void);
+typedef ASIOError (*asioGetChannels) (long *numInputChannels, long *numOutputChannels);
+typedef ASIOError (*asioGetLatencies) (long *inputLatency, long *outputLatency);
+typedef ASIOError (*asioGetBufferSize) (long *minSize, long *maxSize, long *preferredSize, long *granularity);
+typedef ASIOError (*asioCanSampleRate) (ASIOSampleRate sampleRate);
+typedef ASIOError (*asioGetSampleRate) (ASIOSampleRate *currentRate);
+typedef ASIOError (*asioSetSampleRate) (ASIOSampleRate sampleRate);
+typedef ASIOError (*asioGetClockSources) (ASIOClockSource *clocks, long *numSources);
+typedef ASIOError (*asioSetClockSource) (long reference);
+typedef ASIOError (*asioGetSamplePosition) (ASIOSamples *sPos, ASIOTimeStamp *tStamp);
+typedef ASIOError (*asioGetChannelInfo) (ASIOChannelInfo *info);
+typedef ASIOError (*asioCreateBuffers) (ASIOBufferInfo *channelInfos, long numChannels,
+ long bufferSize, ASIOCallbacks *callbacks);
+typedef ASIOError (*asioDisposeBuffers) (void);
+typedef ASIOError (*asioControlPanel) (void);
+typedef ASIOError (*asioFuture)(long selector, void *opt);
+typedef ASIOError (*asioOutputReady) (void);
+
+static void *functionTable[kNumSymbols] = {0};
+static bool inited = false;
+
+//---------------------------------------------------------------------------------------------------------
+
+#include <CodeFragments.h>
+
+bool resolveASIO(unsigned long aconnID)
+{
+ OSErr err;
+ CFragConnectionID connID = (CFragConnectionID)aconnID;
+ CFragSymbolClass symClass;
+ Ptr symAddr = nil;
+ Str255 myName;
+ long myCount = 0;
+
+ err = CountSymbols(connID, &myCount);
+ if(err != noErr || myCount < (kRequiredSymbols + 1)) // there must be a main()
+ return false;
+
+ long n, c = 0;
+ for(n = kRequiredSymbols; n < kNumSymbols; n++)
+ functionTable[n] = 0;
+ for(n = 0; n < myCount; n++)
+ {
+ // we can't use FindSymbol(), as the compiler adds mangling
+ // (such as ASIOInit__Fv). also, the symbols don't appear
+ // in the order they are declared or implemented.
+ // so we use strncmp()
+ err = GetIndSymbol(connID, n, myName, &symAddr, &symClass);
+ if(err != noErr)
+ break;
+ PtoCstr(myName);
+ if(!strncmp((char *)myName, "main", 4L))
+ c++;
+ else
+ {
+ for(long i = 0; i < kNumSymbols; i++)
+ {
+ long sc = strlen(asioTable[i]);
+ if(!strncmp((char *)myName, asioTable[i], sc))
+ {
+ functionTable[i] = symAddr;
+ if(i < kRequiredSymbols)
+ c++;
+ break;
+ }
+ }
+ }
+ // if(c >= kNumSymbols + 1)
+ // break;
+ }
+ if(c >= kRequiredSymbols + 1)
+ {
+ inited = true;
+ return true;
+ }
+ return false;
+}
+
+//---------------------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------------------
+
+#pragma export on
+
+static short curRes = 0;
+#define saveRes() curRes = CurResFile()
+#define restRes() UseResFile(curRes);
+
+
+ASIOError ASIOInit(ASIODriverInfo *info)
+{
+ saveRes();
+ strcpy(info->errorMessage, "No ASIO Driver could be Loaded!");
+ if(!inited)
+ return ASE_NotPresent;
+ fasioInit f = (fasioInit)functionTable[kASIOInit];
+ ASIOError e = (*f)(info);
+ restRes();
+ return e;
+}
+
+ASIOError ASIOExit(void)
+{
+ if(!inited)
+ return ASE_NotPresent;
+ saveRes();
+ fasioExit f = (fasioExit)functionTable[kASIOExit];
+ ASIOError e = (*f)();
+ restRes();
+ return e;
+}
+
+ASIOError ASIOStart(void)
+{
+ if(!inited)
+ return ASE_NotPresent;
+ fasioStart f = (fasioStart)functionTable[kASIOStart];
+ return (*f)();
+}
+
+ASIOError ASIOStop(void)
+{
+ if(!inited)
+ return ASE_NotPresent;
+ fasioStop f = (fasioStop)functionTable[kASIOStop];
+ return (*f)();
+}
+
+ASIOError ASIOGetChannels(long *numInputChannels, long *numOutputChannels)
+{
+ if(!inited)
+ return ASE_NotPresent;
+ asioGetChannels f = (asioGetChannels)functionTable[kASIOGetChannels];
+ return (*f)(numInputChannels, numOutputChannels);
+}
+
+ASIOError ASIOGetLatencies(long *inputLatency, long *outputLatency)
+{
+ if(!inited)
+ return ASE_NotPresent;
+ asioGetLatencies f = (asioGetLatencies)functionTable[kASIOGetLatencies];
+ return (*f)(inputLatency, outputLatency);
+}
+
+ASIOError ASIOGetBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity)
+{
+ if(!inited)
+ return ASE_NotPresent;
+ asioGetBufferSize f = (asioGetBufferSize)functionTable[kASIOGetBufferSize];
+ return (*f)(minSize, maxSize, preferredSize, granularity);
+}
+
+ASIOError ASIOCanSampleRate(ASIOSampleRate sampleRate)
+{
+ if(!inited)
+ return ASE_NotPresent;
+ asioCanSampleRate f = (asioCanSampleRate)functionTable[kASIOCanSampleRate];
+ return (*f)(sampleRate);
+}
+
+ASIOError ASIOGetSampleRate(ASIOSampleRate *currentRate)
+{
+ if(!inited)
+ return ASE_NotPresent;
+ asioGetSampleRate f = (asioGetSampleRate)functionTable[kASIOGetSampleRate];
+ return (*f)(currentRate);
+}
+
+ASIOError ASIOSetSampleRate(ASIOSampleRate sampleRate)
+{
+ if(!inited)
+ return ASE_NotPresent;
+ asioSetSampleRate f = (asioSetSampleRate)functionTable[kASIOSetSampleRate];
+ return (*f)(sampleRate);
+}
+
+ASIOError ASIOGetClockSources(ASIOClockSource *clocks, long *numSources)
+{
+ if(!inited)
+ return ASE_NotPresent;
+ asioGetClockSources f = (asioGetClockSources)functionTable[kASIOGetClockSources];
+ return (*f)(clocks, numSources);
+}
+
+ASIOError ASIOSetClockSource(long reference)
+{
+ if(!inited)
+ return ASE_NotPresent;
+ asioSetClockSource f = (asioSetClockSource)functionTable[kASIOSetClockSource];
+ return (*f)(reference);
+}
+
+ASIOError ASIOGetSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp)
+{
+ if(!inited)
+ return ASE_NotPresent;
+ asioGetSamplePosition f = (asioGetSamplePosition)functionTable[kASIOGetSamplePosition];
+ return (*f)(sPos, tStamp);
+}
+
+ASIOError ASIOGetChannelInfo(ASIOChannelInfo *info)
+{
+ if(!inited)
+ return ASE_NotPresent;
+ asioGetChannelInfo f = (asioGetChannelInfo)functionTable[kASIOGetChannelInfo];
+ return (*f)(info);
+}
+
+ASIOError ASIOCreateBuffers(ASIOBufferInfo *channelInfos, long numChannels, long bufferSize, ASIOCallbacks *callbacks)
+{
+ if(!inited)
+ return ASE_NotPresent;
+ saveRes();
+ asioCreateBuffers f = (asioCreateBuffers)functionTable[kASIOCreateBuffers];
+ ASIOError e = (*f)(channelInfos, numChannels, bufferSize, callbacks);
+ restRes();
+ return e;
+}
+
+ASIOError ASIODisposeBuffers(void)
+{
+ if(!inited)
+ return ASE_NotPresent;
+ asioDisposeBuffers f = (asioDisposeBuffers)functionTable[kASIODisposeBuffers];
+ return (*f)();
+}
+
+ASIOError ASIOControlPanel(void)
+{
+ if(!inited)
+ return ASE_NotPresent;
+ saveRes();
+ asioControlPanel f = (asioControlPanel)functionTable[kASIOControlPanel];
+ ASIOError e = (*f)();
+ restRes();
+ return e;
+}
+
+ASIOError ASIOFuture(long selector, void *opt)
+{
+ if(!inited)
+ return 0;
+ saveRes();
+ asioFuture f = (asioFuture)functionTable[kASIOFuture];
+ ASIOError e = (*f)(selector, opt);
+ restRes();
+ return e;
+}
+
+ASIOError ASIOOutputReady(void)
+{
+ asioOutputReady f = (asioControlPanel)functionTable[kASIOOutputReady];
+ if(!inited || !f)
+ return ASE_NotPresent;
+ return (*f)();
+}
+
+#pragma export off
+
+#endif // ASIOINCLUDED
+
--- /dev/null
+// very MAC specific; generic code fragment handler
+#include "ginclude.h"
+#include <macheaders.c>
+#include <string.h>
+#include <Files.h>
+#include <CodeFragments.h>
+#include "CodeFragments.hpp"
+
+enum
+{
+ kNewCFragCopy = kPrivateCFragCopy
+};
+
+class CodeFragmentInstance
+{
+private:
+friend class CodeFragment;
+ CodeFragmentInstance() {next = 0; handle = 0; connID = (void*)-1;}
+ ~CodeFragmentInstance() {CloseConnection((CFragConnectionID*)&connID); DisposeHandle(handle);}
+
+ CodeFragmentInstance *next;
+ Handle handle;
+ void* connID;
+};
+
+class CodeFragment
+{
+public:
+ CodeFragment();
+ ~CodeFragment();
+
+ bool newInstance(void** cID);
+ void removeInstance(void* id);
+ bool getName(char *name) {if(!resName[0]) return false; strcpy(name, resName); return true;}
+
+private:
+friend class CodeFragments;
+
+ CodeFragment *next;
+ CodeFragmentInstance *root;
+ Handle handle;
+ long numInstances;
+ long index;
+ char resName[64];
+};
+
+//------------------------------------------------------------------------------------------
+
+CodeFragment::CodeFragment()
+{
+ next = 0;
+ root = 0;
+ handle = 0;
+ numInstances = 0;
+ index = 0;
+ resName[0] = 0;
+}
+
+CodeFragment::~CodeFragment()
+{
+ // could delete all instances
+ // rather omit it...
+}
+
+bool CodeFragment::newInstance(void** cID)
+{
+ Ptr myMainAddr;
+ Str255 myErrName;
+ char pname[256];
+
+ *cID = (void*)-1;
+ if(!handle)
+ return false;
+ CodeFragmentInstance *c = new CodeFragmentInstance();
+ if(!c)
+ return false;
+ c->handle = this->handle;
+ OSErr err = HandToHand(&c->handle);
+ if(err == noErr)
+ {
+ // use fragment loader
+ myMainAddr = 0;
+ strcpy(pname, resName);
+ CtoPstr(pname);
+ err = GetMemFragment(*handle, GetHandleSize(handle),
+ (unsigned char *)pname, kNewCFragCopy, (CFragConnectionID*)&c->connID,
+ &myMainAddr, myErrName);
+ if(err == noErr && myMainAddr)
+ {
+ if(!root)
+ root = c;
+ else
+ {
+ CodeFragmentInstance *cc = root;
+ while(cc->next)
+ cc = cc->next;
+ cc->next = c;
+ }
+ numInstances++;
+ *cID = c->connID;
+ return true;
+ }
+ }
+ return false;
+}
+
+void CodeFragment::removeInstance(void* id)
+{
+ CodeFragmentInstance *c = root, *last = root;
+ while(c)
+ {
+ if(c->connID == id)
+ {
+ if(c == root)
+ root = root->next;
+ else
+ last->next = c->next;
+ delete c;
+ numInstances--;
+ return;
+ }
+ last = c;
+ c = c->next;
+ }
+}
+
+//----------------------------------------------------------------------------------------
+//----------------------------------------------------------------------------------------
+
+CodeFragments::CodeFragments(char *folderName, long fileType, long resType)
+{
+ root = 0;
+ numFragments = 0;
+ gARefNum = -1;
+
+ if(setFolder(folderName))
+ {
+ loadFragments(gARefNum, fileType, resType);
+ SetVol(0L, defVol);
+ }
+}
+
+CodeFragments::~CodeFragments()
+{
+ while(root)
+ {
+ CodeFragment *c = root->next;
+ delete root;
+ root = c;
+ }
+}
+
+bool CodeFragments::newInstance(long index, unsigned long* cID)
+{
+ *cID = -1;
+ CodeFragment *c = root;
+ while(c)
+ {
+ if(c->index == index)
+ return c->newInstance((void**)cID);
+ c = c->next;
+ }
+ return false;
+}
+
+void CodeFragments::removeInstance(long index, unsigned long cID)
+{
+ CodeFragment *c = root;
+ while(c)
+ {
+ if(c->index == index)
+ {
+ c->removeInstance((void*)cID);
+ break;
+ }
+ c = c->next;
+ }
+}
+
+bool CodeFragments::getName(long index, char *name)
+{
+ CodeFragment *c = root;
+ while(c)
+ {
+ if(c->index == index)
+ {
+ strcpy(name, c->resName);
+ return true;
+ }
+ c = c->next;
+ }
+ return false;
+}
+
+//------------------------------------------------------------------------------------
+// private
+
+void CodeFragments::loadFragments(short folderRef, long fileType, long resType)
+{
+ Str255 fileName;
+ HFileParam parmblock;
+ short resRef,index = 1,lindex;
+ short resID;
+ ResType resourceType;
+ Str255 resName;
+ Handle h;
+ short curResFile = CurResFile();
+
+ while(true)
+ {
+ // find any file in the folder
+ memset (&parmblock,0,(long)sizeof(HFileParam));
+ parmblock.ioNamePtr = fileName;
+ parmblock.ioVRefNum = folderRef;
+ parmblock.ioFDirIndex = index;
+ if(PBHGetFInfoSync ((HParmBlkPtr)&parmblock) != noErr)
+ break;
+
+ // see if the file type matches
+ if(parmblock.ioFlFndrInfo.fdType == fileType)
+ {
+ resRef = OpenResFile(fileName);
+ if(ResError()==noErr)
+ {
+ UseResFile(resRef);
+ lindex = 1;
+ // search resources in the file found which match
+ while(true)
+ {
+ h = Get1IndResource(resType, lindex);
+ if(h)
+ {
+ CodeFragment *c = new CodeFragment;
+ if(!root)
+ root = c;
+ else
+ {
+ CodeFragment *cc = root;
+ while(cc->next)
+ cc = cc->next;
+ cc->next = c;
+ }
+ GetResInfo(h, &resID, &resourceType, resName);
+ // PtoCstr(fileName);
+ // strcpy(c->fileName, (char *)fileName);
+ PtoCstr(resName);
+ strcpy(c->resName, (char*)resName);
+ DetachResource(h);
+ HLockHi(h);
+ c->handle = h;
+ c->index = numFragments;
+ numFragments++;
+ }
+ else
+ break;
+ lindex++;
+ }
+ CloseResFile(resRef);
+ }
+ }
+ index++;
+ }
+ UseResFile(curResFile);
+}
+
+//-----------------------------------------------------------------------------------------
+
+bool CodeFragments::setFolder(char *folderName)
+{
+ FSSpec fss;
+
+ if(gARefNum == -1)
+ {
+ if(!getFrontProcessDirectory(&fss))
+ return false;
+ if(!openFragmentFolder(&fss, folderName, &gARefNum))
+ return false;
+ }
+ defVol = getDefVol();
+ SetVol(0L, gARefNum);
+ return true;
+}
+
+bool CodeFragments::getFrontProcessDirectory(void *specs)
+{
+ FSSpec *fss = (FSSpec *)specs;
+ ProcessInfoRec pif;
+ ProcessSerialNumber psn;
+
+ memset(&psn,0,(long)sizeof(ProcessSerialNumber));
+ if(GetFrontProcess(&psn) == noErr)
+ {
+ pif.processName = 0; //(StringPtr)name;
+ pif.processAppSpec = fss;
+ pif.processInfoLength = sizeof(ProcessInfoRec);
+ if(GetProcessInformation(&psn, &pif) == noErr)
+ return true;
+ }
+ return false;
+}
+
+bool CodeFragments::openFragmentFolder(void *specs, char *foldername, short *found_vref)
+{
+ FSSpec *fss = (FSSpec *)specs;
+ WDPBRec funcparms,homefolder;
+ HFileInfo my_funcfolder;
+ char funcFolder_name[32];
+
+ *found_vref = -1;
+ strcpy(funcFolder_name,foldername);
+ CtoPstr(funcFolder_name);
+
+ memset (&homefolder,0,(long)sizeof(WDPBRec));
+ homefolder.ioVRefNum = fss->vRefNum;
+ homefolder.ioWDDirID = fss->parID;
+ if(PBOpenWDSync(&homefolder) != noErr)
+ return false;
+ memset(&my_funcfolder,0,(long)sizeof(CInfoPBRec));
+ my_funcfolder.ioNamePtr = (StringPtr)funcFolder_name;
+ my_funcfolder.ioVRefNum = homefolder.ioVRefNum;
+ if(PBGetCatInfoSync((CInfoPBPtr)&my_funcfolder) != noErr)
+ {
+ PBCloseWDSync(&homefolder);
+ return false;
+ }
+ memset (&funcparms,0,(long)sizeof(WDPBRec));
+ funcparms.ioWDProcID = 'stCA';
+ funcparms.ioVRefNum = my_funcfolder.ioVRefNum;
+ funcparms.ioWDDirID = my_funcfolder.ioDirID;
+ if(PBOpenWDSync(&funcparms) != noErr)
+ {
+ PBCloseWDSync(&homefolder);
+ return false;
+ }
+ PBCloseWDSync(&homefolder);
+ *found_vref = funcparms.ioVRefNum;
+ return true;
+}
+
+short CodeFragments::getDefVol()
+{
+ unsigned char text[32];
+ short vol_ref = 0;
+
+ *text=0;
+ if(GetVol(text, &vol_ref) == noErr)
+ return (vol_ref);
+ return 0;
+}
--- /dev/null
+#ifndef __CodeFragments__
+#define __CodeFragments__
+
+class CodeFragment;
+
+class CodeFragments
+{
+public:
+ CodeFragments(char *folderName, long fileType, long resType);
+ ~CodeFragments();
+
+ long getNumFragments() {return numFragments;}
+ bool newInstance(long index, unsigned long *cID);
+ void removeInstance(long index, unsigned long cID);
+ bool getName(long index, char *name);
+
+protected:
+ void loadFragments(short folderRef, long fileType, long resType);
+ bool setFolder(char *folderName);
+ bool openFragmentFolder(void *specs, char *foldername, short *found_vref);
+ bool getFrontProcessDirectory(void *specs);
+ short getDefVol();
+
+ CodeFragment *root;
+ long numFragments;
+ short gARefNum;
+ short defVol;
+};
+
+#endif
--- /dev/null
+#include <windows.h>
+#include "iasiodrv.h"
+#include "asiolist.h"
+
+#define ASIODRV_DESC "description"
+#define INPROC_SERVER "InprocServer32"
+#define ASIO_PATH "software\\asio"
+#define COM_CLSID "clsid"
+
+// ******************************************************************
+// Local Functions
+// ******************************************************************
+static LONG findDrvPath (char *clsidstr,char *dllpath,int dllpathsize)
+{
+ HKEY hkEnum,hksub,hkpath;
+ char databuf[512];
+ LONG cr,rc = -1;
+ DWORD datatype,datasize;
+ DWORD index;
+ OFSTRUCT ofs;
+ HFILE hfile;
+ BOOL found = FALSE;
+
+ CharLowerBuff(clsidstr,strlen(clsidstr));
+ if ((cr = RegOpenKey(HKEY_CLASSES_ROOT,COM_CLSID,&hkEnum)) == ERROR_SUCCESS) {
+
+ index = 0;
+ while (cr == ERROR_SUCCESS && !found) {
+ cr = RegEnumKey(hkEnum,index++,(LPTSTR)databuf,512);
+ if (cr == ERROR_SUCCESS) {
+ CharLowerBuff(databuf,strlen(databuf));
+ if (!(strcmp(databuf,clsidstr))) {
+ if ((cr = RegOpenKeyEx(hkEnum,(LPCTSTR)databuf,0,KEY_READ,&hksub)) == ERROR_SUCCESS) {
+ if ((cr = RegOpenKeyEx(hksub,(LPCTSTR)INPROC_SERVER,0,KEY_READ,&hkpath)) == ERROR_SUCCESS) {
+ datatype = REG_SZ; datasize = (DWORD)dllpathsize;
+ cr = RegQueryValueEx(hkpath,0,0,&datatype,(LPBYTE)dllpath,&datasize);
+ if (cr == ERROR_SUCCESS) {
+ memset(&ofs,0,sizeof(OFSTRUCT));
+ ofs.cBytes = sizeof(OFSTRUCT);
+ hfile = OpenFile(dllpath,&ofs,OF_EXIST);
+ if (hfile) rc = 0;
+ }
+ RegCloseKey(hkpath);
+ }
+ RegCloseKey(hksub);
+ }
+ found = TRUE; // break out
+ }
+ }
+ }
+ RegCloseKey(hkEnum);
+ }
+ return rc;
+}
+
+
+static LPASIODRVSTRUCT newDrvStruct (HKEY hkey,char *keyname,int drvID,LPASIODRVSTRUCT lpdrv)
+{
+ HKEY hksub;
+ char databuf[256];
+ char dllpath[MAXPATHLEN];
+ WORD wData[100];
+ CLSID clsid;
+ DWORD datatype,datasize;
+ LONG cr,rc;
+
+ if (!lpdrv) {
+ if ((cr = RegOpenKeyEx(hkey,(LPCTSTR)keyname,0,KEY_READ,&hksub)) == ERROR_SUCCESS) {
+
+ datatype = REG_SZ; datasize = 256;
+ cr = RegQueryValueEx(hksub,COM_CLSID,0,&datatype,(LPBYTE)databuf,&datasize);
+ if (cr == ERROR_SUCCESS) {
+ rc = findDrvPath (databuf,dllpath,MAXPATHLEN);
+ if (rc == 0) {
+ lpdrv = new ASIODRVSTRUCT[1];
+ if (lpdrv) {
+ memset(lpdrv,0,sizeof(ASIODRVSTRUCT));
+ lpdrv->drvID = drvID;
+ MultiByteToWideChar(CP_ACP,0,(LPCSTR)databuf,-1,(LPWSTR)wData,100);
+ if ((cr = CLSIDFromString((LPOLESTR)wData,(LPCLSID)&clsid)) == S_OK) {
+ memcpy(&lpdrv->clsid,&clsid,sizeof(CLSID));
+ }
+
+ datatype = REG_SZ; datasize = 256;
+ cr = RegQueryValueEx(hksub,ASIODRV_DESC,0,&datatype,(LPBYTE)databuf,&datasize);
+ if (cr == ERROR_SUCCESS) {
+ strcpy(lpdrv->drvname,databuf);
+ }
+ else strcpy(lpdrv->drvname,keyname);
+ }
+ }
+ }
+ RegCloseKey(hksub);
+ }
+ }
+ else lpdrv->next = newDrvStruct(hkey,keyname,drvID+1,lpdrv->next);
+
+ return lpdrv;
+}
+
+static void deleteDrvStruct (LPASIODRVSTRUCT lpdrv)
+{
+ IASIO *iasio;
+
+ if (lpdrv != 0) {
+ deleteDrvStruct(lpdrv->next);
+ if (lpdrv->asiodrv) {
+ iasio = (IASIO *)lpdrv->asiodrv;
+ iasio->Release();
+ }
+ delete lpdrv;
+ }
+}
+
+
+static LPASIODRVSTRUCT getDrvStruct (int drvID,LPASIODRVSTRUCT lpdrv)
+{
+ while (lpdrv) {
+ if (lpdrv->drvID == drvID) return lpdrv;
+ lpdrv = lpdrv->next;
+ }
+ return 0;
+}
+// ******************************************************************
+
+
+// ******************************************************************
+// AsioDriverList
+// ******************************************************************
+AsioDriverList::AsioDriverList ()
+{
+ HKEY hkEnum = 0;
+ char keyname[MAXDRVNAMELEN];
+ LPASIODRVSTRUCT pdl;
+ LONG cr;
+ DWORD index = 0;
+ BOOL fin = FALSE;
+
+ numdrv = 0;
+ lpdrvlist = 0;
+
+ cr = RegOpenKey(HKEY_LOCAL_MACHINE,ASIO_PATH,&hkEnum);
+ while (cr == ERROR_SUCCESS) {
+ if ((cr = RegEnumKey(hkEnum,index++,(LPTSTR)keyname,MAXDRVNAMELEN))== ERROR_SUCCESS) {
+ lpdrvlist = newDrvStruct (hkEnum,keyname,0,lpdrvlist);
+ }
+ else fin = TRUE;
+ }
+ if (hkEnum) RegCloseKey(hkEnum);
+
+ pdl = lpdrvlist;
+ while (pdl) {
+ numdrv++;
+ pdl = pdl->next;
+ }
+
+ if (numdrv) CoInitialize(0); // initialize COM
+}
+
+AsioDriverList::~AsioDriverList ()
+{
+ if (numdrv) {
+ deleteDrvStruct(lpdrvlist);
+ CoUninitialize();
+ }
+}
+
+
+LONG AsioDriverList::asioGetNumDev (VOID)
+{
+ return (LONG)numdrv;
+}
+
+
+LONG AsioDriverList::asioOpenDriver (int drvID,LPVOID *asiodrv)
+{
+ LPASIODRVSTRUCT lpdrv = 0;
+ long rc;
+
+ if (!asiodrv) return DRVERR_INVALID_PARAM;
+
+ if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
+ if (!lpdrv->asiodrv) {
+ rc = CoCreateInstance(lpdrv->clsid,0,CLSCTX_INPROC_SERVER,lpdrv->clsid,asiodrv);
+ if (rc == S_OK) {
+ lpdrv->asiodrv = *asiodrv;
+ return 0;
+ }
+ // else if (rc == REGDB_E_CLASSNOTREG)
+ // strcpy (info->messageText, "Driver not registered in the Registration Database!");
+ }
+ else rc = DRVERR_DEVICE_ALREADY_OPEN;
+ }
+ else rc = DRVERR_DEVICE_NOT_FOUND;
+
+ return rc;
+}
+
+
+LONG AsioDriverList::asioCloseDriver (int drvID)
+{
+ LPASIODRVSTRUCT lpdrv = 0;
+ IASIO *iasio;
+
+ if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
+ if (lpdrv->asiodrv) {
+ iasio = (IASIO *)lpdrv->asiodrv;
+ iasio->Release();
+ lpdrv->asiodrv = 0;
+ }
+ }
+
+ return 0;
+}
+
+LONG AsioDriverList::asioGetDriverName (int drvID,char *drvname,int drvnamesize)
+{
+ LPASIODRVSTRUCT lpdrv = 0;
+
+ if (!drvname) return DRVERR_INVALID_PARAM;
+
+ if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
+ if (strlen(lpdrv->drvname) < (unsigned int)drvnamesize) {
+ strcpy(drvname,lpdrv->drvname);
+ }
+ else {
+ memcpy(drvname,lpdrv->drvname,drvnamesize-4);
+ drvname[drvnamesize-4] = '.';
+ drvname[drvnamesize-3] = '.';
+ drvname[drvnamesize-2] = '.';
+ drvname[drvnamesize-1] = 0;
+ }
+ return 0;
+ }
+ return DRVERR_DEVICE_NOT_FOUND;
+}
+
+LONG AsioDriverList::asioGetDriverPath (int drvID,char *dllpath,int dllpathsize)
+{
+ LPASIODRVSTRUCT lpdrv = 0;
+
+ if (!dllpath) return DRVERR_INVALID_PARAM;
+
+ if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
+ if (strlen(lpdrv->dllpath) < (unsigned int)dllpathsize) {
+ strcpy(dllpath,lpdrv->dllpath);
+ return 0;
+ }
+ dllpath[0] = 0;
+ return DRVERR_INVALID_PARAM;
+ }
+ return DRVERR_DEVICE_NOT_FOUND;
+}
+
+LONG AsioDriverList::asioGetDriverCLSID (int drvID,CLSID *clsid)
+{
+ LPASIODRVSTRUCT lpdrv = 0;
+
+ if (!clsid) return DRVERR_INVALID_PARAM;
+
+ if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
+ memcpy(clsid,&lpdrv->clsid,sizeof(CLSID));
+ return 0;
+ }
+ return DRVERR_DEVICE_NOT_FOUND;
+}
+
+
--- /dev/null
+#ifndef __asiolist__
+#define __asiolist__
+
+#define DRVERR -5000
+#define DRVERR_INVALID_PARAM DRVERR-1
+#define DRVERR_DEVICE_ALREADY_OPEN DRVERR-2
+#define DRVERR_DEVICE_NOT_FOUND DRVERR-3
+
+#define MAXPATHLEN 512
+#define MAXDRVNAMELEN 128
+
+struct asiodrvstruct
+{
+ int drvID;
+ CLSID clsid;
+ char dllpath[MAXPATHLEN];
+ char drvname[MAXDRVNAMELEN];
+ LPVOID asiodrv;
+ struct asiodrvstruct *next;
+};
+
+typedef struct asiodrvstruct ASIODRVSTRUCT;
+typedef ASIODRVSTRUCT *LPASIODRVSTRUCT;
+
+class AsioDriverList {
+public:
+ AsioDriverList();
+ ~AsioDriverList();
+
+ LONG asioOpenDriver (int,VOID **);
+ LONG asioCloseDriver (int);
+
+ // nice to have
+ LONG asioGetNumDev (VOID);
+ LONG asioGetDriverName (int,char *,int);
+ LONG asioGetDriverPath (int,char *,int);
+ LONG asioGetDriverCLSID (int,CLSID *);
+
+ // or use directly access
+ LPASIODRVSTRUCT lpdrvlist;
+ int numdrv;
+};
+
+typedef class AsioDriverList *LPASIODRIVERLIST;
+
+#endif
--- /dev/null
+// hostsample.cpp : a simple ASIO host example.
+// - instantiates the driver
+// - get the information from the driver
+// - built up some audio channels
+// - plays silence for 20 seconds
+// - destruct the driver
+// Note: This sample cannot work with the "ASIO DirectX Driver" as it does
+// not have a valid Application Window handle, which is used as sysRef
+// on the Windows platform.
+
+#include <stdio.h>
+#include <string.h>
+#include "asiosys.h"
+#include "asio.h"
+#include "asiodrivers.h"
+
+// name of the ASIO device to be used
+#if WINDOWS
+// #define ASIO_DRIVER_NAME "ASIO Multimedia Driver"
+ #define ASIO_DRIVER_NAME "ASIO Sample"
+#elif MAC
+// #define ASIO_DRIVER_NAME "Apple Sound Manager"
+ #define ASIO_DRIVER_NAME "ASIO Sample"
+#endif
+
+#define TEST_RUN_TIME 20.0 // run for 20 seconds
+
+
+enum {
+ // number of input and outputs supported by the host application
+ // you can change these to higher or lower values
+ kMaxInputChannels = 32,
+ kMaxOutputChannels = 32
+};
+
+
+// internal data storage
+typedef struct DriverInfo
+{
+ // ASIOInit()
+ ASIODriverInfo driverInfo;
+
+ // ASIOGetChannels()
+ long inputChannels;
+ long outputChannels;
+
+ // ASIOGetBufferSize()
+ long minSize;
+ long maxSize;
+ long preferredSize;
+ long granularity;
+
+ // ASIOGetSampleRate()
+ ASIOSampleRate sampleRate;
+
+ // ASIOOutputReady()
+ bool postOutput;
+
+ // ASIOGetLatencies ()
+ long inputLatency;
+ long outputLatency;
+
+ // ASIOCreateBuffers ()
+ long inputBuffers; // becomes number of actual created input buffers
+ long outputBuffers; // becomes number of actual created output buffers
+ ASIOBufferInfo bufferInfos[kMaxInputChannels + kMaxOutputChannels]; // buffer info's
+
+ // ASIOGetChannelInfo()
+ ASIOChannelInfo channelInfos[kMaxInputChannels + kMaxOutputChannels]; // channel info's
+ // The above two arrays share the same indexing, as the data in them are linked together
+
+ // Information from ASIOGetSamplePosition()
+ // data is converted to double floats for easier use, however 64 bit integer can be used, too
+ double nanoSeconds;
+ double samples;
+ double tcSamples; // time code samples
+
+ // bufferSwitchTimeInfo()
+ ASIOTime tInfo; // time info state
+ unsigned long sysRefTime; // system reference time, when bufferSwitch() was called
+
+ // Signal the end of processing in this example
+ bool stopped;
+} DriverInfo;
+
+
+DriverInfo asioDriverInfo = {0};
+ASIOCallbacks asioCallbacks;
+
+//----------------------------------------------------------------------------------
+// some external references
+extern AsioDrivers* asioDrivers;
+bool loadAsioDriver(char *name);
+
+// internal prototypes (required for the Metrowerks CodeWarrior compiler)
+int main(int argc, char* argv[]);
+long init_asio_static_data (DriverInfo *asioDriverInfo);
+ASIOError create_asio_buffers (DriverInfo *asioDriverInfo);
+unsigned long get_sys_reference_time();
+
+
+// callback prototypes
+void bufferSwitch(long index, ASIOBool processNow);
+ASIOTime *bufferSwitchTimeInfo(ASIOTime *timeInfo, long index, ASIOBool processNow);
+void sampleRateChanged(ASIOSampleRate sRate);
+long asioMessages(long selector, long value, void* message, double* opt);
+
+
+
+//----------------------------------------------------------------------------------
+long init_asio_static_data (DriverInfo *asioDriverInfo)
+{ // collect the informational data of the driver
+ // get the number of available channels
+ if(ASIOGetChannels(&asioDriverInfo->inputChannels, &asioDriverInfo->outputChannels) == ASE_OK)
+ {
+ printf ("ASIOGetChannels (inputs: %d, outputs: %d);\n", asioDriverInfo->inputChannels, asioDriverInfo->outputChannels);
+
+ // get the usable buffer sizes
+ if(ASIOGetBufferSize(&asioDriverInfo->minSize, &asioDriverInfo->maxSize, &asioDriverInfo->preferredSize, &asioDriverInfo->granularity) == ASE_OK)
+ {
+ printf ("ASIOGetBufferSize (min: %d, max: %d, preferred: %d, granularity: %d);\n",
+ asioDriverInfo->minSize, asioDriverInfo->maxSize,
+ asioDriverInfo->preferredSize, asioDriverInfo->granularity);
+
+ // get the currently selected sample rate
+ if(ASIOGetSampleRate(&asioDriverInfo->sampleRate) == ASE_OK)
+ {
+ printf ("ASIOGetSampleRate (sampleRate: %f);\n", asioDriverInfo->sampleRate);
+ if (asioDriverInfo->sampleRate <= 0.0 || asioDriverInfo->sampleRate > 96000.0)
+ {
+ // Driver does not store it's internal sample rate, so set it to a know one.
+ // Usually you should check beforehand, that the selected sample rate is valid
+ // with ASIOCanSampleRate().
+ if(ASIOSetSampleRate(44100.0) == ASE_OK)
+ {
+ if(ASIOGetSampleRate(&asioDriverInfo->sampleRate) == ASE_OK)
+ printf ("ASIOGetSampleRate (sampleRate: %f);\n", asioDriverInfo->sampleRate);
+ else
+ return -6;
+ }
+ else
+ return -5;
+ }
+
+ // check wether the driver requires the ASIOOutputReady() optimization
+ // (can be used by the driver to reduce output latency by one block)
+ if(ASIOOutputReady() == ASE_OK)
+ asioDriverInfo->postOutput = true;
+ else
+ asioDriverInfo->postOutput = false;
+ printf ("ASIOOutputReady(); - %s\n", asioDriverInfo->postOutput ? "Supported" : "Not supported");
+
+ return 0;
+ }
+ return -3;
+ }
+ return -2;
+ }
+ return -1;
+}
+
+
+//----------------------------------------------------------------------------------
+// conversion from 64 bit ASIOSample/ASIOTimeStamp to double float
+#if NATIVE_INT64
+ #define ASIO64toDouble(a) (a)
+#else
+ const double twoRaisedTo32 = 4294967296.;
+ #define ASIO64toDouble(a) ((a).lo + (a).hi * twoRaisedTo32)
+#endif
+
+ASIOTime *bufferSwitchTimeInfo(ASIOTime *timeInfo, long index, ASIOBool processNow)
+{ // the actual processing callback.
+ // Beware that this is normally in a seperate thread, hence be sure that you take care
+ // about thread synchronization. This is omitted here for simplicity.
+ static long processedSamples = 0;
+
+ // store the timeInfo for later use
+ asioDriverInfo.tInfo = *timeInfo;
+
+ // get the time stamp of the buffer, not necessary if no
+ // synchronization to other media is required
+ if (timeInfo->timeInfo.flags & kSystemTimeValid)
+ asioDriverInfo.nanoSeconds = ASIO64toDouble(timeInfo->timeInfo.systemTime);
+ else
+ asioDriverInfo.nanoSeconds = 0;
+
+ if (timeInfo->timeInfo.flags & kSamplePositionValid)
+ asioDriverInfo.samples = ASIO64toDouble(timeInfo->timeInfo.samplePosition);
+ else
+ asioDriverInfo.samples = 0;
+
+ if (timeInfo->timeCode.flags & kTcValid)
+ asioDriverInfo.tcSamples = ASIO64toDouble(timeInfo->timeCode.timeCodeSamples);
+ else
+ asioDriverInfo.tcSamples = 0;
+
+ // get the system reference time
+ asioDriverInfo.sysRefTime = get_sys_reference_time();
+
+#if WINDOWS && _DEBUG
+ // a few debug messages for the Windows device driver developer
+ // tells you the time when driver got its interrupt and the delay until the app receives
+ // the event notification.
+ static double last_samples = 0;
+ char tmp[128];
+ sprintf (tmp, "diff: %d / %d ms / %d ms / %d samples \n", asioDriverInfo.sysRefTime - (long)(asioDriverInfo.nanoSeconds / 1000000.0), asioDriverInfo.sysRefTime, (long)(asioDriverInfo.nanoSeconds / 1000000.0), (long)(asioDriverInfo.samples - last_samples));
+ OutputDebugString (tmp);
+ last_samples = asioDriverInfo.samples;
+#endif
+
+ // buffer size in samples
+ long buffSize = asioDriverInfo.preferredSize;
+
+ // perform the processing
+ for (int i = 0; i < asioDriverInfo.inputBuffers + asioDriverInfo.outputBuffers; i++)
+ {
+ if (asioDriverInfo.bufferInfos[i].isInput == false)
+ {
+ // OK do processing for the outputs only
+ switch (asioDriverInfo.channelInfos[i].type)
+ {
+ case ASIOSTInt16LSB:
+ memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 2);
+ break;
+ case ASIOSTInt24LSB: // used for 20 bits as well
+ memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 3);
+ break;
+ case ASIOSTInt32LSB:
+ memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
+ break;
+ case ASIOSTFloat32LSB: // IEEE 754 32 bit float, as found on Intel x86 architecture
+ memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
+ break;
+ case ASIOSTFloat64LSB: // IEEE 754 64 bit double float, as found on Intel x86 architecture
+ memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 8);
+ break;
+
+ // 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
+ case ASIOSTInt32LSB16: // 32 bit data with 18 bit alignment
+ case ASIOSTInt32LSB18: // 32 bit data with 18 bit alignment
+ case ASIOSTInt32LSB20: // 32 bit data with 20 bit alignment
+ case ASIOSTInt32LSB24: // 32 bit data with 24 bit alignment
+ memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
+ break;
+
+ case ASIOSTInt16MSB:
+ memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 2);
+ break;
+ case ASIOSTInt24MSB: // used for 20 bits as well
+ memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 3);
+ break;
+ case ASIOSTInt32MSB:
+ memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
+ break;
+ case ASIOSTFloat32MSB: // IEEE 754 32 bit float, as found on Intel x86 architecture
+ memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
+ break;
+ case ASIOSTFloat64MSB: // IEEE 754 64 bit double float, as found on Intel x86 architecture
+ memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 8);
+ break;
+
+ // 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
+ case ASIOSTInt32MSB16: // 32 bit data with 18 bit alignment
+ case ASIOSTInt32MSB18: // 32 bit data with 18 bit alignment
+ case ASIOSTInt32MSB20: // 32 bit data with 20 bit alignment
+ case ASIOSTInt32MSB24: // 32 bit data with 24 bit alignment
+ memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
+ break;
+ }
+ }
+ }
+
+ // finally if the driver supports the ASIOOutputReady() optimization, do it here, all data are in place
+ if (asioDriverInfo.postOutput)
+ ASIOOutputReady();
+
+ if (processedSamples >= asioDriverInfo.sampleRate * TEST_RUN_TIME) // roughly measured
+ asioDriverInfo.stopped = true;
+ else
+ processedSamples += buffSize;
+
+ return 0L;
+}
+
+//----------------------------------------------------------------------------------
+void bufferSwitch(long index, ASIOBool processNow)
+{ // the actual processing callback.
+ // Beware that this is normally in a seperate thread, hence be sure that you take care
+ // about thread synchronization. This is omitted here for simplicity.
+
+ // as this is a "back door" into the bufferSwitchTimeInfo a timeInfo needs to be created
+ // though it will only set the timeInfo.samplePosition and timeInfo.systemTime fields and the according flags
+ ASIOTime timeInfo;
+ memset (&timeInfo, 0, sizeof (timeInfo));
+
+ // get the time stamp of the buffer, not necessary if no
+ // synchronization to other media is required
+ if(ASIOGetSamplePosition(&timeInfo.timeInfo.samplePosition, &timeInfo.timeInfo.systemTime) == ASE_OK)
+ timeInfo.timeInfo.flags = kSystemTimeValid | kSamplePositionValid;
+
+ bufferSwitchTimeInfo (&timeInfo, index, processNow);
+}
+
+
+//----------------------------------------------------------------------------------
+void sampleRateChanged(ASIOSampleRate sRate)
+{
+ // do whatever you need to do if the sample rate changed
+ // usually this only happens during external sync.
+ // Audio processing is not stopped by the driver, actual sample rate
+ // might not have even changed, maybe only the sample rate status of an
+ // AES/EBU or S/PDIF digital input at the audio device.
+ // You might have to update time/sample related conversion routines, etc.
+}
+
+//----------------------------------------------------------------------------------
+long asioMessages(long selector, long value, void* message, double* opt)
+{
+ // currently the parameters "value", "message" and "opt" are not used.
+ long ret = 0;
+ switch(selector)
+ {
+ case kAsioSelectorSupported:
+ if(value == kAsioResetRequest
+ || value == kAsioEngineVersion
+ || value == kAsioResyncRequest
+ || value == kAsioLatenciesChanged
+ // the following three were added for ASIO 2.0, you don't necessarily have to support them
+ || value == kAsioSupportsTimeInfo
+ || value == kAsioSupportsTimeCode
+ || value == kAsioSupportsInputMonitor)
+ ret = 1L;
+ break;
+ case kAsioResetRequest:
+ // defer the task and perform the reset of the driver during the next "safe" situation
+ // You cannot reset the driver right now, as this code is called from the driver.
+ // Reset the driver is done by completely destruct is. I.e. ASIOStop(), ASIODisposeBuffers(), Destruction
+ // Afterwards you initialize the driver again.
+ asioDriverInfo.stopped; // In this sample the processing will just stop
+ ret = 1L;
+ break;
+ case kAsioResyncRequest:
+ // This informs the application, that the driver encountered some non fatal data loss.
+ // It is used for synchronization purposes of different media.
+ // Added mainly to work around the Win16Mutex problems in Windows 95/98 with the
+ // Windows Multimedia system, which could loose data because the Mutex was hold too long
+ // by another thread.
+ // However a driver can issue it in other situations, too.
+ ret = 1L;
+ break;
+ case kAsioLatenciesChanged:
+ // This will inform the host application that the drivers were latencies changed.
+ // Beware, it this does not mean that the buffer sizes have changed!
+ // You might need to update internal delay data.
+ ret = 1L;
+ break;
+ case kAsioEngineVersion:
+ // return the supported ASIO version of the host application
+ // If a host applications does not implement this selector, ASIO 1.0 is assumed
+ // by the driver
+ ret = 2L;
+ break;
+ case kAsioSupportsTimeInfo:
+ // informs the driver wether the asioCallbacks.bufferSwitchTimeInfo() callback
+ // is supported.
+ // For compatibility with ASIO 1.0 drivers the host application should always support
+ // the "old" bufferSwitch method, too.
+ ret = 1;
+ break;
+ case kAsioSupportsTimeCode:
+ // informs the driver wether application is interested in time code info.
+ // If an application does not need to know about time code, the driver has less work
+ // to do.
+ ret = 0;
+ break;
+ }
+ return ret;
+}
+
+
+//----------------------------------------------------------------------------------
+ASIOError create_asio_buffers (DriverInfo *asioDriverInfo)
+{ // create buffers for all inputs and outputs of the card with the
+ // preferredSize from ASIOGetBufferSize() as buffer size
+ long i;
+ ASIOError result;
+
+ // fill the bufferInfos from the start without a gap
+ ASIOBufferInfo *info = asioDriverInfo->bufferInfos;
+
+ // prepare inputs (Though this is not necessaily required, no opened inputs will work, too
+ if (asioDriverInfo->inputChannels > kMaxInputChannels)
+ asioDriverInfo->inputBuffers = kMaxInputChannels;
+ else
+ asioDriverInfo->inputBuffers = asioDriverInfo->inputChannels;
+ for(i = 0; i < asioDriverInfo->inputBuffers; i++, info++)
+ {
+ info->isInput = ASIOTrue;
+ info->channelNum = i;
+ info->buffers[0] = info->buffers[1] = 0;
+ }
+
+ // prepare outputs
+ if (asioDriverInfo->outputChannels > kMaxOutputChannels)
+ asioDriverInfo->outputBuffers = kMaxOutputChannels;
+ else
+ asioDriverInfo->outputBuffers = asioDriverInfo->outputChannels;
+ for(i = 0; i < asioDriverInfo->outputBuffers; i++, info++)
+ {
+ info->isInput = ASIOFalse;
+ info->channelNum = i;
+ info->buffers[0] = info->buffers[1] = 0;
+ }
+
+ // create and activate buffers
+ result = ASIOCreateBuffers(asioDriverInfo->bufferInfos,
+ asioDriverInfo->inputBuffers + asioDriverInfo->outputBuffers,
+ asioDriverInfo->preferredSize, &asioCallbacks);
+ if (result == ASE_OK)
+ {
+ // now get all the buffer details, sample word length, name, word clock group and activation
+ for (i = 0; i < asioDriverInfo->inputBuffers + asioDriverInfo->outputBuffers; i++)
+ {
+ asioDriverInfo->channelInfos[i].channel = asioDriverInfo->bufferInfos[i].channelNum;
+ asioDriverInfo->channelInfos[i].isInput = asioDriverInfo->bufferInfos[i].isInput;
+ result = ASIOGetChannelInfo(&asioDriverInfo->channelInfos[i]);
+ if (result != ASE_OK)
+ break;
+ }
+
+ if (result == ASE_OK)
+ {
+ // get the input and output latencies
+ // Latencies often are only valid after ASIOCreateBuffers()
+ // (input latency is the age of the first sample in the currently returned audio block)
+ // (output latency is the time the first sample in the currently returned audio block requires to get to the output)
+ result = ASIOGetLatencies(&asioDriverInfo->inputLatency, &asioDriverInfo->outputLatency);
+ if (result == ASE_OK)
+ printf ("ASIOGetLatencies (input: %d, output: %d);\n", asioDriverInfo->inputLatency, asioDriverInfo->outputLatency);
+ }
+ }
+ return result;
+}
+
+int main(int argc, char* argv[])
+{
+ // load the driver, this will setup all the necessary internal data structures
+ if (loadAsioDriver (ASIO_DRIVER_NAME))
+ {
+ // initialize the driver
+ if (ASIOInit (&asioDriverInfo.driverInfo) == ASE_OK)
+ {
+ printf ("asioVersion: %d\n"
+ "driverVersion: %d\n"
+ "Name: %s\n"
+ "ErrorMessage: %s\n",
+ asioDriverInfo.driverInfo.asioVersion, asioDriverInfo.driverInfo.driverVersion,
+ asioDriverInfo.driverInfo.name, asioDriverInfo.driverInfo.errorMessage);
+ if (init_asio_static_data (&asioDriverInfo) == 0)
+ {
+ // ASIOControlPanel(); you might want to check wether the ASIOControlPanel() can open
+
+ // set up the asioCallback structure and create the ASIO data buffer
+ asioCallbacks.bufferSwitch = &bufferSwitch;
+ asioCallbacks.sampleRateDidChange = &sampleRateChanged;
+ asioCallbacks.asioMessage = &asioMessages;
+ asioCallbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfo;
+ if (create_asio_buffers (&asioDriverInfo) == ASE_OK)
+ {
+ if (ASIOStart() == ASE_OK)
+ {
+ // Now all is up and running
+ fprintf (stdout, "\nASIO Driver started succefully.\n\n");
+ while (!asioDriverInfo.stopped)
+ {
+#if WINDOWS
+ Sleep(100); // goto sleep for 100 milliseconds
+#elif MAC
+ unsigned long dummy;
+ Delay (6, &dummy);
+#endif
+ fprintf (stdout, "%d ms / %d ms / %d samples", asioDriverInfo.sysRefTime, (long)(asioDriverInfo.nanoSeconds / 1000000.0), (long)asioDriverInfo.samples);
+
+ // create a more readable time code format (the quick and dirty way)
+ double remainder = asioDriverInfo.tcSamples;
+ long hours = (long)(remainder / (asioDriverInfo.sampleRate * 3600));
+ remainder -= hours * asioDriverInfo.sampleRate * 3600;
+ long minutes = (long)(remainder / (asioDriverInfo.sampleRate * 60));
+ remainder -= minutes * asioDriverInfo.sampleRate * 60;
+ long seconds = (long)(remainder / asioDriverInfo.sampleRate);
+ remainder -= seconds * asioDriverInfo.sampleRate;
+ fprintf (stdout, " / TC: %2.2d:%2.2d:%2.2d:%5.5d", (long)hours, (long)minutes, (long)seconds, (long)remainder);
+
+ fprintf (stdout, " \r");
+ #if !MAC
+ fflush (stdout);
+ #endif
+ }
+ ASIOStop();
+ }
+ ASIODisposeBuffers();
+ }
+ }
+ ASIOExit();
+ }
+ asioDrivers->removeCurrentDriver();
+ }
+ return 0;
+}
+
+
+unsigned long get_sys_reference_time()
+{ // get the system reference time
+#if WINDOWS
+ return timeGetTime();
+#elif MAC
+static const double twoRaisedTo32 = 4294967296.;
+ UnsignedWide ys;
+ Microseconds(&ys);
+ double r = ((double)ys.hi * twoRaisedTo32 + (double)ys.lo);
+ return (unsigned long)(r / 1000.);
+#endif
+}
--- /dev/null
+# Microsoft Developer Studio Project File - Name="hostsample" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=hostsample - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "hostsample.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "hostsample.mak" CFG="hostsample - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "hostsample - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "hostsample - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "hostsample - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "../../common" /I "../../host" /I "../../host/pc" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "hostsample - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../common" /I "../../host" /I "../../host/pc" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "hostsample - Win32 Release"
+# Name "hostsample - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\common\asio.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\asiodrivers.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\pc\asiolist.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\hostsample.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\common\asio.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\asiodrivers.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\pc\asiolist.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ginclude.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Source File
+
+SOURCE=.\ReadMe.txt
+# End Source File
+# End Target
+# End Project
--- /dev/null
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="hostsample"
+ ProjectGUID="{1E10ECB0-0666-474F-A010-660E7CE9DC00}"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\Release/hostsample.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="../../common,../../host,../../host/pc"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ PrecompiledHeaderFile=".\Release/hostsample.pch"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="2057"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib winmm.lib"
+ OutputFile="$(PlatformName)\$(ConfigurationName)\hostsample.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ TypeLibraryName=".\Release/hostsample.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="../../common,../../host,../../host/pc"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ PrecompiledHeaderFile=".\Release/hostsample.pch"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="2057"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib winmm.lib"
+ OutputFile="$(PlatformName)\$(ConfigurationName)\hostsample.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="true"
+ SubSystem="1"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\Debug/hostsample.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../common,../../host,../../host/pc"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\Debug/hostsample.pch"
+ BrowseInformation="1"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="2057"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib winmm.lib"
+ OutputFile="$(PlatformName)\$(ConfigurationName)\hostsample.exe"
+ LinkIncremental="2"
+ SuppressStartupBanner="true"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ TypeLibraryName=".\Debug/hostsample.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../common,../../host,../../host/pc"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\Debug/hostsample.pch"
+ BrowseInformation="1"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="2057"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib winmm.lib"
+ OutputFile="$(PlatformName)\$(ConfigurationName)\hostsample.exe"
+ LinkIncremental="2"
+ SuppressStartupBanner="true"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="..\..\common\asio.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\asiodrivers.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\pc\asiolist.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hostsample.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="..\..\common\asio.h"
+ >
+ </File>
+ <File
+ RelativePath="..\asiodrivers.h"
+ >
+ </File>
+ <File
+ RelativePath="..\pc\asiolist.h"
+ >
+ </File>
+ <File
+ RelativePath="..\ginclude.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+ >
+ </Filter>
+ <File
+ RelativePath="ReadMe.txt"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
--- /dev/null
+ASIO 2.3 SDK Contents
+---------------------
+
+readme.txt - this file
+changes.txt - contains change information between
+ SDK releases
+ASIO SDK 2.3.pdf - ASIO SDK 2.3 specification
+Steinberg ASIO Licensing Agreement.pdf - Licencing Agreement
+
+common:
+asio.h - ASIO C definition
+iasiodrv.h - interface definition for the ASIO driver class
+asio.cpp - asio host interface (not used on Mac)
+asiodrvr.h
+asiodrvr.cpp - ASIO driver class base definition
+combase.h
+combase.cpp - COM base definitions (PC only)
+dllentry.cpp - DLL functions (PC only)
+register.cpp - driver self registration functionality
+wxdebug.h
+debugmessage.cpp - some debugging help
+
+host:
+asiodrivers.h
+asiodrivers.cpp - ASIO driver managment (enumeration and instantiation)
+ASIOConvertSamples.h
+ASIOConvertSamples.cpp - sample data format conversion class
+ginclude.h - platform specific definitions
+
+host/mac:
+asioshlib.cpp - asio.cpp for the Mac, resolves the symbols
+codefragments.hpp
+codefragments.cpp - code fragment loader
+
+host/pc:
+asiolist.h
+asiolist.cpp - instantiates an ASIO driver via the COM model
+
+host/sample:
+hostsample.cpp - a simple console app which shows ASIO hosting
+hostsample.dsp - MSVC++ 5.0 project
+hostsample.vcproj - Visual Studio 2005 project (32 and 64 bit targets)
+
+driver/asiosample:
+asiosmpl.h
+asiosmpl.cpp - ASIO 2.0 sample driver
+wintimer.cpp - bufferSwitch() wakeup thread (Windows)
+asiosample.def - Windows DLL module export definition
+mactimer.cpp - bufferSwitch() wakeup thread (Macintosh)
+macnanosecs.cpp - Macintosh system reference time
+makesamp.cpp - Macintosh driver object instantiation
+
+driver/asiosample/asiosample:
+asiosample.dsp - MSVC++ 5.0 project
+asiosample.vcproj - Visual Studio 2005 project (32 and 64 bit targets)