pipelined / vst2

Build vst2 plugins and hosts with Go
MIT License
135 stars 17 forks source link

How to build a vst2 synth? #61

Closed vsariola closed 1 year ago

vsariola commented 1 year ago

I'd like to use this library to build a synth instead of an effect plugin, but just changing the category was not enough. The synth would need to receive MIDI messages and produce sound in response. Is it currently possible?

dudk commented 1 year ago

Hello @vsariola. It should be possible, but required plugin dispatch call is not implemented in this library. You can check PlugProcessEvents godoc and other dispatch calls for inspiration.

vsariola commented 1 year ago

First tests and observations:

1) I would need cp.flags = cp.flags | C.int(PluginIsSynth) here: https://github.com/pipelined/vst2/blob/bc659a1443b585c376cc25a6d13614488c9fa4ee/plugin_export.go#L32

How to define that flexibly? Would adding IsSynth bool to Plugin that defaults to false, but user can set it to true?

2) I would like respond to PlugCanDo opcodes, with something along these lines:

case PlugCanDo:
  var str string = C.GoString((*C.char)(ptr))
  p := PluginCanDoString(str)
  switch p {
  case PluginCanReceiveEvents:
  return 1
  case PluginCanReceiveMIDIEvent:
  return 1
  case PluginCanReceiveTimeInfo:
  return 1
  }
  return -1

3) Should Plugin define something like ProcessEventsFunc that gets called by PlugProcessEvents?

dudk commented 1 year ago

I think that those are correct observations.

I would need cp.flags = cp.flags | C.int(PluginIsSynth) here. How to define that flexibly? Would adding IsSynth bool to Plugin that defaults to false, but user can set it to true?

Seems like a right way to do it.

I would like respond to PlugCanDo opcodes, with something along these lines.

I think that a good way to do it is to define a PlugCanDoFuc and embed it to Plugin type:

type PlugCanDoFunc(PluginCanDoString) bool;

It would allow users to define this custom canDo function per plugin.

Should Plugin define something like ProcessEventsFunc that gets called by PlugProcessEvents?

Yes, I think so.

vsariola commented 1 year ago

Just reporting in that I have:

1) Exposed the entire Flags as a field of the Plugin:

Flags PluginFlag

The PluginDoubleProcessing and PluginFloatProcessing flags are still automatically set if needed by the presence of the associated functions, but this allows the user to set any other flags as needed.

2) I've given Plugin a member

PluginCanDoFunc func(PluginCanDoString) CanDoResponse

and in vst2.go, I've defined

type CanDoResponse int64

const (
    // YesCanDo is returned by CanDo queries when plugin/host is certain that it supports a feature.
    YesCanDo CanDoResponse = 1
    // NoCanDo is returned by CanDo queries when plugin/host is certain that it does not support a feature.
    NoCanDo CanDoResponse = -1
    // MaybeCanDo is returned by CanDo queries when plugin/host doesn't know if it supports a particular feature.
    MaybeCanDo CanDoResponse = 0
)

I was looking for a type like Optional bool but could not find anything like that in the go standard library, so I went with these. I'm really sorry about the NoCanDo :D But I could not resist the temptation.

If these sound somewhat reasonable, and once I have the MIDI messaging working, I'll hit you with a PR.