Page 1 of 1

VST Hosting: processing a .wav-file

Posted: Sat Jun 10, 2006 11:24 pm
by soerenkj
I am trying to make a VST host that will use a VST plugin to process a 44100, 16 bit, stereo .wav-file. However, when I call the plugin's standard method 'processReplacing()' the file does not seem to get processed correctly - with some plugins the sound gets distorted, with others processReplacing() never returns.

Can anybody see what I am doing wrong in the following code? (to run the code you need directx 8, a 2-input VST plugin and a 44100, 16 bit stereo .wav-file)

Code: Select all

#DSBLOCK_ENTIREBUFFER = $2

#audioMasterVersion = 1

Enumeration
	#effOpen             
	#effClose            
	#effSetProgram       
	#effGetProgram       
	#effSetProgramName   
	#effGetProgramName
	#effGetParamLabel    
	#effGetParamDisplay  
	#effGetParamName     
	#effGetVu            
	#effSetSampleRate    
	#effSetBlockSize     
	#effMainsChanged     
	#effEditGetRect
	#effEditOpen   
	#effEditClose   
	#effEditDraw    
	#effEditMouse   
	#effEditKey     
	#effEditIdle    
	#effEditTop     
	#effEditSleep   
	#effIdentify    
	#effGetChunk    
	#effSetChunk         
	#effNumOpcodes		
EndEnumeration

Structure DSBUFFERDESC
 dwSize.l            
 dwFlags.l           
 dwBufferBytes.l     
 dwReserved.l        
 *lpwfxFormat        
 guid3DAlgorithm.GUID
EndStructure

Structure AEffect 
  magic.l             
  dispatcher.l        
  process.l                 
  setParameter.l            
  getParameter.l            
  numPrograms.l             
  numParams.l               
  numInputs.l               
  numOutputs.l              
  flags.l                   
  resvd1.l                  
  resvd2.l                  
  initialDelay.l            
  realQualities.l           
  offQualities.l            
  ioRatio.f                 
  object.l                  
  user.l                    
  uniqueID.l             
  version.l              
  processReplacing.l        
  future.b[60]              
EndStructure 

Structure WAVEFORMATEX
 wFormatTag.w
 nChannels.w         
 nSamplesPerSec.l    
 nAvgBytesPerSec.l   
 nBlockAlign.w       
 wBitsPerSample.w    
 cbSize.w            
EndStructure

Structure WAVDATA
  mem.l
  size.l
EndStructure

Procedure.l GetWavHeader(*wavfmt.WAVEFORMATEX, filename.s)
  Protected fmtSize.l

  If ReadFile(0, filename)
    If ReadLong(0) <> 'FFIR' : ProcedureReturn #False : EndIf
    ReadLong(0)
    If ReadLong(0) <> 'EVAW' : ProcedureReturn #False : EndIf
    While ReadLong(0) <> ' tmf' And Eof(0) = #False
      FileSeek(0, Loc(0)-3)
    Wend
    fmtSize = ReadLong(0)
    *wavfmt\wFormatTag = ReadWord(0)
    *wavfmt\nChannels = ReadWord(0)
    *wavfmt\nSamplesPerSec = ReadLong(0)
    *wavfmt\nAvgBytesPerSec = ReadLong(0)
    *wavfmt\nBlockAlign = ReadWord(0)
    *wavfmt\wBitsPerSample = ReadWord(0)
   
    If fmtSize > 16
      *wavfmt\cbSize = ReadWord(0)
    Else
      *wavfmt\cbSize = 0
    EndIf

    CloseFile(0)
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
EndProcedure

Procedure.l GetWAVData(*wavdata.WAVDATA, filename.s)
  If ReadFile(0, filename)
    While ReadLong(0) <> 'atad' And Eof(0) = #False
      FileSeek(0, Loc(0)-3)
    Wend
    *wavdata\size = ReadLong(0)
    *wavdata\mem = AllocateMemory(*wavdata\size)
    ReadData(0, *wavdata\mem, *wavdata\size)

    CloseFile(0)
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
EndProcedure 

