SynthLab SDK
|
Look at the class definition for th ModuleCore to find the five functions that implement the five operational phases of all sytnth components. All functions take the same argument, a reference to a CoreProcData structure. The owning SynthModule prepares this structure in its constructor, and passes it to the cores when it calls their functions.
This structure is different from the others in SynthLab as it uses naked pointers (rather than std::unique_ptr and std::shared_ptr) and const char*s (rather than std::string). There is a very important reason for using these old-fashioned constructs: for dynamically loaded ModuleCores (mini-DLLs) this structure will be passed across the thunk layer, an imaginary barrier between the process and the DLL with which it communicates. This absolutely requires using these basic C++ datatypes while avoiding the standard library (in addition to many others) and has to do with the way functions are called and the stack is pushed/popped. The standard library's binaries are different for every version of Visual Studio and Xcode, and are also different for the Debug and Release configurations. This would break the whole idea of compiling the mini-DLLs in whatever version of Visual Studio or Xcode you choose.
The CoreProcData structure contains every piece of information that will be needed for any and all of the five operational phases. The structure is shown below and most of the parameters are self-explanatory based on the name. First are the modulation input and output array pointers:
Next are the naked pointers to the audio buffers; the pointers are arrays of pointers as each channel has its own buffer. The fmBuffer contains audio data that is used for phase modulation (FM synthesis).
To get a pointer to the left channel input buffer during the render() operation you would write:
Next are the database and MIDI input data pointers (the interfaces are likewise "pure" C++ with no std:: library members)
The next member is so important, it has its own code listing. This is the custom data structure pointer. This pointer is cloaked as a void* since it will depend on the type of module.
You cast this pointer to the datatype you need for a particular module. You can use simple casting or more complex versions, checking the cast before usage. Here I will just use a simple cast:
The remaining members are used in various operational phases. Note the MIDINoteEvent structure that is used for the note-on and note-off handlers.