Ben Voigt [C++ MVP]
6/10/2007 5:19:00 PM
"Jeff M" <JeffM@discussions.microsoft.com> wrote in message
news:4B4071F0-3A34-4547-B4F8-9BA0C19A09FA@microsoft.com...
>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
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);
>
>
>
>
> 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.
> }
>
>