It is currently Tue Jul 14, 2020 12:47 am

All times are UTC + 1 hour




Post new topic Reply to topic  [ 11 posts ] 
Author Message
 Post subject: PB Asio
PostPosted: Wed Aug 21, 2013 9:16 am 
Offline
Enthusiast
Enthusiast

Joined: Wed Mar 17, 2004 12:31 am
Posts: 277
Feel free to update the code to 5.20 (I still use 4.31)...

Code:
;:=============================================================================
;:- 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


Top
 Profile  
Reply with quote  
 Post subject: Re: PB Asio
PostPosted: Wed Aug 21, 2013 4:18 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sat Jun 24, 2006 3:29 am
Posts: 244
Location: Edinburgh, Scotland.
Great! Thanx for posting this. :D

_________________
Proud supporter of PB! * Musician * C64/6502 Freak


Top
 Profile  
Reply with quote  
 Post subject: Re: PB Asio
PostPosted: Sun Sep 01, 2013 2:02 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Mon Jan 12, 2004 11:40 pm
Posts: 769
Location: Okazaki, JAPAN
Nice, thanks.

How output samples?

I want to Raw outputs ASIO library. then, use BASS ASIO.

TUSBAudio ASIO Driver
Quote:
Driver info

inputChannels=2
outputChannels=2
minSize=272
maxsize=272
preferredSize=272
granularity=0
samplerate=44100
postoutput=0
inputLatency=448
outputLatency=448

_________________
My homepage in Japan - Bug head Nontallion
My facebook page.


Top
 Profile  
Reply with quote  
 Post subject: Re: PB Asio
PostPosted: Mon Sep 02, 2013 12:20 pm 
Offline
Enthusiast
Enthusiast

Joined: Wed Mar 17, 2004 12:31 am
Posts: 277
oryaaaaa wrote:
Nice, thanks.
How output samples?


see procedure "BufferSwitchTimeInfo"


Top
 Profile  
Reply with quote  
 Post subject: Re: PB Asio
PostPosted: Sun Sep 15, 2013 9:11 am 
Offline
Addict
Addict
User avatar

Joined: Wed Jun 11, 2003 9:33 pm
Posts: 4625
Location: Spa, relaxing and thinking, and learning...
Thanks :!: :wink:

_________________
http://www.zeitgeistmovie.com

While world=business:world+mafia:Wend


Top
 Profile  
Reply with quote  
 Post subject: Re: PB Asio
PostPosted: Wed Aug 20, 2014 6:40 am 
Offline
User
User

Joined: Tue Apr 13, 2010 5:39 am
Posts: 32
Код работает прекрасно, но без прав администратора не определяет что есть АСИО. Следующий код исправляет недочет. Может я не прав?


The code works fine, but without administrative rights does not define what is ASIO. The following code corrects the defect. Maybe I'm wrong?

(line 279)
Code:
RegOpenKeyEx_(#HKEY_LOCAL_MACHINE, #ASIO_PATH+"\"+AsioName$, 0, #KEY_READ, @hKey2)=0


Last edited by cherri123 on Wed Aug 20, 2014 10:21 am, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: PB Asio
PostPosted: Wed Aug 20, 2014 10:16 am 
Offline
Enthusiast
Enthusiast

Joined: Tue May 26, 2009 2:11 pm
Posts: 651
cherri123 wrote:
Код работает прекрасно, но без прав администратора не определяет что есть АСИО. Следующий код исправляет недочет. Может я не прав?
Rembrand?

_________________
Image


Top
 Profile  
Reply with quote  
 Post subject: Re: PB Asio
PostPosted: Fri Aug 22, 2014 8:37 am 
Offline
User
User

Joined: Mon Dec 24, 2012 9:07 am
Posts: 38
Location: Ukraine, Donetck
Very thanks eriansa!
You do not have the simplest code vst synth?

cherri123 wrote:
Код работает прекрасно, но без прав администратора не определяет что есть АСИО. Следующий код исправляет недочет. Может я не прав?


The code works fine, but without administrative rights does not define what is ASIO. The following code corrects the defect. Maybe I'm wrong?

(line 279)
Code:
RegOpenKeyEx_(#HKEY_LOCAL_MACHINE, #ASIO_PATH+"\"+AsioName$, 0, #KEY_READ, @hKey2)=0


You should have the asio driver.
Должен быть установлен asio драйвер.

_________________
Sory my bad english


Top
 Profile  
Reply with quote  
 Post subject: Re: PB Asio
PostPosted: Thu Aug 28, 2014 2:35 pm 
Offline
Addict
Addict

Joined: Mon Apr 28, 2003 2:22 pm
Posts: 942
Location: Europe
Thanks for sharing.
One question: Why do you use Enumeration if you assign the values by your own?

_________________
Tranquil


Top
 Profile  
Reply with quote  
 Post subject: Re: PB Asio
PostPosted: Wed Nov 26, 2014 12:23 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Mon Jan 12, 2004 11:40 pm
Posts: 769
Location: Okazaki, JAPAN
eriansa wrote:
oryaaaaa wrote:
Nice, thanks.
How output samples?


see procedure "BufferSwitchTimeInfo"


I am trying high quality asio output.
If you improve asio sound quality, should use follows tips.

my tips
1. Don't use MOVQ for write memory
2. Use MOVNTQ for write memory
3. Use mmx register for copy memory buffer

my code
Code:
Procedure CopyMemoryMMX(*memory_in, *memory_out, mem_size.i)
  Protected s.i ; this variable use interger for High quality sound
 
  If mem_size%8>0
    s = mem_size + ( 8 - mem_size%8 ) ; adjust align
  Else
    s = mem_size
  EndIf
 
  If s<1
    ProcedureReturn
  EndIf
 
  CompilerSelect #PB_Compiler_Processor
    CompilerCase #PB_Processor_x86
      !PXOR mm1, mm1
      !MOV Eax, [p.v_s]
      !MOV Ecx, [p.p_memory_in]
      !MOV Edx, [p.p_memory_out]
      !copy_mmx:
      !PXOR mm1, mm1
      !movq mm1, [Ecx]
      !movntq [Edx], mm1 ; don't use CPU cache
      !ADD  Ecx, 8
      !ADD  Edx, 8
      !SUB  Eax, 8
      !JNZ copy_mmx
      !emms
      ProcedureReturn
    CompilerCase #PB_Processor_x64
      !PXOR mm1, mm1
      !MOV Rax, [p.v_s]
      !MOV Rcx, [p.p_memory_in]
      !MOV Rdx, [p.p_memory_out]
      !copy_mmx:
      !PXOR mm1, mm1
      !movq mm1, [Rcx]
      !movntq [Rdx], mm1 ; don't use CPU cache
      !ADD  Rcx, 8
      !ADD  Rdx, 8
      !SUB  Rax, 8
      !JNZ copy_mmx
      !emms
      ProcedureReturn
  CompilerEndSelect
EndProcedure

_________________
My homepage in Japan - Bug head Nontallion
My facebook page.


Top
 Profile  
Reply with quote  
 Post subject: Re: PB Asio
PostPosted: Wed Mar 04, 2020 8:13 pm 
Offline
Enthusiast
Enthusiast

Joined: Wed Jul 12, 2006 4:38 pm
Posts: 420
Location: UK
Hi, can anyone help me get this running on PB 5.71 LTS? I get and invalid memory access at address 0 in the following procedure

Code:
Procedure _Asio_Init(sysHandle)
Result=0; <----- ERROR
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


The asio driver is listed. It dies when i click start asio device


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 11 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 40 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye