LMMS
Loading...
Searching...
No Matches
DistrhoPluginKars.cpp
Go to the documentation of this file.
1/*
2 * DISTRHO Kars Plugin, based on karplong by Chris Cannam.
3 * Copyright (C) 2015-2019 Filipe Coelho <falktx@falktx.com>
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any purpose with
6 * or without fee is hereby granted, provided that the above copyright notice and this
7 * permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
10 * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
11 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
13 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "DistrhoPluginKars.hpp"
18#include "DistrhoPluginUtils.hpp"
19
21
22// -----------------------------------------------------------------------
23
24DistrhoPluginKars::DistrhoPluginKars()
25 : Plugin(paramCount, 0, 0), // 0 programs, 0 states
26 fSustain(false),
27 fRelease(0.01),
28 fVolume(75.0f),
29 fSampleRate(getSampleRate()),
30 fBlockStart(0)
31{
32 for (int i=kMaxNotes; --i >= 0;)
33 {
34 fNotes[i].voice = i;
35 fNotes[i].setSampleRate(fSampleRate);
36 }
37}
38
39// -----------------------------------------------------------------------
40// Init
41
42void DistrhoPluginKars::initParameter(uint32_t index, Parameter& parameter)
43{
44 switch (index)
45 {
46 case paramSustain:
47 parameter.hints = kParameterIsAutomatable|kParameterIsBoolean;
48 parameter.name = "Sustain";
49 parameter.symbol = "sustain";
50 parameter.ranges.def = 0.0f;
51 parameter.ranges.min = 0.0f;
52 parameter.ranges.max = 1.0f;
53 break;
54 case paramRelease:
55 parameter.hints = kParameterIsAutomatable;
56 parameter.name = "Release";
57 parameter.symbol = "release";
58 parameter.unit = "s";
59 parameter.ranges.def = 0.01f;
60 parameter.ranges.min = 0.0f;
61 parameter.ranges.max = 5.0f;
62 break;
63 case paramVolume:
64 parameter.hints = kParameterIsAutomatable;
65 parameter.name = "Volume";
66 parameter.symbol = "volume";
67 parameter.unit = "%";
68 parameter.ranges.def = 75.0f;
69 parameter.ranges.min = 0.0f;
70 parameter.ranges.max = 100.0f;
71 break;
72 }
73}
74
75// -----------------------------------------------------------------------
76// Internal data
77
78float DistrhoPluginKars::getParameterValue(uint32_t index) const
79{
80 switch (index)
81 {
82 case paramSustain: return fSustain ? 1.0f : 0.0f;
83 case paramRelease: return fRelease;
84 case paramVolume: return fVolume;
85 }
86
87 return 0.0f;
88}
89
90void DistrhoPluginKars::setParameterValue(uint32_t index, float value)
91{
92 switch (index)
93 {
94 case paramSustain:
95 fSustain = value > 0.5f;
96 break;
97 case paramRelease:
98 fRelease = value;
99 break;
100 case paramVolume:
101 fVolume = value;
102 break;
103 }
104}
105
106// -----------------------------------------------------------------------
107// Process
108
109void DistrhoPluginKars::activate()
110{
111 fBlockStart = 0;
112
113 for (int i=kMaxNotes; --i >= 0;)
114 {
115 fNotes[i].on = kNoteNull;
116 fNotes[i].off = kNoteNull;
117 fNotes[i].velocity = 0;
118 }
119}
120
121void DistrhoPluginKars::run(const float**, float** outputs, uint32_t frames, const MidiEvent* midiEvents, uint32_t midiEventCount)
122{
123 uint8_t note, velo;
124 std::memset(outputs[0], 0, sizeof(float)*frames);
125
126 for (AudioMidiSyncHelper amsh(outputs, frames, midiEvents, midiEventCount); amsh.nextEvent();)
127 {
128 for (uint32_t i=0; i<amsh.midiEventCount; ++i)
129 {
130 if (amsh.midiEvents[i].size > MidiEvent::kDataSize)
131 continue;
132
133 const uint8_t* data = amsh.midiEvents[i].data;
134 const uint8_t status = data[0] & 0xF0;
135
136 switch (status)
137 {
138 case 0x90:
139 note = data[1];
140 velo = data[2];
141 DISTRHO_SAFE_ASSERT_BREAK(note < 128); // kMaxNotes
142 if (velo > 0)
143 {
144 fNotes[note].on = fBlockStart;
145 fNotes[note].off = kNoteNull;
146 fNotes[note].velocity = velo;
147 break;
148 }
149 // fall through
150 case 0x80:
151 note = data[1];
152 DISTRHO_SAFE_ASSERT_BREAK(note < 128); // kMaxNotes
153 fNotes[note].off = fBlockStart;
154 break;
155 }
156 }
157
158 float* const out = amsh.outputs[0];
159
160 for (int i=kMaxNotes; --i >= 0;)
161 {
162 if (fNotes[i].on != kNoteNull)
163 addSamples(out, i, amsh.frames);
164 }
165
166 fBlockStart += amsh.frames;
167 }
168}
169
170void DistrhoPluginKars::addSamples(float* out, int voice, uint32_t frames)
171{
172 const uint32_t start = fBlockStart;
173
174 Note& note(fNotes[voice]);
175
176 if (start < note.on)
177 return;
178
179 if (start == note.on)
180 {
181 for (int i=note.sizei; --i >= 0;)
182 note.wavetable[i] = (float(rand()) / float(RAND_MAX)) * 2.0f - 1.0f;
183 }
184
185 const float vgain = float(note.velocity) / 127.0f;
186
187 bool decay;
188 float gain, sample;
189 uint32_t index, size;
190
191 for (uint32_t i=0, s=start-note.on; i<frames; ++i, ++s)
192 {
193 gain = vgain;
194
195 if ((! fSustain) && note.off != kNoteNull && note.off < i+start)
196 {
197 // reuse index and size to save some performance.
198 // actual values are release and dist
199 index = 1 + uint32_t(fRelease * fSampleRate); // release, not index
200 size = i + start - note.off; // dist, not size
201
202 if (size > index)
203 {
204 note.on = kNoteNull;
205 break;
206 }
207
208 gain = gain * float(index - size) / float(index);
209 }
210
211 size = uint32_t(note.sizei);
212 decay = s > size;
213 index = s % size;
214
215 sample = note.wavetable[index];
216
217 if (decay)
218 {
219 if (index == 0)
220 sample += note.wavetable[size-1];
221 else
222 sample += note.wavetable[index-1];
223
224 note.wavetable[index] = sample/2;
225 }
226
227 out[i] += gain * sample * (fVolume / 100.0f);
228 }
229}
230
231// -----------------------------------------------------------------------
232
234{
235 return new DistrhoPluginKars();
236}
237
238// -----------------------------------------------------------------------
239
#define END_NAMESPACE_DISTRHO
Definition DistrhoDefines.h:191
#define START_NAMESPACE_DISTRHO
Definition DistrhoDefines.h:190
#define DISTRHO_SAFE_ASSERT_BREAK(cond)
Definition DistrhoDefines.h:110
Plugin * createPlugin()
Definition DistrhoPluginKars.cpp:233
Definition basics.h:174
register unsigned i
Definition inflate.c:1575
unsigned s
Definition inflate.c:1555
static PuglViewHint int value
Definition pugl.h:1708
virtual ASIOError start()=0
virtual ASIOError getSampleRate(ASIOSampleRate *sampleRate)=0
JSAMPIMAGE data
Definition jpeglib.h:945
float out
Definition lilv_test.c:1461
unsigned int uint32_t
Definition mid.cpp:100
unsigned char uint8_t
Definition mid.cpp:98
#define false
Definition ordinals.h:83
Definition InMgr.h:16
signed int sample
Definition tap_dynamics_m.c:41
ulg size
Definition extract.c:2350