I would greatly appreciate anyone that can help me with the proper way to
declare this interface?
Here is the C++ declaration:
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 /* array */, 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;
};
Here is what I have so far:
[Guid("615C2C61-F8EB-11d3-B0B2-0000E8ED4AD9")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IAsioDelta1010
{
AsioBool init(IntPtr sysHandle); // void *
void getDriverName(out String name); // char *
int getDriverVersion();
void getErrorMessage(out String message); // char *
AsioError start();
AsioError stop();
AsioError getChannels(out int numInputChannels, out int
numOutputChannels);// long *
AsioError getLatencies(out int inputLatency, out int outputLatency);
// long *
AsioError getBufferSize(out int minSize, out int maxSize,
out int preferredSize, out int granularity);
// long *
AsioError canSampleRate(double sampleRate);
AsioError getSampleRate(out double sampleRate); // double *
AsioError setSampleRate(double sampleRate);
AsioError getClockSources(ref AsioClockSource[] clocks, ref int
numSources);
AsioError setClockSource(int reference);
AsioError getSamplePosition(out AsioSamples sPos, out AsioTimeStamp
tStamp);
AsioError getChannelInfo(ref AsioChannelInfo info);
AsioError createBuffers(ref AsioBufferInfo[] bufferInfos, int
numChannels,
int bufferSize, ref AsioCallbacks callbacks);
AsioError disposeBuffers();
AsioError controlPanel();
AsioError future(int selector, IntPtr opt); // void *
AsioError outputReady();
}
Here is my code to create the COM object:
Type AsioDelta1010 = Type.GetTypeFromCLSID(AsioGuid.Delta1010, true);
IAsioDelta1010 delta1010 =
(IAsioDelta1010)Activator.CreateInstance(AsioDelta1010);
delta1010.init(this.Handle); <<<--- this throws protected memory access
violation
int ver = delta1010.getDriverVersion();
Console.WriteLine(ver);
Here is the rest of the code I have converted thus far:
public enum AsioBool : int
{
ASIOFalse = 0,
ASIOTrue = 1
}
public enum AsioError : int
{
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
}
public struct AsioClockSource
{
public int index; // as used for ASIOSetClockSource()
public int associatedChannel; // for instance, S/PDIF or AES/EBU
public int associatedGroup; // see channel groups
(ASIOGetChannelInfo())
public AsioBool isCurrentSource; // ASIOTrue if this is the current
clock source
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
public string name; // for user selection
}
public struct AsioSamples
{
public uint hi;
public uint lo;
}
public struct AsioTimeStamp
{
public uint hi;
public uint lo;
}
public enum AsioSampleType : int
{
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
}
public struct AsioChannelInfo
{
public int channel; // on input, channel index
public AsioBool isInput; // on input
public AsioBool isActive; // on exit
public int channelGroup; // dto
public AsioSampleType type; // dto
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string name; // dto
}
public struct AsioBufferInfo
{
public AsioBool isInput; // on input: ASIOTrue: input, else output
public int channelNum; // on input: channel index
public IntPtr buffers1; // on output: double buffer addresses
public IntPtr buffers2; // on output: double buffer addresses
}
public enum AsioTimeInfoFlags: uint
{
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
}
public struct AsioTimeInfo
{
public double speed; // absolute speed (1. =
nominal)
public 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()
public AsioSamples samplePosition;
public double sampleRate; // current rate
public uint flags; // (see below)
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=12)]
public string reserved; // for user selection
}
public enum AsioTimeCodeFlags : uint
{
kTcValid = 1,
kTcRunning = 1 << 1,
kTcReverse = 1 << 2,
kTcOnspeed = 1 << 3,
kTcStill = 1 << 4,
kTcSpeedValid = 1 << 8
}
public struct AsioTimeCode
{
public double speed; // speed relation (fraction
of nominal speed)
// optional; set to 0. or
1. if not supported
public AsioSamples timeCodeSamples; // time in samples
public uint flags; // some information flags
(see below)
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=64)]
public string future; //
}
public struct AsioTime // both input/output
{
public int reserved1; // must be 0
public int reserved2; // must be 0
public int reserved3; // must be 0
public int reserved4; // must be 0
public AsioTimeInfo timeInfo; // required
public AsioTimeCode timeCode; // optional, evaluated if
(timeCode.flags & kTcValid)
}
public enum AsioMessageSelectors: int
{
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
}
public delegate void AsioBufferSwitchDelegate(int doubleBufferIndex,
AsioBool directProcess);
public delegate void AsioSampleRateDidChangeDelegate(double sRate);
public delegate void AsioMessageDelegate(int selector, int value, IntPtr
message, ref double opt);
public delegate AsioTime AsioBufferSwitchTimeInfoDelegate(ref AsioTime
times, int doubleBufferIndex, AsioBool directProcess);
public struct AsioCallbacks
{
public AsioBufferSwitchDelegate BufferSwitch;
//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.
public AsioSampleRateDidChangeDelegate SampleRateDidChange;
//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).
public AsioMessageDelegate Message;
//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
public AsioBufferSwitchTimeInfoDelegate BufferSwitchTimeInfo;
//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.
}
Ben Voigt [C++ MVP] - 09 Jun 2007 18:22 GMT
>I would greatly appreciate anyone that can help me with the proper way to
> declare this interface?
[quoted text clipped - 81 lines]
> delta1010.init(this.Handle); <<<--- this throws protected memory access
> violation
what is "this.Handle"? Is this code inside a Windows.Forms object?
You will need to refer to the documentation for the component, a "sysHandle"
is almost certainly entirely different from an "HWND".
> int ver = delta1010.getDriverVersion();
> Console.WriteLine(ver);
[quoted text clipped - 276 lines]
> // the driver calls asioMessage with selector kAsioSupportsTimeInfo.
> }