Procedure Host(*effect.AEffect, opcode.l, index.l, Value.l, *ptr.l, opt.f) 
  Select opcode
	  Case #audioMasterVersion          
	    r = 2
  EndSelect
  ProcedureReturn r
EndProcedure

If OpenLibrary(0, "dsound.dll") And OpenLibrary(1, "phaser.dll") And GetWavHeader(wavFormat.WAVEFORMATEX, "drumloop2.wav") And GetWavData(wavData.WAVDATA, "drumloop2.wav")
  hwnd = OpenWindow(0,0,0,800,400,"Sound", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  CallFunction(0,"DirectSoundCreate8",0,@dsound.IDirectSound8,0)
  dsound\SetCooperativeLevel(hwnd,1)

  desc.DSBUFFERDESC\dwSize = SizeOf(DSBUFFERDESC)  
  desc\dwBufferBytes = wavData\size
  desc\lpwfxFormat = @wavFormat
  dsound\CreateSoundBuffer(@desc,@dsb.IDirectSoundBuffer,0)
  
  sampleFrames = wavData\size / 4

  *effect.AEffect = CallFunction(1, "main", @Host())
  
  CallFunctionFast(*effect\dispatcher, *effect, #effOpen, 0, 0, #Null, 0.0)
  CallFunctionFast(*effect\dispatcher, *effect, #effMainsChanged, 0, 0, #Null, 0.0)
  CallFunctionFast(*effect\dispatcher, *effect, #effSetSampleRate, 0, 0, #Null, 44100)
  CallFunctionFast(*effect\dispatcher, *effect, #effSetBlockSize, 0, sampleFrames, #Null, 0.0)
  CallFunctionFast(*effect\dispatcher, *effect, #effMainsChanged, 0, 1, #Null, 0.0)

  Dim in.l(1)
  Dim leftIn.f(sampleFrames-1)
  Dim rightIn.f(sampleFrames-1)
  m = wavData\mem
  For i = 0 To sampleFrames-1
    leftIn(i) = PeekW(m)/32768
    rightIn(i) = PeekW(m+2)/32768
    m + 4
  Next
  in(0) = leftIn()
  in(1) = rightIn()
  
  Dim out.l(1)
  Dim leftOut.f(sampleFrames-1)
  Dim rightOut.f(sampleFrames-1)
  out(0) = leftOut()
  out(1) = rightOut()

  CallFunctionFast(*effect\processReplacing, *effect, in(), out(), sampleFrames)
  
  processedWavData = AllocateMemory(wavData\size)
  m = processedWavData
  For i = 0 To sampleFrames-1
    PokeW(m, leftOut(i) * 32768)
    PokeW(m+2, rightOut(i) * 32768)
    m + 4
  Next

  dsb\Lock(0,0,@m,@len,0,0,#DSBLOCK_ENTIREBUFFER)
  CopyMemory(processedWavData,m,len)
  dsb\UnLock(m,len,0,0)
  dsb\Play(0, 0, 0)
  
  FreeMemory(processedWavData)

  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
  
  CallFunctionFast(*effect\dispatcher, *effect, #effMainsChanged, 0, 0, #Null, 0.0)  
  CallFunctionFast(*effect\dispatcher, *effect, #effClose, 0, 0, #Null, 0.0)   

  dsb\Stop()
  dsb\Release()
  dsound\Release()
  CloseLibrary(1) 
  CloseLibrary(0) 
Else 
  MessageRequester("Error","Can't find VST plugin and/or .wav-file.",0) 
EndIf

Posted: Sun Jun 11, 2006 1:38 am
by KarLKoX

Code: Select all

#FILENAME = "J:\sebekmaj - Turrican II Level 1 (remake).wav"
;#VST_PLUGIN = "L:\Musique\Audio\Vstplugins\BluePhaser VST.dll"  ; works OK
#VST_PLUGIN = "L:\Musique\Audio\Vstplugins\SupaPhaser.dll"  ; reproduce distortion then works OK with this code

#DSBLOCK_ENTIREBUFFER = $2

#audioMasterVersion = 1

Enumeration
   #effOpen             
   #effClose           
   #effSetProgram       
   #effGetProgram       
   #effSetProgramName   
   #effGetProgramName
   #effGetParamLabel   
   #effGetParamDisplay 
   #effGetParamName     
   #effGetVu           
   #effSetSampleRate   
   #effSetBlockSize     
   #effMainsChanged     
   #effEditGetRect
   #effEditOpen   
   #effEditClose   
   #effEditDraw   
   #effEditMouse   
   #effEditKey     
   #effEditIdle   
   #effEditTop     
   #effEditSleep   
   #effIdentify   
   #effGetChunk   
   #effSetChunk         
   #effNumOpcodes      
EndEnumeration

Structure DSBUFFERDESC
 dwSize.l           
 dwFlags.l           
 dwBufferBytes.l     
 dwReserved.l       
 *lpwfxFormat       
 guid3DAlgorithm.GUID
EndStructure

Structure AEffect
  magic.l             
  dispatcher.l       
  process.l                 
  setParameter.l           
  getParameter.l           
  numPrograms.l             
  numParams.l               
  numInputs.l               
  numOutputs.l             
  flags.l                   
  resvd1.l                 
  resvd2.l                 
  initialDelay.l           
  realQualities.l           
  offQualities.l           
  ioRatio.f                 
  object.l                 
  user.l                   
  uniqueID.l             
  version.l             
  processReplacing.l       
  future.b[60]             
EndStructure

Structure WAVEFORMATEX
 wFormatTag.w
 nChannels.w         
 nSamplesPerSec.l   
 nAvgBytesPerSec.l   
 nBlockAlign.w       
 wBitsPerSample.w   
 cbSize.w           
EndStructure

Structure WAVDATA
  mem.l
  size.l
EndStructure

Procedure.l GetWavHeader(*wavfmt.WAVEFORMATEX, filename.s)
  Protected fmtSize.l

  If ReadFile(0, filename)
    If ReadLong(0) <> 'FFIR' : ProcedureReturn #False : EndIf
    ReadLong(0)
    If ReadLong(0) <> 'EVAW' : ProcedureReturn #False : EndIf
    While ReadLong(0) <> ' tmf' And Eof(0) = #False
      FileSeek(0, Loc(0)-3)
    Wend
    fmtSize = ReadLong(0)
    *wavfmt\wFormatTag = ReadWord(0)
    *wavfmt\nChannels = ReadWord(0)
    *wavfmt\nSamplesPerSec = ReadLong(0)
    *wavfmt\nAvgBytesPerSec = ReadLong(0)
    *wavfmt\nBlockAlign = ReadWord(0)
    *wavfmt\wBitsPerSample = ReadWord(0)
   
    If fmtSize > 16
      *wavfmt\cbSize = ReadWord(0)
    Else
      *wavfmt\cbSize = 0
    EndIf

    CloseFile(0)
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
EndProcedure

Procedure.l GetWAVData(*wavdata.WAVDATA, filename.s)
  If ReadFile(0, filename)
    While ReadLong(0) <> 'atad' And Eof(0) = #False
      FileSeek(0, Loc(0)-3)
    Wend
    *wavdata\size = ReadLong(0)
    *wavdata\mem = AllocateMemory(*wavdata\size)
    ReadData(0, *wavdata\mem, *wavdata\size)

    CloseFile(0)
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
EndProcedure

ProcedureCDLL Host(*effect.AEffect, opcode.l, index.l, Value.l, *ptr.l, opt.f)
  Select opcode
     Case #audioMasterVersion         
       r = 2.3
  EndSelect
  ProcedureReturn r
EndProcedure

If OpenLibrary(0, "dsound.dll") And OpenLibrary(1, #VST_PLUGIN) And GetWavHeader(wavFormat.WAVEFORMATEX, #FILENAME) And GetWavData(wavData.WAVDATA, #FILENAME)
  hwnd = OpenWindow(0,0,0,800,400,"Sound", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  CallFunction(0,"DirectSoundCreate8",0,@dsound.IDirectSound8,0)
  dsound\SetCooperativeLevel(hwnd,1)

  desc.DSBUFFERDESC\dwSize = SizeOf(DSBUFFERDESC) 
  desc\dwBufferBytes = wavData\size 
  desc\lpwfxFormat = @wavFormat
  dsound\CreateSoundBuffer(@desc,@dsb.IDirectSoundBuffer,0)
 
  sampleFrames = wavData\size / 4

  *effect.AEffect = CallFunction(1, "main", @Host())
 
  CallFunctionFast(*effect\dispatcher, *effect, #effOpen, 0, 0, #Null, 0.0)
  CallFunctionFast(*effect\dispatcher, *effect, #effMainsChanged, 0, 0, #Null, 0.0)
  CallFunctionFast(*effect\dispatcher, *effect, #effSetSampleRate, 0, 0, #Null, 44100)
  CallFunctionFast(*effect\dispatcher, *effect, #effSetBlockSize, 0, sampleFrames, #Null, 0.0)
  CallFunctionFast(*effect\dispatcher, *effect, #effMainsChanged, 0, 1, #Null, 0.0)

  Dim in.l(1)
  Dim leftIn.f(sampleFrames-1)
  Dim rightIn.f(sampleFrames-1)
  m = wavData\mem
  For i = 0 To sampleFrames-1
    leftIn(i) = PeekW(m)/32768.0
    rightIn(i) = PeekW(m+2)/32768.0
    m + 4
  Next
  in(0) = leftIn()
  in(1) = rightIn()
 
  Dim out.l(1)
  Dim leftOut.f(sampleFrames-1)
  Dim rightOut.f(sampleFrames-1)
  out(0) = leftOut()
  out(1) = rightOut()
    
  CallFunctionFast(*effect\processReplacing, *effect, in(), out(), sampleFrames)
 
  processedWavData = AllocateMemory(wavData\size)
  *m.Word = processedWavData
  m_dwBufferPos = 0
  For i = 0 To sampleFrames-1
    leftsample.l  = leftOut(i) * 32768.0
    rightsample.l = rightOut(i) * 32768.0
    If leftsample > 32767 
      leftsample = 32767
    ElseIf leftsample <32767> 32767 
      rightsample = 32767
    ElseIf rightsample <32767>> 8
    *m + 1
    
    *m\w = rightsample & $FF
    *m + 1
    
    *m\w = rightsample >> 8
    *m + 1
  Next

  dsb\Lock(0,0,@m,@len,0,0,#DSBLOCK_ENTIREBUFFER)
  CopyMemory(processedWavData,m,len)
  dsb\UnLock(m,len,0,0)
  dsb\Play(0, 0, 0)
 
  FreeMemory(processedWavData)

  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
 
  CallFunctionFast(*effect\dispatcher, *effect, #effMainsChanged, 0, 0, #Null, 0.0) 
  CallFunctionFast(*effect\dispatcher, *effect, #effClose, 0, 0, #Null, 0.0)   

  dsb\Stop()
  dsb\Release()
  dsound\Release()
  CloseLibrary(1)
  CloseLibrary(0)
Else
  MessageRequester("Error","Can't find VST plugin and/or .wav-file.",0)
EndIf
PS : phpbb seems to have some pb with formatting the code, PM me if you want it.

Posted: Sun Jun 11, 2006 9:24 am
by soerenkj
Thanks KarLKoX, but I do not understand your syntax with '<32767>' and my compiler doesn't either.. and isn't there also missing an 'EndIf'? (is this the problem with PhpBB that you mention?)

Posted: Sun Jun 11, 2006 12:50 pm
by KarLKoX

Code: Select all

#FILENAME = "J:\sebekmaj - Turrican II Level 1 (remake).wav"
;#VST_PLUGIN = "L:\Musique\Audio\Vstplugins\BluePhaser VST.dll"  ; works OK
#VST_PLUGIN = "L:\Musique\Audio\Vstplugins\SupaPhaser.dll"  ; works OK

#DSBLOCK_ENTIREBUFFER = $2

#audioMasterVersion = 1

Enumeration
   #effOpen             
   #effClose           
   #effSetProgram       
   #effGetProgram       
   #effSetProgramName   
   #effGetProgramName
   #effGetParamLabel   
   #effGetParamDisplay 
   #effGetParamName     
   #effGetVu           
   #effSetSampleRate   
   #effSetBlockSize     
   #effMainsChanged     
   #effEditGetRect
   #effEditOpen   
   #effEditClose   
   #effEditDraw   
   #effEditMouse   
   #effEditKey     
   #effEditIdle   
   #effEditTop     
   #effEditSleep   
   #effIdentify   
   #effGetChunk   
   #effSetChunk         
   #effNumOpcodes      
EndEnumeration

Structure DSBUFFERDESC
 dwSize.l           
 dwFlags.l           
 dwBufferBytes.l     
 dwReserved.l       
 *lpwfxFormat       
 guid3DAlgorithm.GUID
EndStructure

Structure AEffect
  magic.l             
  dispatcher.l       
  process.l                 
  setParameter.l           
  getParameter.l           
  numPrograms.l             
  numParams.l               
  numInputs.l               
  numOutputs.l             
  flags.l                   
  resvd1.l                 
  resvd2.l                 
  initialDelay.l           
  realQualities.l           
  offQualities.l           
  ioRatio.f                 
  object.l                 
  user.l                   
  uniqueID.l             
  version.l             
  processReplacing.l       
  future.b[60]             
EndStructure

Structure WAVEFORMATEX
 wFormatTag.w
 nChannels.w         
 nSamplesPerSec.l   
 nAvgBytesPerSec.l   
 nBlockAlign.w       
 wBitsPerSample.w   
 cbSize.w           
EndStructure

Structure WAVDATA
  mem.l
  size.l
EndStructure

Procedure.l GetWavHeader(*wavfmt.WAVEFORMATEX, filename.s)
  Protected fmtSize.l

  If ReadFile(0, filename)
    If ReadLong(0) <> 'FFIR' : ProcedureReturn #False : EndIf
    ReadLong(0)
    If ReadLong(0) <> 'EVAW' : ProcedureReturn #False : EndIf
    While ReadLong(0) <> ' tmf' And Eof(0) = #False
      FileSeek(0, Loc(0)-3)
    Wend
    fmtSize = ReadLong(0)
    *wavfmt\wFormatTag = ReadWord(0)
    *wavfmt\nChannels = ReadWord(0)
    *wavfmt\nSamplesPerSec = ReadLong(0)
    *wavfmt\nAvgBytesPerSec = ReadLong(0)
    *wavfmt\nBlockAlign = ReadWord(0)
    *wavfmt\wBitsPerSample = ReadWord(0)
   
    If fmtSize > 16
      *wavfmt\cbSize = ReadWord(0)
    Else
      *wavfmt\cbSize = 0
    EndIf

    CloseFile(0)
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
EndProcedure

Procedure.l GetWAVData(*wavdata.WAVDATA, filename.s)
  If ReadFile(0, filename)
    While ReadLong(0) <> 'atad' And Eof(0) = #False
      FileSeek(0, Loc(0)-3)
    Wend
    *wavdata\size = ReadLong(0)
    *wavdata\mem = AllocateMemory(*wavdata\size)
    ReadData(0, *wavdata\mem, *wavdata\size)

    CloseFile(0)
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
EndProcedure

ProcedureCDLL Host(*effect.AEffect, opcode.l, index.l, Value.l, *ptr.l, opt.f)
  Select opcode
     Case #audioMasterVersion         
       r = 2.3
  EndSelect
  ProcedureReturn r
EndProcedure

If OpenLibrary(0, "dsound.dll") And OpenLibrary(1, #VST_PLUGIN) And GetWavHeader(wavFormat.WAVEFORMATEX, #FILENAME) And GetWavData(wavData.WAVDATA, #FILENAME)
  hwnd = OpenWindow(0,0,0,800,400,"Sound", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  CallFunction(0,"DirectSoundCreate8",0,@dsound.IDirectSound8,0)
  dsound\SetCooperativeLevel(hwnd,1)

  desc.DSBUFFERDESC\dwSize = SizeOf(DSBUFFERDESC) 
  desc\dwBufferBytes = wavData\size 
  desc\lpwfxFormat = @wavFormat
  dsound\CreateSoundBuffer(@desc,@dsb.IDirectSoundBuffer,0)
 
  sampleFrames = wavData\size / 4

  *effect.AEffect = CallFunction(1, "main", @Host())
 
  CallFunctionFast(*effect\dispatcher, *effect, #effOpen, 0, 0, #Null, 0.0)
  CallFunctionFast(*effect\dispatcher, *effect, #effMainsChanged, 0, 0, #Null, 0.0)
  CallFunctionFast(*effect\dispatcher, *effect, #effSetSampleRate, 0, 0, #Null, 44100)
  CallFunctionFast(*effect\dispatcher, *effect, #effSetBlockSize, 0, sampleFrames, #Null, 0.0)
  CallFunctionFast(*effect\dispatcher, *effect, #effMainsChanged, 0, 1, #Null, 0.0)

  Dim in.l(1)
  Dim leftIn.f(sampleFrames-1)
  Dim rightIn.f(sampleFrames-1)
  m = wavData\mem
  For i = 0 To sampleFrames-1
    leftIn(i) = PeekW(m)/32768.0
    rightIn(i) = PeekW(m+2)/32768.0
    m + 4
  Next
  in(0) = leftIn()
  in(1) = rightIn()
 
  Dim out.l(1)
  Dim leftOut.f(sampleFrames-1)
  Dim rightOut.f(sampleFrames-1)
  out(0) = leftOut()
  out(1) = rightOut()
    
  CallFunctionFast(*effect\processReplacing, *effect, in(), out(), sampleFrames)
 
  processedWavData = AllocateMemory(wavData\size)
  *m.Word = processedWavData
  m_dwBufferPos = 0
  For i = 0 To sampleFrames-1
    leftsample.l  = leftOut(i) * 32768.0
    rightsample.l = rightOut(i) * 32768.0

    If leftsample > 32767 
      leftsample = 32767
    ElseIf leftsample < "-32767"  ; remove the quote
      leftsample = "-32767"
    EndIf

    If rightsample > 32767 
      rightsample = 32767
    ElseIf rightsample < "-32767" ; remove the quote
      rightsample = "-32767" 
    EndIf
    
    *m\w = leftsample & $FF
    *m + 1

    *m\w = leftsample >> 8
    *m + 1
    
    *m\w = rightsample & $FF
    *m + 1
    
    *m\w = rightsample >> 8
    *m + 1
  Next
  
  dsb\Lock(0,0,@m,@len,0,0,#DSBLOCK_ENTIREBUFFER)
  CopyMemory(processedWavData,m,len)
  dsb\UnLock(m,len,0,0)
  dsb\Play(0, 0, 0)
 
  FreeMemory(processedWavData)

  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
 
  CallFunctionFast(*effect\dispatcher, *effect, #effMainsChanged, 0, 0, #Null, 0.0) 
  CallFunctionFast(*effect\dispatcher, *effect, #effClose, 0, 0, #Null, 0.0)   

  dsb\Stop()
  dsb\Release()
  dsound\Release()
  CloseLibrary(1)
  CloseLibrary(0)
Else
  MessageRequester("Error","Can't find VST plugin and/or .wav-file.",0)
EndIf