Browse Source

Import SendNote example from #212, slightly adjusted

Signed-off-by: falkTX <falktx@falktx.com>
pull/277/head
falkTX 3 years ago
parent
commit
ae52c3647c
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
6 changed files with 450 additions and 0 deletions
  1. +2
    -0
      Makefile
  2. +32
    -0
      examples/SendNote/DistrhoPluginInfo.h
  3. +46
    -0
      examples/SendNote/Makefile
  4. +6
    -0
      examples/SendNote/README.md
  5. +192
    -0
      examples/SendNote/SendNoteExamplePlugin.cpp
  6. +172
    -0
      examples/SendNote/SendNoteExampleUI.cpp

+ 2
- 0
Makefile View File

@@ -25,6 +25,7 @@ examples: dgl
$(MAKE) all -C examples/Meters
$(MAKE) all -C examples/MidiThrough
$(MAKE) all -C examples/Parameters
$(MAKE) all -C examples/SendNote
$(MAKE) all -C examples/States
ifeq ($(HAVE_CAIRO),true)
$(MAKE) all -C examples/CairoUI
@@ -65,6 +66,7 @@ clean:
$(MAKE) clean -C examples/Meters
$(MAKE) clean -C examples/MidiThrough
$(MAKE) clean -C examples/Parameters
$(MAKE) clean -C examples/SendNote
$(MAKE) clean -C examples/States
$(MAKE) clean -C utils/lv2-ttl-generator
ifneq ($(MACOS_OR_WINDOWS),true)


+ 32
- 0
examples/SendNote/DistrhoPluginInfo.h View File

@@ -0,0 +1,32 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
* permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#ifndef DISTRHO_PLUGIN_INFO_H_INCLUDED
#define DISTRHO_PLUGIN_INFO_H_INCLUDED

#define DISTRHO_PLUGIN_BRAND "DISTRHO"
#define DISTRHO_PLUGIN_NAME "SendNote"
#define DISTRHO_PLUGIN_URI "http://distrho.sf.net/examples/SendNote"

#define DISTRHO_PLUGIN_HAS_UI 1
#define DISTRHO_PLUGIN_HAS_EMBED_UI 1
#define DISTRHO_PLUGIN_IS_RT_SAFE 1
#define DISTRHO_PLUGIN_NUM_INPUTS 0
#define DISTRHO_PLUGIN_NUM_OUTPUTS 1
#define DISTRHO_PLUGIN_WANT_MIDI_INPUT 1
#define DISTRHO_PLUGIN_WANT_MIDI_OUTPUT 0

#endif // DISTRHO_PLUGIN_INFO_H_INCLUDED

+ 46
- 0
examples/SendNote/Makefile View File

@@ -0,0 +1,46 @@
#!/usr/bin/make -f
# Makefile for DISTRHO Plugins #
# ---------------------------- #
# Created by falkTX
#

# --------------------------------------------------------------
# Project name, used for binaries

NAME = d_sendNote

# --------------------------------------------------------------
# Files to build

FILES_DSP = \
SendNoteExamplePlugin.cpp


FILES_UI = \
SendNoteExampleUI.cpp

# --------------------------------------------------------------
# Do some magic

include ../../Makefile.plugins.mk

# --------------------------------------------------------------
# Enable all possible plugin types

ifeq ($(HAVE_JACK),true)
ifeq ($(HAVE_OPENGL),true)
TARGETS += jack
endif
endif

ifeq ($(HAVE_OPENGL),true)
TARGETS += lv2_sep
else
TARGETS += lv2_dsp
endif

TARGETS += vst

all: $(TARGETS)

# --------------------------------------------------------------

+ 6
- 0
examples/SendNote/README.md View File

@@ -0,0 +1,6 @@
# SendNote example

This example will show how to send MIDI notes in DPF based UIs.<br/>

The UI presents a row of MIDI keys which transmit note events to a synthesizer.


+ 192
- 0
examples/SendNote/SendNoteExamplePlugin.cpp View File

@@ -0,0 +1,192 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
* permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "DistrhoPlugin.hpp"
#include <cmath>
#include <cstring>
START_NAMESPACE_DISTRHO
// -----------------------------------------------------------------------------------------------------------
/**
Plugin that demonstrates sending notes from the editor in DPF.
*/
class SendNoteExamplePlugin : public Plugin
{
public:
SendNoteExamplePlugin()
: Plugin(0, 0, 0)
{
std::memset(fNotesPlayed, 0, sizeof(fNotesPlayed));
std::memset(fOscillatorPhases, 0, sizeof(fOscillatorPhases));
}
protected:
/* --------------------------------------------------------------------------------------------------------
* Information */
/**
Get the plugin label.
This label is a short restricted name consisting of only _, a-z, A-Z and 0-9 characters.
*/
const char* getLabel() const override
{
return "SendNote";
}
/**
Get an extensive comment/description about the plugin.
*/
const char* getDescription() const override
{
return "Plugin that demonstrates sending notes from the editor in DPF.";
}
/**
Get the plugin author/maker.
*/
const char* getMaker() const override
{
return "DISTRHO";
}
/**
Get the plugin homepage.
*/
const char* getHomePage() const override
{
return "https://github.com/DISTRHO/DPF";
}
/**
Get the plugin license name (a single line of text).
For commercial plugins this should return some short copyright information.
*/
const char* getLicense() const override
{
return "ISC";
}
/**
Get the plugin version, in hexadecimal.
*/
uint32_t getVersion() const override
{
return d_version(1, 0, 0);
}
/**
Get the plugin unique Id.
This value is used by LADSPA, DSSI and VST plugin formats.
*/
int64_t getUniqueId() const override
{
return d_cconst('d', 'S', 'N', 'o');
}
/* --------------------------------------------------------------------------------------------------------
* Init and Internal data, unused in this plugin */
void initParameter(uint32_t, Parameter&) override {}
float getParameterValue(uint32_t) const override { return 0.0f;}
void setParameterValue(uint32_t, float) override {}
/* --------------------------------------------------------------------------------------------------------
* Audio/MIDI Processing */
/**
Run/process function for plugins with MIDI input.
This synthesizes the MIDI voices with a sum of sine waves.
*/
void run(const float**, float** outputs, uint32_t frames,
const MidiEvent* midiEvents, uint32_t midiEventCount) override
{
for (uint32_t i = 0; i < midiEventCount; ++i)
{
if (midiEvents[i].size <= 3)
{
uint8_t status = midiEvents[i].data[0];
uint8_t note = midiEvents[i].data[1] & 127;
uint8_t velocity = midiEvents[i].data[2] & 127;
switch (status & 0xf0)
{
case 0x90:
if (velocity != 0)
{
fNotesPlayed[note] = velocity;
break;
}
/* fall through */
case 0x80:
fNotesPlayed[note] = 0;
fOscillatorPhases[note] = 0;
break;
}
}
}
float* const output = outputs[0];
std::memset(output, 0, frames * sizeof(float));
for (uint32_t noteNumber = 0; noteNumber < 128; ++noteNumber)
{
if (fNotesPlayed[noteNumber] == 0)
continue;
float notePitch = 8.17579891564 * std::exp(0.0577622650 * noteNumber);
float phase = fOscillatorPhases[noteNumber];
float timeStep = notePitch / getSampleRate();
float k2pi = 2.0 * M_PI;
float gain = 0.1;
for (uint32_t i = 0; i < frames; ++i)
{
output[i] += gain * std::sin(k2pi * phase);
phase += timeStep;
phase -= (int)phase;
}
fOscillatorPhases[noteNumber] = phase;
}
}
// -------------------------------------------------------------------------------------------------------
private:
uint8_t fNotesPlayed[128];
float fOscillatorPhases[128];
/**
Set our plugin class as non-copyable and add a leak detector just in case.
*/
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SendNoteExamplePlugin)
};
/* ------------------------------------------------------------------------------------------------------------
* Plugin entry point, called by DPF to create a new plugin instance. */
Plugin* createPlugin()
{
return new SendNoteExamplePlugin();
}
// -----------------------------------------------------------------------------------------------------------
END_NAMESPACE_DISTRHO

