Skip to content

Instantly share code, notes, and snippets.

@skitaoka
Last active July 16, 2023 14:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save skitaoka/47bb2d3094936a75facd03561969c2ea to your computer and use it in GitHub Desktop.
Save skitaoka/47bb2d3094936a75facd03561969c2ea to your computer and use it in GitHub Desktop.
31平均律を想定して 3ch で打ち込まれたノートを Pianoteq の Multi-channel MIDI layout [MIDI channel 1] にルーティングする VSTi
! Default
! Size of map:
0
! MIDI range:
0
127
! Middle note:
60
! Reference note (MIDI number and frequency in Hz):
69
440
! Scale degree to consider as formal octave:
31
! Mapping:
Equal temperament with 31 degrees / octave
31
38.709677
77.419355
116.129032
154.838710
193.548387
232.258065
270.967742
309.677419
348.387097
387.096774
425.806452
464.516129
503.225806
541.935484
580.645161
619.354839
658.064516
696.774194
735.483871
774.193548
812.903226
851.612903
890.322581
929.032258
967.741935
1006.451613
1045.161290
1083.870968
1122.580645
1161.290323
2/1
#include <public.sdk/source/main/pluginfactory.h>
#include <public.sdk/source/vst/vstaudioeffect.h>
#include <public.sdk/source/vst/vstguieditor.h>
#include <public.sdk/source/vst/vsteditcontroller.h>
#include <public.sdk/source/vst/vstaudioprocessoralgo.h>
#include <public.sdk/source/vst/vstaudioprocessoralgo.h>
#include <pluginterfaces/base/ibstream.h>
#include <pluginterfaces/base/ustring.h>
#include <pluginterfaces/vst/ivstevents.h>
#include <pluginterfaces/vst/ivstparameterchanges.h>
#include <pluginterfaces/vst/ivstplugview.h>
#include <pluginterfaces/vst/ivsteditcontroller.h>
#include <pluginterfaces/vst/ivstmidicontrollers.h>
#include <pluginterfaces/vst/vstpresetkeys.h>
#include <vstgui/vstgui.h>
#include <vstgui/plugin-bindings/vst3editor.h>
#include <base/source/fstreamer.h>
#include <cstring>
namespace {
Steinberg::FUID const NoteRouter31ProcessorUID{0x35B67B8B, 0x8B8F429E, 0x9A6BE7F1, 0x204D57D2};
Steinberg::FUID const NoteRouter31ControllerUID{0x191B63A0, 0x56A34988, 0xAA2DFD6D, 0xAC2EEFF8};
class NoteRouter31Processor : public Steinberg::Vst::AudioEffect {
public:
static Steinberg::FUnknown* createInstance(void*) {
return reinterpret_cast<Steinberg::FUnknown*>(new NoteRouter31Processor());
}
public:
NoteRouter31Processor() {
setControllerClass(NoteRouter31ControllerUID);
}
Steinberg::tresult PLUGIN_API initialize(Steinberg::FUnknown* context) SMTG_OVERRIDE {
if (Steinberg::tresult const retval = AudioEffect::initialize(context)) {
return retval;
}
this->addAudioOutput(STR16("Mono Out"), Steinberg::Vst::SpeakerArr::kMono);
this->addEventInput(STR16("Event In"), 3);
this->addEventOutput(STR16("Event Out"), 16);
return Steinberg::kResultOk;
}
Steinberg::tresult PLUGIN_API setBusArrangements(
Steinberg::Vst::SpeakerArrangement* inputs, Steinberg::int32 numIns,
Steinberg::Vst::SpeakerArrangement* outputs, Steinberg::int32 numOuts) SMTG_OVERRIDE {
if ((numOuts == 1) && (outputs[0] == Steinberg::Vst::SpeakerArr::kMono)) {
return AudioEffect::setBusArrangements(inputs, numIns, outputs, numOuts);
}
return Steinberg::kNotImplemented;
}
public:
Steinberg::tresult PLUGIN_API process(Steinberg::Vst::ProcessData& data) SMTG_OVERRIDE {
static constexpr Steinberg::int32 const equal_division_of_the_octave = 31;
static constexpr Steinberg::int32 const base_note_number = 60;
static constexpr Steinberg::int32 const scale_notes[] = { 0, 2, 5, 7, 10, 13, 15, 18, 20, 23, 25, 28 };
static constexpr std::size_t const num_scale_notes = std::size(scale_notes);
static constexpr Steinberg::int32 const note_channels[] = { 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5 };
static constexpr Steinberg::int32 const note_shifts[] = { 0, 1, -1 };
static constexpr std::size_t const num_note_shifts = std::size(note_shifts);
if (Steinberg::Vst::IEventList* const inputEvents = data.inputEvents) {
if (Steinberg::Vst::IEventList* const outputEvents = data.outputEvents) {
for (Steinberg::int32 i = 0, n = inputEvents->getEventCount(); i < n; ++i) {
Steinberg::Vst::Event evt;
if (!inputEvents->getEvent(i, evt)) {
switch (evt.type) {
case Steinberg::Vst::Event::kNoteOnEvent:
{
std::size_t const channel = evt.noteOn.channel;
std::size_t const pitch = evt.noteOn.pitch;
evt.noteOn.channel = note_channels[pitch / num_scale_notes];
evt.noteOn.pitch = base_note_number + note_shifts[channel % num_note_shifts] + scale_notes[pitch % num_scale_notes];
outputEvents->addEvent(evt);
break;
}
case Steinberg::Vst::Event::kNoteOffEvent:
{
std::size_t const channel = evt.noteOff.channel;
std::size_t const pitch = evt.noteOff.pitch;
evt.noteOff.channel = note_channels[pitch / num_scale_notes];
evt.noteOff.pitch = base_note_number + note_shifts[channel % num_note_shifts] + scale_notes[pitch % num_scale_notes];
outputEvents->addEvent(evt);
break;
}
case Steinberg::Vst::Event::kDataEvent:
case Steinberg::Vst::Event::kPolyPressureEvent:
case Steinberg::Vst::Event::kNoteExpressionValueEvent:
case Steinberg::Vst::Event::kNoteExpressionTextEvent:
case Steinberg::Vst::Event::kChordEvent:
case Steinberg::Vst::Event::kScaleEvent:
case Steinberg::Vst::Event::kLegacyMIDICCOutEvent:
outputEvents->addEvent(evt);
break;
}
}
}
}
}
Steinberg::uint32 const sampleFramesSize = Steinberg::Vst::getSampleFramesSizeInBytes(processSetup, data.numSamples);
for (Steinberg::int32 i = 0, n = data.numOutputs; i < n; ++i) {
for (Steinberg::int32 j = 0, m = data.outputs[i].numChannels; j < m; ++j) {
std::memset(data.outputs[i].channelBuffers64[j], 0, sampleFramesSize);
data.outputs[i].silenceFlags |= 1ull << j;
}
}
return Steinberg::kResultOk;
}
};
class NoteRouter31Controller : public Steinberg::Vst::EditController {
public:
static Steinberg::FUnknown* createInstance(void* /*context*/) {
return static_cast<Steinberg::Vst::IEditController*>(new NoteRouter31Controller());
}
OBJ_METHODS(NoteRouter31Controller, EditController)
DEFINE_INTERFACES
END_DEFINE_INTERFACES(EditController)
REFCOUNT_METHODS(EditController)
};
BEGIN_FACTORY_DEF("Shinya Kitaoka", "https://github.com/skitaoka", "mailto:skitaoka@gmail.com")
DEF_CLASS2(
INLINE_UID_FROM_FUID(NoteRouter31ProcessorUID),
Steinberg::PClassInfo::kManyInstances,
kVstAudioEffectClass,
"NoteRouter31",
Vst::kDistributable,
Steinberg::Vst::PlugType::kInstrument,
"1.0.0",
kVstVersionString,
NoteRouter31Processor::createInstance)
DEF_CLASS2(
INLINE_UID_FROM_FUID(NoteRouter31ControllerUID),
Steinberg::PClassInfo::kManyInstances,
kVstComponentControllerClass,
"NoteRouter31Controller",
0, "",
"1.0.0",
kVstVersionString,
NoteRouter31Controller::createInstance)
END_FACTORY
}
EXPORTS
GetPluginFactory
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment