Code: Select all
;:=============================================================================
;:- PB_Asio.pb
;:- Author : Eric Nassen (www.raxntrax.com) / (www.raxntrax.com/modulys)
;:- Date : August 21, 2013
;:- Compiler : PureBasic 4.31
;:- Target OS : Windows x32, x64
;:=============================================================================
;x32 uses asm to call driver (because of thiscall convention), x64 uses the interface
CompilerIf SizeOf(Integer)=4
#Asio_Native=1
CompilerElse
#Asio_Native=0
CompilerEndIf
#Stop=0
#Start=1
#TM_Refresh=0
#EngineOn=1
#Debug=0
#WindowDevice=0
#Gain8=127
#Gain16=32767
#Gain24=8388607
#Gain32=2147483648 - 0.5
#kMaxInputChannels=32
#kMaxOutputChannels=32
#ASIO_PATH = "software\ASIO"
#ERROR_NO_MORE_ITEMS = 259
#HKEY_LOCAL_MACHINE = $80000002
#KEY_ENUMERATE_SUB_KEYS = $8
#WM_ASIO = #WM_USER + 4096; // unique we hope
#WM_ASIO_Reset=#WM_ASIO+1
Enumeration
#ASE_OK = 0
#ASE_SUCCESS = $3F4847A0
#ASE_NotPresent = -1000
#ASE_HWMalfunction
#ASE_InvalidParameter
#ASE_InvalidMode
#ASE_SPNotAdvancing
#ASE_NoClock
#ASE_NoMemory
EndEnumeration
Enumeration
#ASIOSTInt16MSB = 0
#ASIOSTInt24MSB = 1
#ASIOSTInt32MSB = 2
#ASIOSTFloat32MSB = 3
#ASIOSTFloat64MSB = 4
#ASIOSTInt32MSB16 = 8
#ASIOSTInt32MSB18 = 9
#ASIOSTInt32MSB20 = 10
#ASIOSTInt32MSB24 = 11
#ASIOSTInt16LSB = 16
#ASIOSTInt24LSB = 17
#ASIOSTInt32LSB = 18
#ASIOSTFloat32LSB = 19
#ASIOSTFloat64LSB = 20
#ASIOSTInt32LSB16 = 24
#ASIOSTInt32LSB18 = 25
#ASIOSTInt32LSB20 = 26
#ASIOSTInt32LSB24 = 27
EndEnumeration
Enumeration
#kAsioSelectorSupported = 1
#kAsioEngineVersion = 2
#kAsioResetRequest = 3
#kAsioBufferSizeChange = 4
#kAsioResyncRequest = 5
#kAsioLatenciesChanged = 6
#kAsioSupportsTimeInfo = 7
#kAsioSupportsTimeCode = 8
#kAsioSupportsInputMonitor = 9
#kAsioNumMessageSelectors = 10
EndEnumeration
Enumeration
#kTcValid = 1;
#kTcRunning = 1 << 1;
#kTcReverse = 1 << 2;
#kTcOnspeed = 1 << 3;
#kTcStill = 1 << 4;
#kTcSpeedValid = 1 << 8;
EndEnumeration
Enumeration
#kSystemTimeValid = 1
#kSamplePositionValid = 1 << 1
#kSampleRateValid = 1 << 2
#kSpeedValid = 1 << 3
#kSampleRateChanged = 1 << 4
#kClockSourceChanged = 1 << 5
EndEnumeration
;Following can be changed (backwards compatibility)
Structure MyDouble
HI.l
Lo.l
EndStructure
Structure ASIOInt64
HI.l
Lo.l
EndStructure
Structure ASIOTimeStamp
HI.l
Lo.l
EndStructure
Structure ASIO64bitFloat
HI.l
Lo.l
EndStructure
Structure ASIOSampleRate
HI.l
Lo.l
EndStructure
Structure ASIOBool
l.l
EndStructure
Structure ASIOSamples
HI.l
Lo.l
EndStructure
Structure ASIOTimeCodeFlags
l.l
EndStructure
Structure AsioTimeInfoFlags
l.l
EndStructure
; --------------------------------------
;Engine simulation....
Structure ENG
Pause.b
BufferIndex.l
SampleRate.d
BlockSize.l
AsioReset.b
EndStructure
Interface IOpenAsio Extends iunknown
Init(sysHandle)
GetDriverName(*Name)
GetDriverVersion()
GetErrorMessage(*errorStrings)
Start()
Stop()
GetChannels(*numInputChannels, *numOutputChannels)
GetLatencies(inputLatency, outputLatency)
GetBufferSize(minSize, maxSize, preferredSize, granularity)
CanSampleRate(dbl.d)
GetSampleRate(*dbl)
SetSampleRate(dbl.d)
GetClockSources(clocks,numSources)
SetClockSource(reference)
GetSamplePosition(sPos,tStamp)
GetChannelInfo(info)
CreateBuffers(bufferInfos, numChannels, bufferSize,callbacks)
DisposeBuffers()
ControlPanel()
Future(selector,opt)
OutputReady()
EndInterface
Structure ASIOCallbacks
bufferSwitch.i
sampleRateDidChange.i
asioMessage.i
bufferSwitchTimeInfo.i
EndStructure
Structure AsioBufferInfo
isInput.l
channelNum.l
buffers.i[2]
EndStructure
Structure ASIOChannelInfo
channel.l
isInput.l
isActive.l
channelGroup.l
vType.l
Name.c[32]
EndStructure
Structure ASIOTimeCode
speed.MyDouble
timecodeSamples.ASIOSamples
flags.l
future.c[64]
EndStructure
Structure AsioTimeInfo
speed.MyDouble
SystemTime.ASIOTimeStamp
samplePosition.ASIOSamples
SampleRate.ASIOSampleRate
flags .l
reserved.c[12]
EndStructure
Structure ASIOTime
reserved.l[4]
timeInfo.AsioTimeInfo
timeCode.ASIOTimeCode
EndStructure
;User defined driver (can be changed)
Structure AsioDriver
inputChannels.i
outputChannels.i
channelInfos.ASIOChannelInfo[#kMaxInputChannels+#kMaxOutputChannels]
inputBuffers.l
outputBuffers.l
bufferInfos.AsioBufferInfo[#kMaxInputChannels+#kMaxOutputChannels]
minSize.l
maxSize.l
preferredSize.l
granularity.l
SampleRate.d
postOutput.l
inputLatency.l
outputLatency.l
nanoSeconds.d
samples.d
tcSamples.d
tInfo.ASIOTime
sysRefTime.l
stopped.l
ActiveInput.l
ActiveOutput.l
EndStructure
Structure AsioStruct
DeviceID.l
AsioName$
CLSID$
DLLName$
EndStructure
;Quick 'n dirty.....
Global AsioTime.ASIOTime
Global _IAsio.IOpenAsio
Global AsioDriver.AsioDriver
Global callbacks.ASIOCallbacks
Global gDeviceID=-1
Global gAsioState
Global gTicks.l
Global Eng_Event.l
Global NewList AsioDeviceInfo.AsioStruct()
Global Eng.ENG
Eng\SampleRate=44100
Eng\BlockSize=512
Procedure myTimerCB(hwnd,uMsg,idEvent,dwTime)
if AsioTime and gAsioState=#Start
SetGadgetText(2,Str(AsioTime\timeInfo\samplePosition\HI)+"/"+Str(AsioTime\timeInfo\samplePosition\Lo))
else
SetGadgetText(2,"Sampleposition")
EndIf
EndProcedure
Procedure FillAsioDeviceInfo()
hKey = 0 : count.l = 0
buffer$=Space(1024)
If RegOpenKeyEx_(#HKEY_LOCAL_MACHINE, #ASIO_PATH,0, #KEY_ALL_ACCESS,@hKey)=#ERROR_SUCCESS
buffsize=255
index=0
While RegEnumKeyEx_ (hKey, index, @buffer$, @buffsize, #Null, #Null, #Null, @written.SYSTEMTIME)<>#ERROR_NO_MORE_ITEMS
AsioName$ = Left(buffer$,buffsize)
hKey2 = 0
If RegOpenKeyEx_(#HKEY_LOCAL_MACHINE, #ASIO_PATH+"\"+AsioName$, 0, #KEY_READ, @hKey2)=0
DataSize = 255
If RegQueryValueEx_(hKey2, "CLSID", 0, 0, @buffer$, @DataSize)=0
CLSID$ = Left(buffer$, DataSize - 1)
hKey3=0
If RegOpenKeyEx_(#HKEY_CLASSES_ROOT, "clsid"+"\"+CLSID$+"\"+"InprocServer32", 0, #KEY_READ, @hKey3)=0
buffsize=255
If RegQueryValueEx_(hKey3, "", 0, 0, @buffer$, @buffsize)=0
DLLName$=Left(buffer$,buffsize)
lSize=FileSize(DLLName$)
If lSize=-1
lLen=GetSystemDirectory_(@buffer$,255)
szDir.s=Left(buffer$,lLen)
DLLName$=szDir+"\"+DLLName$
lSize=FileSize(DLLName$)
EndIf
If lSize>0
AddElement(AsioDeviceInfo())
AsioDeviceInfo()\DeviceID=count
AsioDeviceInfo()\AsioName$=AsioName$
AsioDeviceInfo()\CLSID$=CLSID$
AsioDeviceInfo()\DLLName$=DLLName$
count+1
EndIf
EndIf
RegCloseKey_(hKey3)
EndIf
EndIf
RegCloseKey_(hKey2)
EndIf
index+1
buffsize = 255
Wend
RegCloseKey_(hKey)
EndIf
EndProcedure
Procedure WideStr(pointer)
widelen.w = 2*Len(PeekS(pointer))+2
widebuf.i = AllocateMemory(widelen)
longlen.w = MultiByteToWideChar_(#CP_ACP,0,pointer,-1,widebuf,widelen)
ProcedureReturn widebuf
EndProcedure
;Interface
Procedure _Asio_Release()
CompilerIf #ASIO_NATIVE
! mov eax, [v__IAsio]
! push eax
! mov ecx, dword [v__IAsio]
! mov eax, [ecx]
! call dword [eax+8]
CompilerElse
_IAsio\Release()
CompilerEndIf
EndProcedure
Procedure _Asio_Init(sysHandle)
Result=0
CompilerIf #ASIO_NATIVE
! mov eax, [p.v_sysHandle]
! push eax
! mov ecx, dword [v__IAsio]
! mov eax, [ecx]
! call dword [eax+12]
! mov [p.v_Result], eax
CompilerElse
Result=_IAsio\Init(sysHandle)
CompilerEndIf
ProcedureReturn Result
EndProcedure
Procedure _Asio_GetDriverName(*char)
Result=0
CompilerIf #ASIO_NATIVE
! mov eax, [p.p_char]
! push eax
! mov ecx, dword [v__IAsio]
! mov eax, [ecx]
! call dword [eax+16]
! mov [p.v_Result], eax
CompilerElse
Result=_IAsio\GetDriverName(*char)
CompilerEndIf
ProcedureReturn Result
EndProcedure
Procedure _Asio_GetDriverVersion()
Result=0
CompilerIf #ASIO_NATIVE
! mov ecx, dword [v__IAsio]
! mov eax, [ecx]
! call dword [eax+20]
! mov [p.v_Result], eax
CompilerElse
Result=_IAsio\GetDriverVersion()
CompilerEndIf
ProcedureReturn Result
EndProcedure
Procedure _Asio_getErrorMessage(*char)
Result=0
CompilerIf #ASIO_NATIVE
! mov eax, [p.p_char]
! push eax
! mov ecx, dword [v__IAsio]
! mov eax, [ecx]
! call dword [eax+24]
! mov [p.v_Result], eax
CompilerElse
Result=_IAsio\getErrorMessage(*char)
CompilerEndIf
ProcedureReturn Result
EndProcedure
Procedure _Asio_Start()
Result=0
CompilerIf #ASIO_NATIVE
! mov ecx, dword [v__IAsio]
! mov eax, [ecx]
! call dword [eax+28]
! mov [p.v_Result], eax
CompilerElse
Result=_IAsio\Start()
CompilerEndIf
ProcedureReturn Result
EndProcedure
Procedure _Asio_Stop()
Result=0
CompilerIf #ASIO_NATIVE
! mov ecx, dword [v__IAsio]
! mov eax, [ecx]
! call dword [eax+32]
! mov [p.v_Result], eax
CompilerElse
Result=_IAsio\Stop()
CompilerEndIf
ProcedureReturn Result
EndProcedure
Procedure _Asio_GetChannels(*inputChannels, *outputChannels)
Result=0
CompilerIf #ASIO_NATIVE
! mov eax, [p.p_outputChannels]
! push eax
! mov eax, [p.p_inputChannels+4]
! push eax
! mov ecx, dword [v__IAsio]
! mov eax, [ecx]
! call dword [eax+36]
! mov [p.v_Result], eax
CompilerElse
Result=_IAsio\GetChannels(*inputChannels, *outputChannels)
CompilerEndIf
ProcedureReturn Result
EndProcedure
Procedure _Asio_GetLatencies(*inputLatency, *outputLatency)
Result=0
CompilerIf #ASIO_NATIVE
! mov eax, [p.p_outputLatency]
! push eax
! mov eax, [p.p_inputLatency+4]
! push eax
! mov ecx, dword [v__IAsio]
! mov eax, [ecx]
! call dword [eax+40]
! mov [p.v_Result], eax
CompilerElse
Result=_IAsio\GetLatencies(*inputLatency, *outputLatency)
CompilerEndIf
ProcedureReturn Result
EndProcedure
Procedure _Asio_GetBufferSize(*minSize, *maxSize, *preferredSize, *granularity)
Result=0
CompilerIf #ASIO_NATIVE
! mov eax, [p.p_granularity]
! push eax
! mov eax, [p.p_preferredSize+4]
! push eax
! mov eax, [p.p_maxSize+8]
! push eax
! mov eax, [p.p_minSize+12]
! push eax
! mov ecx, [v__IAsio]
! mov eax, [ecx]
! call dword [eax+44]
! mov [p.v_Result], eax
CompilerElse
Result=_IAsio\GetBufferSize(*minSize, *maxSize, *preferredSize, *granularity)
CompilerEndIf
procedurereturn Result;
EndProcedure
Procedure _Asio_CanSampleRate(sampleRate.d)
Result=0
CompilerIf #ASIO_NATIVE
*sampleRate_=@sampleRate
! mov eax, [p.p_sampleRate_]
! push dword [eax+4]
! push dword [eax]
! mov ecx, [v__IAsio]
! mov eax, [ecx]
! call dword [eax+48]
! mov [p.v_Result], eax
CompilerElse
Result=_IAsio\CanSampleRate(sampleRate.d)
CompilerEndIf
procedurereturn Result;
EndProcedure
Procedure _Asio_GetSampleRate(*sampleRate)
Result=0
CompilerIf #ASIO_NATIVE
! mov eax, [p.p_sampleRate]
! push eax
! mov ecx, [v__IAsio]
! mov eax, [ecx]
! call dword [eax+52]
! mov [p.v_Result], eax
CompilerElse
Result=_IAsio\GetSampleRate(*sampleRate)
CompilerEndIf
procedurereturn Result;
EndProcedure
Procedure _Asio_SetSampleRate(sampleRate.d)
Result=0
CompilerIf #ASIO_NATIVE
*sampleRate_=@sampleRate
! mov eax, [p.p_sampleRate_]
! push dword [eax+4]
! push dword [eax]
! mov ecx, [v__IAsio]
! mov eax, [ecx]
! call dword [eax+56]
! mov [p.v_Result], eax
CompilerElse
Result=_IAsio\SetSampleRate(sampleRate.d)
CompilerEndIf
procedurereturn Result;
EndProcedure
Procedure _Asio_GetClockSources(*Clocks, *numSources)
Result=0
CompilerIf #ASIO_NATIVE
! mov eax, [p.p_numSources]
! push eax
! mov eax, [p.p_Clocks]
! push eax
! mov ecx, dword [v__IAsio]
! mov eax, [ecx]
! call dword [eax+60]
! mov [p.v_Result], eax
CompilerElse
Result=_IAsio\GetClockSources(*Clocks, *numSources)
CompilerEndIf
ProcedureReturn Result
EndProcedure
Procedure _Asio_SetClockSource(reference.l)
Result=0
CompilerIf #ASIO_NATIVE
! mov eax, [p.v_reference]
! push eax
! mov ecx, dword [v__IAsio]
! mov eax, [ecx]
! call dword [eax+64]
! mov [p.v_Result], eax
CompilerElse
Result=_IAsio\SetClockSource(reference)
CompilerEndIf
ProcedureReturn Result
EndProcedure
Procedure _Asio_GetSamplePosition(*sPos, *tStamp)
Result=0
CompilerIf #ASIO_NATIVE
! mov eax, [p.p_tStamp]
! push eax
! mov eax, [p.p_sPos+4]
! push eax
! mov ecx, dword [v__IAsio]
! mov eax, [ecx]
! call dword [eax+68]
! mov [p.v_Result], eax
CompilerElse
Result=_IAsio\GetSamplePosition(*sPos, *tStamp)
CompilerEndIf
procedurereturn Result
EndProcedure
Procedure _Asio_GetChannelInfo(*info)
Result=0
CompilerIf #ASIO_NATIVE
! mov eax, [p.p_info]
! push eax
! mov ecx, [v__IAsio]
! mov eax, [ecx]
! call dword [eax+72]
! mov [p.v_Result], eax
CompilerElse
Result=_IAsio\GetChannelInfo(*info)
CompilerEndIf
procedurereturn Result;
EndProcedure
Procedure _Asio_CreateBuffers(*bufferInfos, numChannels.l, bufferSize.l, *callbacks)
Result=0
CompilerIf #ASIO_NATIVE
! mov eax, [p.p_callbacks]
! push eax
! mov eax, [p.v_bufferSize+4]
! push eax
! mov eax, [p.v_numChannels+8]
! push eax
! mov eax, [p.p_bufferInfos+12]
! push eax
! mov ecx, [v__IAsio]
! mov eax, [ecx]
! call dword [eax+76]
! mov [p.v_Result], eax
procedurereturn Result
CompilerElse
Result=_IAsio\CreateBuffers(*bufferInfos, numChannels, bufferSize, *callbacks)
CompilerEndIf
procedurereturn Result;
EndProcedure
Procedure _Asio_DisposeBuffers()
Result=0
CompilerIf #ASIO_NATIVE
! mov ecx, dword [v__IAsio]
! mov eax, [ecx]
! call dword [eax+80]
! mov [p.v_Result], eax
CompilerElse
Result=_IAsio\DisposeBuffers()
CompilerEndIf
ProcedureReturn Result
EndProcedure
Procedure _Asio_controlPanel()
Result=0
CompilerIf #ASIO_NATIVE
! mov ecx, dword [v__IAsio]
! mov eax, [ecx]
! call dword [eax+84]
! mov [p.v_Result], eax
CompilerElse
Result=_IAsio\controlPanel()
CompilerEndIf
ProcedureReturn Result
EndProcedure
Procedure _Asio_OutputReady()
Result=0
CompilerIf #ASIO_NATIVE
! mov ecx, dword [v__IAsio]
! mov eax, [ecx]
! call dword [eax+92]
! mov [p.v_Result], eax
CompilerElse
Result=_IAsio\OutputReady()
CompilerEndIf
ProcedureReturn Result
EndProcedure
Procedure BufferSwitchTimeInfo(lBufferNumber.l,*AsioTime.ASIOTime)
Eng\BufferIndex=lBufferNumber
;AudioIn
Select AsioDriver\channelInfos[AsioDriver\ActiveInput]\vType
Case #ASIOSTInt16LSB
wSample.w=PeekW(AsioDriver\bufferInfos[AsioDriver\ActiveInput]\buffers[Eng\BufferIndex])
Case #ASIOSTInt32LSB
lSample.l=PeekL(AsioDriver\bufferInfos[AsioDriver\ActiveInput]\buffers[Eng\BufferIndex])
EndSelect
If Eng\Pause=0
;here comes code to generate output
;fill outputbuffers
Select AsioDriver\channelInfos[AsioDriver\ActiveOutput]\vType
Case #ASIOSTInt16LSB
For j = 0 To Eng\BlockSize-1
Next
Case #ASIOSTInt32LSB
For j = 0 To Eng\BlockSize-1
Next
Case #ASIOSTFloat32LSB
;..........
EndSelect
EndIf
Tag_Asio_Ready:
If AsioDriver\postOutput
_Asio_OutputReady() ; // some asio drivers require this
EndIf
EndProcedure
ProcedureCDLL.l AsioBufferSwitchTimeInfo(*AsioTime.ASIOTime,doubleBufferIndex.l,directProcess.l) ;: PASIOTime; cdecl;
Select directProcess
Case #False
;PostMessage_(WindowID(#WindowDevice), #WM_ASIO, doubleBufferIndex,*AsioTime);
;or setevent_() or .....
Case #True
BufferSwitchTimeInfo(doubleBufferIndex, *AsioTime);
EndSelect
ProcedureReturn 0
EndProcedure
ProcedureCDLL AsioBufferSwitch(doubleBufferIndex.l,directProcess.l)
If _Asio_GetSamplePosition(@AsioTime\timeInfo\samplePosition, @AsioTime\timeInfo\SystemTime) = #ASE_OK
AsioTime\timeInfo\flags = #kSystemTimeValid | #kSamplePositionValid
EndIf
Select directProcess
Case #False
;PostMessage_(WindowID(#WindowDevice), #WM_ASIO, doubleBufferIndex,#Null);
Case #True
BufferSwitchTimeInfo(doubleBufferIndex, AsioTime);
EndSelect
EndProcedure
ProcedureCDLL.l AsioMessage(selector.l, Value.l, *message, *opt.MyDouble) ;: longint; cdecl;
CompilerIf #Debug:ShowSelector(selector,Value):CompilerEndIf
Result = 0
;ShowSelector(selector)
Select selector
Case #kAsioSelectorSupported
Select Value
Case #kAsioEngineVersion : Result = 1
Case #kAsioResetRequest : Result = 1
Case #kAsioBufferSizeChange : Result = 0
Case #kAsioResyncRequest : Result = 1
Case #kAsioLatenciesChanged : Result = 1
Case #kAsioSupportsTimeInfo : Result = 1
Case #kAsioSupportsTimeCode : Result = 0
Case #kAsioSupportsInputMonitor : Result = 0
EndSelect
Case #kAsioEngineVersion
Result=2
Case #kAsioResetRequest
Eng\AsioReset=2
PostMessage_(WindowID(#WindowDevice),#WM_ASIO_Reset,0,0)
Result=1
Case #kAsioBufferSizeChange
Eng\AsioReset=1
PostMessage_(WindowID(#WindowDevice),#WM_ASIO_Reset,0,0)
Result=1
Case #kAsioResyncRequest
Eng\AsioReset=2
PostMessage_(WindowID(#WindowDevice),#WM_ASIO_Reset,0,0)
Result=1
Case #kAsioLatenciesChanged
Eng\AsioReset=1
PostMessage_(WindowID(#WindowDevice),#WM_ASIO_Reset,0,0)
Result=1
Case #kAsioSupportsTimeInfo
Result=1
Case #kAsioSupportsTimeCode
Case #kAsioSupportsInputMonitor
EndSelect
ProcedureReturn Result
EndProcedure
ProcedureCDLL AsioSampleRateDidChange(sRateHI.l, sRateLO.l)
EndProcedure
Procedure.l Asio_static_data()
YnSampleRateOK=0
If _Asio_GetChannels(@AsioDriver\inputChannels, @AsioDriver\outputChannels)=#ASE_OK
If _Asio_GetBufferSize(@AsioDriver\minSize, @AsioDriver\maxSize, @AsioDriver\preferredSize, @AsioDriver\granularity) = #ASE_OK
If _Asio_GetSampleRate(@AsioDriver\SampleRate) = #ASE_OK
If Eng\SampleRate=44100 Or Eng\SampleRate=48000 Or Eng\SampleRate=96000
;Force to Engine Samplerate
If _Asio_CanSampleRate(Eng\SampleRate) = #ASE_OK
If _Asio_SetSampleRate(Eng\SampleRate) = #ASE_OK
If _Asio_GetSampleRate(@AsioDriver\SampleRate) = #ASE_OK
EndIf
EndIf
EndIf
EndIf
If AsioDriver\SampleRate <= 0 Or AsioDriver\SampleRate > 96000
;Try 44100
If _Asio_CanSampleRate(44100) = #ASE_OK
If _Asio_SetSampleRate(44100) = #ASE_OK
If _Asio_GetSampleRate(@AsioDriver\SampleRate) = #ASE_OK
YnSampleRateOK=1
EndIf
EndIf
EndIf
If YnSampleRateOK=0
If _Asio_CanSampleRate(48000) = #ASE_OK
If _Asio_SetSampleRate(48000) = #ASE_OK
If _Asio_GetSampleRate(@AsioDriver\SampleRate) = #ASE_OK
YnSampleRateOK=1
EndIf
EndIf
EndIf
EndIf
Else
YnSampleRateOK=1
EndIf
EndIf
If _Asio_OutputReady() = #ASE_OK
AsioDriver\postOutput = #True
Else
AsioDriver\postOutput = #False
EndIf
EndIf
EndIf
If YnSampleRateOK
ProcedureReturn 0
Else
ProcedureReturn 1
EndIf
tag_end:
EndProcedure
Procedure.l Asio_create_buffers()
; // fill the bufferInfos from the start without a gap
*info.AsioBufferInfo = @AsioDriver\bufferInfos;
; Inputs
If AsioDriver\inputChannels > #kMaxInputChannels
AsioDriver\inputBuffers = #kMaxInputChannels;
Else
AsioDriver\inputBuffers = AsioDriver\inputChannels
EndIf
AsioDriver\ActiveInput=0
AsioDriver\ActiveOutput=AsioDriver\inputBuffers
For i = 0 To AsioDriver\inputBuffers-1
*info\isInput = #True
*info\channelNum = i
*info\buffers[0] = 0
*info\buffers[1] = 0
*info+SizeOf(AsioBufferInfo)
Next
; Outputs
If AsioDriver\outputChannels > #kMaxOutputChannels
AsioDriver\outputBuffers = #kMaxOutputChannels
Else
AsioDriver\outputBuffers = AsioDriver\outputChannels
EndIf
For i = 0 To AsioDriver\outputBuffers-1
*info\isInput = #False
*info\channelNum = i
*info\buffers[0] = 0
*info\buffers[1] = 0;
*info+SizeOf(AsioBufferInfo)
Next
Result=_Asio_CreateBuffers(@AsioDriver\bufferInfos, AsioDriver\inputBuffers + AsioDriver\outputBuffers, AsioDriver\preferredSize, @callbacks)
If Result=#ASE_OK
For i = 0 To AsioDriver\inputBuffers + AsioDriver\outputBuffers -1
AsioDriver\channelInfos[i]\channel = AsioDriver\bufferInfos[i]\channelNum
AsioDriver\channelInfos[i]\isInput = AsioDriver\bufferInfos[i]\isInput
Result = _Asio_GetChannelInfo(@AsioDriver\channelInfos[i])
If Result<>#ASE_OK
;Break
Else
EndIf
Next
If Result=#ASE_OK
Result=_Asio_GetLatencies(@AsioDriver\inputLatency, @AsioDriver\outputLatency)
EndIf
EndIf
;AudioIn
Select AsioDriver\channelInfos[AsioDriver\ActiveInput]\vType
Case #ASIOSTInt16LSB
Case #ASIOSTInt32LSB
EndSelect
ProcedureReturn Result
EndProcedure
Procedure ASIO_Open()
SelectElement(AsioDeviceInfo(),gDeviceID)
sCLSID.s = AsioDeviceInfo()\CLSID$
Err.l=CLSIDFromString_(WideStr(@sCLSID),@clsid.GUID)
CoInitialize_(0);
CoCreateInstance_(@CLSID, #Null, 1, @CLSID, @_IAsio)
hWnd=WindowID(#WindowDevice)
Retval= _Asio_Init(hwnd)
if RetVal
If Asio_static_data() = 0
callbacks\bufferSwitch = @AsioBufferSwitch()
callbacks\sampleRateDidChange = @AsioSampleRateDidChange()
callbacks\asioMessage = @AsioMessage()
callbacks\bufferSwitchTimeInfo = @AsioBufferSwitchTimeInfo()
If Asio_create_buffers()=#ASE_OK
Eng\BlockSize=AsioDriver\preferredSize
Eng\SampleRate=AsioDriver\SampleRate
If #EngineOn
If _Asio_Start()=#ASE_OK
Else
MessageRequester("Asio","Driver could not be started",#MB_TOPMOST)
EndIf
EndIf
Else
MessageRequester("Asio","Unable to create the buffers",#MB_TOPMOST)
EndIf
EndIf
EndIf
EndProcedure
Procedure ASIO_Close()
Eng\Pause=1
If _Asio_Stop()=#ASE_OK
If _Asio_DisposeBuffers()=#ASE_OK
AsioDriver\stopped=1
EndIf
EndIf
_Asio_release()
_IAsio=0
CoUninitialize_()
EndProcedure
Procedure.s Info_Refresh()
With AsioDriver
info$="Driver info"+chr(13)+chr(13)
info$=info$+"inputChannels="+str(\inputChannels)+chr(13)
info$=info$+"outputChannels="+str(\outputChannels)+chr(13)
info$=info$+"minSize="+str(\minSize)+chr(13)
info$=info$+"maxsize="+str(\maxSize)+chr(13)
info$=info$+"preferredSize="+str(\preferredSize)+chr(13)
info$=info$+"granularity="+str(\granularity)+chr(13)
info$=info$+"samplerate="+StrD(\SampleRate)+chr(13)
info$=info$+"postoutput="+str(\postOutput)+chr(13)
info$=info$+"inputLatency="+str(\inputLatency)+chr(13)
info$=info$+"outputLatency="+str(\outputLatency)
EndWith
ProcedureReturn info$
EndProcedure
FillAsioDeviceInfo()
;Quick 'n dirty window implementation ;-)
OpenWindow(0,0,0,620,280,"Select Asio device",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
SetTimer_(WindowID(#WindowDevice),#TM_Refresh,25,@myTimerCB())
ListViewGadget(0,10,10,300,200)
ButtonGadget(1,10,220,300,25,"Start Asio device")
TextGadget(2,10,250,150,25,"Sampleposition")
TextGadget(3,320,10,300,180,"")
ButtonGadget(4,170,250,130,25,"Control Panel")
ResetList(AsioDeviceInfo()) : i = 0 :gDeviceID=-1
While NextElement(AsioDeviceInfo())
AddGadgetItem(0,-1,AsioDeviceInfo()\AsioName$)
i+1
Wend
repeat
ev=WaitWindowEvent()
if ev=#PB_Event_Gadget
Select EventGadget()
case 0
if gDeviceID<>GetGadgetState(0)
if gAsioState=#Start
ASIO_Close()
gAsioState=#Stop
SetGadgetText(1,"Start Asio device")
SetGadgetText(2,"Sampleposition")
SetGadgetText(3,"")
EndIf
gDeviceID=GetGadgetState(0)
EndIf
Case 1
if gAsioState=#Stop
if gDeviceID>=0
ASIO_Open()
gAsioState=#Start
SetGadgetText(1,"Stop Asio device")
SetGadgetText(3,Info_Refresh())
EndIf
else
ASIO_Close()
gAsioState=#Stop
SetGadgetText(1,"Start Asio device")
SetGadgetText(2,"Sampleposition")
SetGadgetText(3,"")
endif
Case 4
if gAsioState=#Start
_Asio_controlPanel()
EndIf
EndSelect
EndIf
if ev=#WM_ASIO_Reset
if gAsioState=#Start
Asio_close()
Eng\AsioReset=0
Asio_open()
SetGadgetText(3,Info_Refresh())
EndIf
EndIf
until ev=#PB_Event_CloseWindow
if gAsioState=#Start
Asio_close()
EndIf