+ 172
- 0
examples/SendNote/SendNoteExampleUI.cpp View File

@@ -0,0 +1,172 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
* permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#include "DistrhoUI.hpp"

#include "Color.hpp"

#include <cstring>

START_NAMESPACE_DISTRHO

/**
We need the rectangle class from DGL.
*/
using DGL_NAMESPACE::Rectangle;

// -----------------------------------------------------------------------------------------------------------

class SendNoteExampleUI : public UI
{
public:
SendNoteExampleUI()
: UI(64*12+8, 64+8),
fLastKey(-1)
{
std::memset(fKeyState, 0, sizeof(fKeyState));
}

protected:
/* --------------------------------------------------------------------------------------------------------
* DSP/Plugin Callbacks */

/**
A parameter has changed on the plugin side.
This is called by the host to inform the UI about parameter changes.
*/
void parameterChanged(uint32_t index, float value) override
{
(void)index;
(void)value;
}

/* --------------------------------------------------------------------------------------------------------
* Widget Callbacks */

/**
The OpenGL drawing function.
This UI will draw a row of 12 keys, with on/off states according to pressed status.
*/
void onDisplay() override
{
const GraphicsContext& context(getGraphicsContext());

for (int key = 0; key < 12; ++key)
{
bool pressed = fKeyState[key];
Rectangle<int> bounds = getKeyBounds(key);

if (pressed)
Color(0.8f, 0.5f, 0.3f).setFor(context);
else
Color(0.3f, 0.5f, 0.8f).setFor(context);

bounds.draw(context);
}
}

/**
Mouse press event.
This UI will de/activate keys when you click them and reports it as MIDI note events to the plugin.
*/
bool onMouse(const MouseEvent& ev) override
{
// Test for last key release first
if (fLastKey != -1 && ! ev.press)
{
// Send a note event. Velocity=0 means off
sendNote(0, kNoteOctaveStart+fLastKey, 0);
// Unset key state
fKeyState[fLastKey] = false;
fLastKey = -1;
repaint();
return true;
}

// Test for left-clicked first.
if (ev.button != 1)
return false;

// Find the key which is pressed, if any
int whichKey = -1;
for (int key = 0; key < 12 && whichKey == -1; ++key)
{
Rectangle<int> bounds = getKeyBounds(key);

if (bounds.contains(ev.pos))
whichKey = key;
}

if (whichKey == -1)
return false;
if (fKeyState[whichKey] == ev.press)
return false;

// Send a note event. Velocity=0 means off
sendNote(0, kNoteOctaveStart+whichKey, ev.press ? kNoteVelocity : 0);

// Set pressed state of this key, and update display
fLastKey = whichKey;
fKeyState[whichKey] = ev.press;
repaint();

return true;
}

/**
Set our UI class as non-copyable and add a leak detector just in case.
*/
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SendNoteExampleUI)

private:
/**
Get the bounds of a particular key of the virtual MIDI keyboard.
*/
Rectangle<int> getKeyBounds(unsigned index) const
{
Rectangle<int> bounds;
int padding = 8;
bounds.setX(64 * index + padding);
bounds.setY(padding);
bounds.setWidth(64 - padding);
bounds.setHeight(64 - padding);
return bounds;
}

/**
The pressed state of one octave of a virtual MIDI keyboard.
*/
bool fKeyState[12];
int8_t fLastKey;

enum
{
kNoteVelocity = 100, // velocity of sent Note-On events
kNoteOctaveStart = 60, // starting note of the virtual MIDI keyboard
};
};

/* ------------------------------------------------------------------------------------------------------------
* UI entry point, called by DPF to create a new UI instance. */

UI* createUI()
{
return new SendNoteExampleUI();
}

// -----------------------------------------------------------------------------------------------------------

END_NAMESPACE_DISTRHO

Loading…
Cancel
Save