Last active
July 16, 2023 14:16
-
-
Save skitaoka/47bb2d3094936a75facd03561969c2ea to your computer and use it in GitHub Desktop.
31平均律を想定して 3ch で打ち込まれたノートを Pianoteq の Multi-channel MIDI layout [MIDI channel 1] にルーティングする VSTi
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
! 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: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
EXPORTS | |
GetPluginFactory |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment