heavydpf_midi_thru/plugin/source/HeavyDPF_dpf_example.cpp
2021-10-17 23:09:30 +02:00

298 lines
8.6 KiB
C++

/**
* Copyright (c) 2021 Enzien Audio, Ltd.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions, and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the phrase "powered by heavy",
* the heavy logo, and a hyperlink to https://enzienaudio.com, all in a visible
* form.
*
* 2.1 If the Application is distributed in a store system (for example,
* the Apple "App Store" or "Google Play"), the phrase "powered by heavy"
* shall be included in the app description or the copyright text as well as
* the in the app itself. The heavy logo will shall be visible in the app
* itself as well.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "HeavyDPF_dpf_example.hpp"
#define HV_LV2_NUM_PARAMETERS 0
#define HV_HASH_NOTEIN 0x67E37ca3
#define HV_HASH_CTLIN 0x41be0f9c
#define HV_HASH_BENDIN 0x3083f0f7
#define HV_HASH_TOUCHIN 0x553925bd
#define HV_HASH_PGMIN 0x2e1ea03d
#define HV_HASH_NOTEOUT 0xd1d4ac2
#define HV_HASH_CTLOUT 0xe5e2a040
#define HV_HASH_BENDOUT 0xe8458013
#define HV_HASH_TOUCHOUT 0x476d4387
#define HV_HASH_PGMOUT 0x8753e39e
START_NAMESPACE_DISTRHO
static void sendHookFunc(HeavyContextInterface *c, const char *sendName, uint32_t sendHash, const HvMessage *m)
{
printf("> midi output stuff! \n");
HeavyDPF_dpf_example* plugin = (HeavyDPF_dpf_example*)c->getUserData();
if (plugin != nullptr)
{
plugin->handleMidiSend(sendHash, m);
}
}
HeavyDPF_dpf_example::HeavyDPF_dpf_example()
: Plugin(HV_LV2_NUM_PARAMETERS, 0, 0)
{
_context = new Heavy_dpf_example(getSampleRate(), 10, 2, 5);
_context->setUserData(this);
_context->setSendHook(&sendHookFunc);
}
HeavyDPF_dpf_example::~HeavyDPF_dpf_example() {
delete _context;
}
void HeavyDPF_dpf_example::initParameter(uint32_t index, Parameter& parameter)
{
}
// -------------------------------------------------------------------
// Internal data
float HeavyDPF_dpf_example::getParameterValue(uint32_t index) const
{
return 0.0f;
}
void HeavyDPF_dpf_example::setParameterValue(uint32_t index, float value)
{
// nothing to do
}
// -------------------------------------------------------------------
// Process
// void HeavyDPF_dpf_example::activate()
// {
// }
// void HeavyDPF_dpf_example::deactivate()
// {
// }
void HeavyDPF_dpf_example::run(const float** inputs, float** outputs, uint32_t frames, const MidiEvent* midiEvents, uint32_t midiEventCount)
{
uint32_t framesDone = 0;
uint32_t curEventIndex = 0;
_context->process((float**)inputs, outputs, frames);
while (framesDone < frames)
{
while (curEventIndex < midiEventCount && framesDone == midiEvents[curEventIndex].frame)
{
if (midiEvents[curEventIndex].size > MidiEvent::kDataSize)
continue;
handleMidiInput(frames, curEventIndex, midiEvents, midiEventCount);
curEventIndex++;
}
framesDone++;
}
}
// -------------------------------------------------------------------
// Callbacks
void HeavyDPF_dpf_example::sampleRateChanged(double newSampleRate)
{
delete _context;
_context = new Heavy_dpf_example(newSampleRate, 10, 2, 5);
_context->setUserData(this);
_context->setSendHook(&sendHookFunc);
}
void HeavyDPF_dpf_example::handleMidiInput(uint32_t frames, uint32_t curEventIndex, const MidiEvent* midiEvents, uint32_t midiEventCount)
{
int status = midiEvents[curEventIndex].data[0];
int command = status & 0xF0;
int channel = status & 0x0F;
int data1 = midiEvents[curEventIndex].data[1];
int data2 = midiEvents[curEventIndex].data[2];
switch (command) {
case 0x80: // note off
case 0x90: { // note on
printf("> midi input stuff! pitch: %d - velocity: %d - channel: %d \n", data1, data2, channel);
_context->sendMessageToReceiverV(HV_HASH_NOTEIN, 1000.0*frames/getSampleRate(), "fff",
(float) data1, // pitch
(float) data2, // velocity
(float) channel);
break;
}
case 0xB0: { // control change
_context->sendMessageToReceiverV(HV_HASH_CTLIN, 0, "fff",
(float) data2, // value
(float) data1, // controller number
(float) channel);
break;
}
case 0xC0: { // program change
_context->sendMessageToReceiverV(HV_HASH_PGMIN, 0, "ff",
(float) data1,
(float) channel);
break;
}
case 0xD0: { // aftertouch
_context->sendMessageToReceiverV(HV_HASH_TOUCHIN, 0, "ff",
(float) data1,
(float) channel);
break;
}
case 0xE0: { // pitch bend
hv_uint32_t value = (((hv_uint32_t) data2) << 7) | ((hv_uint32_t) data1);
_context->sendMessageToReceiverV(HV_HASH_BENDIN, 0, "ff",
(float) value,
(float) channel);
break;
}
default: break;
}
}
void HeavyDPF_dpf_example::handleMidiSend(uint32_t sendHash, const HvMessage *m)
{
switch(sendHash){
case HV_HASH_NOTEOUT: // __hv_noteout
{
uint8_t note = hv_msg_getFloat(m, 0);
uint8_t velocity = hv_msg_getFloat(m, 1);
uint8_t ch = hv_msg_getFloat(m, 2);
printf("> note: %d - velocity: %d - ch: %d \n", note, velocity, ch);
MidiEvent midiSendEvent;
midiSendEvent.frame = 0;
midiSendEvent.size = m->numElements;
midiSendEvent.dataExt = nullptr;
if (velocity == 127){
midiSendEvent.data[0] = 0x80 | ch; // noteoff
} else {
midiSendEvent.data[0] = 0x90 | ch; // noteon
}
midiSendEvent.data[1] = note;
midiSendEvent.data[2] = velocity;
midiSendEvent.data[3] = 0;
writeMidiEvent(midiSendEvent);
break;
}
case HV_HASH_CTLOUT:
{
uint8_t value = hv_msg_getFloat(m, 0);
uint8_t cc = hv_msg_getFloat(m, 1);
uint8_t ch = hv_msg_getFloat(m, 2);
printf("> value: %d - cc: %d - ch: %d \n", value, cc, ch);
MidiEvent midiSendEvent;
midiSendEvent.frame = 0;
midiSendEvent.size = m->numElements;
midiSendEvent.dataExt = nullptr;
midiSendEvent.data[0] = 0xB0 | ch; // send CC
midiSendEvent.data[1] = cc;
midiSendEvent.data[2] = value;
midiSendEvent.data[3] = 0;
writeMidiEvent(midiSendEvent);
break;
}
case HV_HASH_PGMOUT:
{
uint8_t cc_val = hv_msg_getFloat(m, 0);
uint8_t cc_num = hv_msg_getFloat(m, 1);
uint8_t ch = hv_msg_getFloat(m, 2);
printf("> cc_val: %d - cc_num: %d - ch: %d \n", cc_val, cc_num, ch);
MidiEvent midiSendEvent;
midiSendEvent.frame = 0;
midiSendEvent.size = m->numElements;
midiSendEvent.dataExt = nullptr;
midiSendEvent.data[0] = 0xC0 | ch; // send Program Change
midiSendEvent.data[1] = cc_num;
midiSendEvent.data[2] = cc_val;
midiSendEvent.data[3] = 0;
break;
}
case HV_HASH_TOUCHOUT:
{
uint8_t value = hv_msg_getFloat(m, 0);
uint8_t ch = hv_msg_getFloat(m, 2);
printf("> value: %d - ch: %d \n", value, ch);
MidiEvent midiSendEvent;
midiSendEvent.frame = 0;
midiSendEvent.size = m->numElements;
midiSendEvent.dataExt = nullptr;
midiSendEvent.data[0] = 0xD0 | ch; // send Touch
midiSendEvent.data[1] = value;
midiSendEvent.data[2] = 0;
midiSendEvent.data[3] = 0;
break;
}
case HV_HASH_BENDOUT:
{
break;
}
default:
break;
}
}
// -----------------------------------------------------------------------
/* Plugin entry point, called by DPF to create a new plugin instance. */
Plugin* createPlugin()
{
return new HeavyDPF_dpf_example();
}
// -----------------------------------------------------------------------
END_NAMESPACE_DISTRHO