About VSTi...

Asked by Jin

Hi I'm building a sequencer with your module and have two problems.

First it crashes while dumping some of the VSTi's parameters without modifications to these:

class VstStringConstants(object):
  kVstMaxProgNameLen = 256
  kVstMaxParamStrLen = 256
  kVstMaxVendorStrLen = 256
  kVstMaxProductStrLen = 256
  kVstMaxEffectNameLen = 256

I solved it by setting every numbers big enough..

And secondly, I'm trying to send a Midi message and get an output but I don't get any output.... I don't know if sending midi message part is wrong or getting an output part is wrong...
Same code using C++ produces result, but with python no results.

Can you tell me what I'm doing wrong?

Below is the code.

Thank you!

class VSTWindow:
    def __init__(self, fileName, parent):
        self.parent = parent
        vstEff = pyvst.VSTPlugin(fileName,self.Callback)
        self.vstEff = vstEff
        vstEff.open()
        self.sampleRate = 44100.0
        self.blockSize = 512
        vstEff.set_sample_rate(self.sampleRate)
        vstEff.set_block_size(11025) # some vsts can't increase block size so set it big enough first time
        self.isVSTi = vstEff.CanDo("receiveVstMidiEvent") == True # False: Effect, True: VSTi?
        vstEff.resume()
        vstEff.suspend()
        vstEff.set_block_size(self.blockSize) # and shrink it back
        vstEff.resume()
        pyvst.dump_effect_properties(vstEff)

        #self.vstThd = VSTSoundWorker(vstEff, self)
        #self.vstThd.start()

        wndproc = {
                    win32con.WM_CLOSE:self.OnWM_CLOSE,
                    }

        title = vstEff.get_name()
        l,t,r,b = 100, 100, 200, 200
        wc = win32gui.WNDCLASS()
        wc.lpszClassName = 'test_win32gui_1'
        wc.style = win32con.CS_GLOBALCLASS|win32con.CS_VREDRAW | win32con.CS_HREDRAW
        wc.hbrBackground = win32con.COLOR_WINDOW+1
        wc.hCursor = win32gui.LoadCursor( 0, win32con.IDC_ARROW )
        wc.lpfnWndProc=wndproc
        class_atom=win32gui.RegisterClass(wc)
        self.hwnd = hwnd = win32gui.CreateWindowEx(win32con.WS_EX_DLGMODALFRAME | win32con.WS_EX_TOOLWINDOW , wc.lpszClassName,
            title,
            win32con.WS_CAPTION|win32con.WS_VISIBLE|win32con.WS_SYSMENU,
            l,t,r,b, 0, 0, win32gui.GetModuleHandle(None), None)

        vstEff.open_edit(hwnd)
        eRect = self.vstEff.get_erect()
        width = eRect.right - eRect.left;
        height = eRect.bottom - eRect.top;
        if (width < 100):
            width = 100
        if (height < 100):
            height = 100
        width += 10
        height += 35

        win32gui.SetWindowPos (hwnd, win32con.HWND_TOP, 0, 0, width, height, win32con.SWP_NOMOVE);

        self.notClosed = True
        self.NoteEvent(0x64, 0xFF)

    def NoteEvent(self, key, volume):
        kVstMidiType = 1
        kVstMidiEventIsRealTime = 1
        vstMidiEvents = pyvst.VstMidiEvents()
        vstMidiEvents.numEvents = 4
        vstMidiEvents.reserved = 0
        midiEvent1 = pyvst.VstMidiEvent()
        midiEvent1.type = kVstMidiType
        midiEvent1.byteSize = 24#sizeof(pyvst.VstMidiEvent)
        midiEvent1.deltaFrames = 0 # note start position!
        midiEvent1.flags = 0
        midiEvent1.noteLength = 0#self.sampleRate/1000*30
        midiEvent1.noteOffset = 0 # ??? end position?
        midiEvent1.midiData1 = (0x90) # play note midi msg
        midiEvent1.midiData2 = (key) # note key
        midiEvent1.midiData3 = (0xFF) # volume
        midiEvent1.midiData4 = (0x00)
        midiEvent1.detune = 0
        midiEvent1.noteOffVelocity = 0
        midiEvent1.reserved1 = 0
        midiEvent1.reserved2 = 0
        vstMidiEvents.events[0] = POINTER(pyvst.VstMidiEvent)(midiEvent1)
        midiEvent2 = pyvst.VstMidiEvent()
        midiEvent2.type = kVstMidiType
        midiEvent2.byteSize = 24#sizeof(pyvst.VstMidiEvent)
        midiEvent2.deltaFrames = 128 # note start position!
        midiEvent2.flags = 0
        midiEvent2.noteLength = 0#self.sampleRate/1000*30
        midiEvent2.noteOffset = 0 # ??? end position?
        midiEvent2.midiData1 = (0x90) # play note midi msg
        midiEvent2.midiData2 = (key) # note key
        midiEvent2.midiData3 = (0x00) # volume
        midiEvent2.midiData4 = (0x00)
        midiEvent2.detune = 0
        midiEvent2.noteOffVelocity = 0
        midiEvent2.reserved1 = 0
        midiEvent2.reserved2 = 0
        vstMidiEvents.events[1] = POINTER(pyvst.VstMidiEvent)(midiEvent2)
        midiEvent3 = pyvst.VstMidiEvent()
        midiEvent3.type = kVstMidiType
        midiEvent3.byteSize = 24#sizeof(pyvst.VstMidiEvent)
        midiEvent3.deltaFrames = 256 # note start position!
        midiEvent3.flags = 0
        midiEvent3.noteLength = 0#self.sampleRate/1000*30
        midiEvent3.noteOffset = 0 # ??? end position?
        midiEvent3.midiData1 = (0x90) # play note midi msg
        midiEvent3.midiData2 = (key) # note key
        midiEvent3.midiData3 = (0xFF) # volume
        midiEvent3.midiData4 = (0x00)
        midiEvent3.detune = 0
        midiEvent3.noteOffVelocity = 0
        midiEvent3.reserved1 = 0
        midiEvent3.reserved2 = 0
        vstMidiEvents.events[2] = POINTER(pyvst.VstMidiEvent)(midiEvent3)
        midiEvent4 = pyvst.VstMidiEvent()
        midiEvent4.type = kVstMidiType
        midiEvent4.byteSize = 24#sizeof(pyvst.VstMidiEvent)
        midiEvent4.deltaFrames = 384 # note start position!
        midiEvent4.flags = 0
        midiEvent4.noteLength = 0#self.sampleRate/1000*30
        midiEvent4.noteOffset = 0 # ??? end position?
        midiEvent4.midiData1 = (0x90) # play note midi msg
        midiEvent4.midiData2 = (key) # note key
        midiEvent4.midiData3 = (0x00) # volume
        midiEvent4.midiData4 = (0x00)
        midiEvent4.detune = 0
        midiEvent4.noteOffVelocity = 0
        midiEvent4.reserved1 = 0
        midiEvent4.reserved2 = 0
        vstMidiEvents.events[3] = POINTER(pyvst.VstMidiEvent)(midiEvent4)
        print self.vstEff.ProcessMidi(vstMidiEvents)
        output = numpy.zeros((self.vstEff.number_of_outputs, 512), dtype=numpy.float32)
        self.vstEff.process_replacing_output(output[:, 0:512], 512)
        f = open("text.wav", "wb")
        f.write(output[1][0:512])
        f.write(output[0][0:512])
        f.close()
    def OnWM_CLOSE(self, hwnd, msg, wp, lp):
        self.CloseWindow(hwnd)
    def Close(self, hwnd):
        self.CloseWindow(hwnd)
        VSTSoundWorker.quit = True
    def CloseWindow(self, hwnd):
        if self.notClosed:
            self.notClosed = False
            self.vstEff.close_edit()
            win32gui.DestroyWindow(hwnd)
    def Callback(self, effect, opcode, index, value, ptr, opt):
        """
        Basic callback
        """
        kVstVersion = 2400
        if opcode == pyvst.AudioMasterOpcodes.audioMasterCanDo:
            canDos = ["sendVstEvents",
                "sendVstMidiEvent",
                "receiveVstEvents",
                "receiveVstMidiEvent",
                "sizeWindow",
                "sendVstMidiEventFlagIsRealtime",
                "openFileSelector",
                "closeFileSelector",
                "shellCategory",
                "supplyIdle"]

            print c_char_p(ptr).value
            if c_char_p(ptr).value in canDos:
                return 1
        if opcode == pyvst.AudioMasterOpcodes.audioMasterVersion:
            return kVstVersion

        return 0

# additions to your module
class VstMidiEvent(Structure):
    _fields_ = [
        ("type", c_int, 32),
        ("byteSize", c_int, 32),
        ("deltaFrames", c_int, 32),
        ("flags", c_int, 32),
        ("noteLength", c_int, 32),
        ("noteOffset", c_int, 32),
        ("midiData1", c_byte, 8),
        ("midiData2", c_byte, 8),
        ("midiData3", c_byte, 8),
        ("midiData4", c_byte, 8),
        ("detune", c_byte, 8),
        ("noteOffVelocity", c_byte, 8),
        ("reserved1", c_byte, 8),
        ("reserved2", c_byte, 8), ]

class VstMidiEvents(Structure):
    _fields_ = [
        ("numEvents", c_int, 32),
        ("reserved", c_void_p),
        ("events", POINTER(VstMidiEvent)*256),
    ]

def ProcessMidi(self, midiEvents):
    evtP = POINTER(VstMidiEvents)(midiEvents)
    return self.dispatcher(byref(self.__effect), AEffectXOpcodes.effProcessEvents, 0, 0, evtP, 0.0)

def process_replacing_output(self, outputs, size):
    f4ptr = POINTER(c_float)
    float_output_pointers = (f4ptr*len(outputs))(*[row.ctypes.data_as(f4ptr) for row in outputs])
    self.__process_replacing(byref(self.__effect), POINTER(c_float)(), float_output_pointers, size)

Question information

Language:
English Edit question
Status:
Solved
For:
pyvst Edit question
Assignee:
No assignee Edit question
Solved by:
Jin
Solved:
Last query:
Last reply:
Revision history for this message
Jin (yubgipenguin) said :
#1

OK I found problem... problem was

32 as in ("numEvents", c_int, 32).
When modified to ("numEvents", c_int) it worked....