LMMS
Loading...
Searching...
No Matches
Lb302.h
Go to the documentation of this file.
1/*
2 * Lb302.h - Incomplete Roland TB-303 bass synth emulation
3 *
4 * Copyright (c) 2006-2008 Paul Giblock <pgib/at/users.sourceforge.net>
5 * Copyright (c) 2026 Fawn Sannar <rubiefawn/at/gmail.com>
6 *
7 * This file is part of LMMS - https://lmms.io
8 *
9 * Lb302FilterIIR2 is based on the gsyn filter code by Andy Sloane.
10 *
11 * Lb302Filter3Pole is based on the TB-303 instrument written by
12 * Josep M Comajuncosas for the CSounds library
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public
16 * License as published by the Free Software Foundation; either
17 * version 2 of the License, or (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public
25 * License along with this program (see COPYING); if not, write to the
26 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
27 * Boston, MA 02110-1301 USA.
28 *
29 */
30
31#ifndef LB302_H
32#define LB302_H
33
34#include <array>
35#include <atomic>
36#include <memory>
37
38#include "Hardware.h"
39#include "Instrument.h"
40#include "InstrumentView.h"
41#include "NotePlayHandle.h"
42
43namespace lmms
44{
45
46namespace DspEffectLibrary { class Distortion; }
47
48namespace gui
49{
51class Knob;
52class Lb302SynthView;
53class LedCheckBox;
54}
55
56
58{
59 float cutoff;
60 float reso;
61 float envmod;
62 float envdecay;
63 float dist;
64};
65
66
68{
69public:
71 virtual ~Lb302Filter() = default;
72
73 virtual void recalc();
74 virtual void envRecalc();
75 virtual void playNote();
76 virtual sample_t process(sample_t samp) = 0;
77
78protected:
80
81 // Filter Decay
82 struct
83 {
84 float c0 = 0.f;
85 std::array<float, 2> e = {0.f, 0.f};
86 float resCoeff;
88};
89
90
92{
93public:
95
96 void recalc() override;
97 void envRecalc() override;
98 sample_t process(sample_t samp) override;
99
100protected:
101 struct
102 {
106 std::array<float, 2> d = {0.f, 0.f};
107
108 // IIR2 Coefficients for mixing dry and delay. Mixing coefficients for the final sound.
109 float a = 0.f;
110 float b = 0.f;
111 float c = 1.f;
113
114 std::unique_ptr<DspEffectLibrary::Distortion> m_dist;
115};
116
117
119{
120public:
122
123 void envRecalc() override;
124 void recalc() override;
125 sample_t process(sample_t samp) override;
126
127protected:
128 float m_kfcn;
129 float m_kp;
130 float m_kp1h;
131 float m_kres;
132 std::array<sample_t, 3> m_ay = { 0.f, 0.f, 0.f };
133 float m_lastin = 0.f;
134 float m_value;
135};
136
137
138class Lb302Synth : public Instrument
139{
140 Q_OBJECT
142
143public:
145 void play(SampleFrame* working_buffer) override;
146 void playNote(NotePlayHandle* nph, SampleFrame* working_buffer) override;
147 void deleteNotePluginData(NotePlayHandle* nph) override;
148 void saveSettings(QDomDocument& doc, QDomElement& el) override;
149 void loadSettings(const QDomElement& el) override;
150 QString nodeName() const override;
151 gui::PluginView* instantiateView(QWidget* parent) override;
152
153public slots:
154 void filterChanged();
155
157 void decayChanged();
158
159 void db24Toggled();
160
161private:
162 void processNote(NotePlayHandle* nph);
163 void process(SampleFrame* outbuf, const f_cnt_t size);
164 void recalcFilter();
165
169
170 static constexpr float s_distRatio = 4.f;
171 static constexpr f_cnt_t s_envInc = 64;
172 static constexpr float s_vcaAttack = 1.f - 0.96406088f;
173 static constexpr float s_vcaInitial = 0.5f;
174
180
184
189
190 // Oscillator
191 float m_vcoInc = 0.f;
192 float m_vcoK = 0.f;
193 float m_vcoC = 0.f;
194
195 bool m_newFreq = false;
196 float m_trueFreq = 0.f;
197 float m_slide = 0.f;
198 float m_slideInc = 0.f;
199 float m_slideBase = 0.f;
200
202
203 // User settings
205
206 std::array<std::unique_ptr<Lb302Filter>, 2> m_vcfs;
207
211 Lb302Filter& vcf() { return *m_vcfs[m_db24Toggle.value()]; }
212
215
216 // Envelope State
217 float m_vca = 0.f;
218 float m_noteVolume = 1.f;
221
223
232 static constexpr std::size_t s_maxPendingNotes = 128;
233 static_assert(std::has_single_bit(s_maxPendingNotes)); // s_maxPendingNotes MUST be a power of 2
234
249 static constexpr std::size_t s_maxNoteEnqueueRetries = s_maxPendingNotes;
250
256 static constexpr std::size_t s_notesBufMask = s_maxPendingNotes - 1;
257
267 std::array<NotePlayHandle*, s_maxPendingNotes> m_notes {};
268
281
295
308};
309
310
311namespace gui
312{
313
314
316{
317 Q_OBJECT
318
319public:
320 Lb302SynthView(Instrument* instrument, QWidget* parent);
321 ~Lb302SynthView() override = default;
322
323private:
324 void modelChanged() override;
325
330
334
336 // LedCheckBox* m_accentToggle; // TODO: implement accent notes
339};
340
341
342} // namespace gui
343
344} // namespace lmms
345
346#endif // LB302_H
Definition noise.cpp:45
Definition AutomatableModel.h:497
Definition DspEffectLibrary.h:301
Definition AutomatableModel.h:463
Definition Instrument.h:52
Instrument(InstrumentTrack *_instrument_track, const Descriptor *_descriptor, const Descriptor::SubPluginFeatures::Key *key=nullptr, Flags flags=Flag::NoFlags)
Definition Instrument.cpp:38
Definition InstrumentTrack.h:62
Definition AutomatableModel.h:481
float m_kfcn
Definition Lb302.h:128
sample_t process(sample_t samp) override
Definition Lb302.cpp:199
float m_kres
Definition Lb302.h:131
float m_value
Definition Lb302.h:134
float m_kp
Definition Lb302.h:129
float m_kp1h
Cached value of (m_kp + 1) / 2.
Definition Lb302.h:130
Lb302Filter3Pole(Lb302FilterKnobState *p_fs)
Definition Lb302.h:121
std::array< sample_t, 3 > m_ay
Definition Lb302.h:132
void envRecalc() override
Definition Lb302.cpp:164
float m_lastin
Definition Lb302.h:133
void recalc() override
Definition Lb302.cpp:156
Definition Lb302.h:68
virtual ~Lb302Filter()=default
std::array< float, 2 > e
Two values for interpolation.
Definition Lb302.h:85
virtual sample_t process(sample_t samp)=0
virtual void recalc()
Definition Lb302.cpp:90
struct lmms::Lb302Filter::@046074133257322201173360347057124124216004105072 m_vcf
Lb302Filter(Lb302FilterKnobState *p_fs)
Definition Lb302.h:70
virtual void envRecalc()
Definition Lb302.cpp:103
virtual void playNote()
Definition Lb302.cpp:106
Lb302FilterKnobState * fs
Definition Lb302.h:79
float resCoeff
Resonance coefficient [0.30, 9.54]
Definition Lb302.h:86
float c0
c0 = e[1] on retrigger; c0 *=ed every sample; cutoff = e[0] + c0
Definition Lb302.h:84
Lb302FilterIIR2(Lb302FilterKnobState *p_fs)
Definition Lb302.cpp:113
sample_t process(sample_t samp) override
Definition Lb302.cpp:138
float c
Definition Lb302.h:111
std::unique_ptr< DspEffectLibrary::Distortion > m_dist
Definition Lb302.h:114
float a
Definition Lb302.h:109
struct lmms::Lb302FilterIIR2::@346123164351052165335065110147243267100110262132 m_iir2
void recalc() override
Definition Lb302.cpp:119
void envRecalc() override
Definition Lb302.cpp:126
std::array< float, 2 > d
IIR2 resonance loop. d[0] and d[1] are added back into the sample with a and b as coefficients.
Definition Lb302.h:106
float b
Definition Lb302.h:110
float m_vcoC
Raw oscillator sample [-0.5, 0.5].
Definition Lb302.h:193
static constexpr float s_distRatio
Definition Lb302.h:170
static constexpr std::size_t s_maxPendingNotes
The maximum number of note events Lb302 can process per audio buffer.
Definition Lb302.h:232
static constexpr std::size_t s_maxNoteEnqueueRetries
The maximum number of retries permitted per enqueue operation before a note is dropped.
Definition Lb302.h:249
void db24Toggled()
Definition Lb302.cpp:305
QString nodeName() const override
Definition Lb302.cpp:308
float m_noteVolume
The per-note volume (velocity) of the most recent note, within [0, 1].
Definition Lb302.h:218
float m_slideInc
Slide base to use in next node. Nonzero=slide next note.
Definition Lb302.h:198
void recalcFilter()
Definition Lb302.cpp:311
FloatModel m_vcoDetuneKnob
Definition Lb302.h:179
Lb302FilterKnobState m_fs
Definition Lb302.h:204
float m_slide
Current value of slide exponential curve. Nonzero=sliding.
Definition Lb302.h:197
FloatModel m_vcfCutKnob
Definition Lb302.h:175
std::array< NotePlayHandle *, s_maxPendingNotes > m_notes
Backing array for the multiple-producer single-consumer realtime-safe ring buffer queue for note even...
Definition Lb302.h:267
FloatModel m_vcfResKnob
Definition Lb302.h:176
float m_vcoInc
Sample increment for the frequency. Creates Sawtooth.
Definition Lb302.h:191
FloatModel m_slideDecKnob
Definition Lb302.h:183
void saveSettings(QDomDocument &doc, QDomElement &el) override
Definition Lb302.cpp:249
void loadSettings(const QDomElement &el) override
Definition Lb302.cpp:266
NotePlayHandle * m_playingNote
Definition Lb302.h:222
void filterChanged()
Definition Lb302.cpp:288
float m_slideBase
The base m_vcoInc while sliding.
Definition Lb302.h:199
Lb302Filter & vcf()
Helper to get current vcf.
Definition Lb302.h:211
f_cnt_t m_vcfEnvPos
Update counter. Updates when >= s_envInc.
Definition Lb302.h:213
void playNote(NotePlayHandle *nph, SampleFrame *working_buffer) override
Definition Lb302.cpp:498
f_cnt_t m_releaseFrame
Definition Lb302.h:214
IntModel m_waveShape
Definition Lb302.h:182
VcaMode m_vcaMode
Definition Lb302.h:220
void play(SampleFrame *working_buffer) override
Definition Lb302.cpp:574
std::atomic_size_t m_notesReadSeq
Sequence number indicating complete dequeue operations.
Definition Lb302.h:280
static constexpr std::size_t s_notesBufMask
Bitmask used to wrap arbitrary indicies within the bounds of m_notes.
Definition Lb302.h:256
void deleteNotePluginData(NotePlayHandle *nph) override
Definition Lb302.cpp:598
BoolModel m_deadToggle
Definition Lb302.h:187
BoolModel m_slideToggle
Definition Lb302.h:185
VcoShape m_vcoShape
Definition Lb302.h:201
gui::PluginView * instantiateView(QWidget *parent) override
Create a view for the model.
Definition Lb302.cpp:604
FloatModel m_distKnob
Definition Lb302.h:181
BoolModel m_accentToggle
Definition Lb302.h:186
static constexpr float s_vcaInitial
Initial amplifier coefficient.
Definition Lb302.h:173
float m_trueFreq
Definition Lb302.h:196
static constexpr float s_vcaAttack
Amplitude attack.
Definition Lb302.h:172
float m_vca
Amplifier coefficient.
Definition Lb302.h:217
FloatModel m_vcfDecKnob
Definition Lb302.h:178
panning_t m_notePan
The per-note panning of the most recent note.
Definition Lb302.h:219
static constexpr f_cnt_t s_envInc
Envelope Recalculation period
Definition Lb302.h:171
void processNote(NotePlayHandle *nph)
Definition Lb302.cpp:545
bool m_newFreq
Definition Lb302.h:195
BoolModel m_db24Toggle
Definition Lb302.h:188
void process(SampleFrame *outbuf, const f_cnt_t size)
Definition Lb302.cpp:318
Lb302Synth(InstrumentTrack *)
Definition Lb302.cpp:216
std::atomic_size_t m_notesWriteClaimed
Sequence number indicating in-progress enqueue operations.
Definition Lb302.h:307
std::array< std::unique_ptr< Lb302Filter >, 2 > m_vcfs
Filters (just keep both loaded and switch).
Definition Lb302.h:206
VcaMode
Definition Lb302.h:168
@ Decay
Definition Lb302.h:168
@ Attack
Definition Lb302.h:168
@ Idle
Definition Lb302.h:168
@ NeverPlayed
Definition Lb302.h:168
void decayChanged()
Adjusts m_fs 's Lb302FilterKnobState::envdecay for both sampling rate and s_envInc.
Definition Lb302.cpp:298
FloatModel m_vcfModKnob
Definition Lb302.h:177
float m_vcoK
Raw oscillator sample [-0.5, 0.5].
Definition Lb302.h:192
std::atomic_size_t m_notesWriteCommitted
Sequence number indicating complete enqueue operations.
Definition Lb302.h:294
VcoShape
Definition Lb302.h:166
@ BLSquare
Definition Lb302.h:167
@ BLTriangle
Definition Lb302.h:167
@ Moog
Definition Lb302.h:166
@ Triangle
Definition Lb302.h:166
@ Sine
Definition Lb302.h:166
@ RoundSquare
Definition Lb302.h:166
@ BLMoog
Definition Lb302.h:167
@ Exponential
Definition Lb302.h:166
@ Sawtooth
Definition Lb302.h:166
@ Square
Definition Lb302.h:166
@ BLSawtooth
Definition Lb302.h:167
Definition NotePlayHandle.h:48
Definition SampleFrame.h:41
Definition AutomatableButton.h:84
Instrument view with fixed LMMS-default size.
Definition InstrumentView.h:66
Definition Knob.h:47
Definition Lb302.h:316
Knob * m_vcfResKnob
Definition Lb302.h:327
Knob * m_vcfCutKnob
Definition Lb302.h:326
Lb302SynthView(Instrument *instrument, QWidget *parent)
Definition Lb302.cpp:618
LedCheckBox * m_slideToggle
Definition Lb302.h:335
Knob * m_vcfModKnob
Definition Lb302.h:329
Knob * m_distKnob
Definition Lb302.h:331
Knob * m_vcfDecKnob
Definition Lb302.h:328
LedCheckBox * m_db24Toggle
Definition Lb302.h:338
void modelChanged() override
Definition Lb302.cpp:757
AutomatableButtonGroup * m_waveBtnGrp
Definition Lb302.h:333
LedCheckBox * m_deadToggle
Definition Lb302.h:337
~Lb302SynthView() override=default
Knob * m_slideDecKnob
Definition Lb302.h:332
Definition LedCheckBox.h:37
Definition PluginView.h:36
unsigned el
Definition inflate.c:1571
static uintptr_t parent
Definition pugl.h:1644
Definition DspEffectLibrary.h:35
Definition AudioPortAudio.cpp:209
Definition AudioAlsa.cpp:35
constexpr panning_t DefaultPanning
Definition panning.h:41
float sample_t
Definition LmmsTypes.h:39
constexpr std::size_t hardware_destructive_interference_size
Platform-dependent minimum amount of padding between objects to prevent false cache sharing.
Definition Hardware.h:60
std::int8_t panning_t
Definition LmmsTypes.h:37
std::uint64_t f_cnt_t
Definition LmmsTypes.h:43
GUI::ui_handle_t gui
Definition main.cpp:50
Definition Lb302.h:58
float dist
Definition Lb302.h:63
float cutoff
Definition Lb302.h:59
float reso
Definition Lb302.h:60
float envmod
Definition Lb302.h:61
float envdecay
Definition Lb302.h:62
ulg size
Definition extract.c:2350