Anklang 0.3.0-460-gc4ef46ba
ASE — Anklang Sound Engine (C++)

« « « Anklang Documentation
Loading...
Searching...
No Matches
freeverb.cc
Go to the documentation of this file.
1 // This Source Code Form is licensed MPL-2.0: http://mozilla.org/MPL/2.0
2#include "ase/processor.hh"
3#include "ase/internal.hh"
5
6namespace {
7
8#include "revmodel.hpp"
9#include "revmodel.cpp"
10#include "allpass.cpp"
11#include "comb.cpp"
12
13using namespace Ase;
14
15class Freeverb : public AudioProcessor {
16 IBusId stereoin;
17 OBusId stereout;
18 revmodel model;
19 LinearSmooth mix_smooth_;
20 bool mix_smooth_reset_ = false;
21public:
22 Freeverb (const ProcessorSetup &psetup) :
23 AudioProcessor (psetup)
24 {}
25 static void
26 static_info (AudioProcessorInfo &info)
27 {
28 info.version = "1";
29 info.label = "Freeverb3";
30 info.category = "Reverb";
31 info.website_url = "https://beast.testbit.eu";
32 info.creator_name = "Jezar at Dreampoint";
33 }
34 enum Params { MODE = 1, MIX, ROOMSIZE, DAMPING, WIDTH };
35 void
36 initialize (SpeakerArrangement busses) override
37 {
39
40 stereoin = add_input_bus ("Stereo In", SpeakerArrangement::STEREO);
41 stereout = add_output_bus ("Stereo Out", SpeakerArrangement::STEREO);
42
43 ParameterMap pmap;
44
45 pmap.group = _("Reverb Settings");
46 pmap[MIX] = Param { "mix", "Mix dry/wet", "Mix", 30, "%", { 0, 100 } };
47
48 ChoiceS centries;
49 centries += { "Signflip 2000", _("Preserve May 2000 Freeverb damping sign flip") };
50 centries += { "VLC Damping", _("The VLC Freeverb version disables one damping feedback chain") };
51 centries += { "Normal Damping", _("Damping with sign correction as implemented in STK Freeverb") };
52 pmap[MODE] = Param ("mode", _("Mode"), _("Mode"), 2, "", std::move (centries), "",
53 { String ("blurb=") + _("Damping mode found in different Freeverb variants"), });
54
55 pmap.group = _("Room Settings");
56 pmap[ROOMSIZE] = Param ("roomsize", _("Room size"), _("RS"), offsetroom + scaleroom * initialroom, _("size"), { offsetroom, offsetroom + scaleroom });
57 pmap[WIDTH] = Param ("width", _("Width"), _("W"), 100 * initialwidth, "%", { 0, 100 });
58 pmap[DAMPING] = Param ("damping", _("Damping"), _("D"), 100 * initialdamp, "%", { 0, 100 });
59
60 install_params (pmap);
61 }
62 void
63 adjust_param (uint32_t paramid) override
64 {
65 switch (Params (paramid))
66 {
67 case MIX: mix_smooth_.set (get_param (paramid) * 0.01, mix_smooth_reset_);
68 mix_smooth_reset_ = false;
69 break;
70 case ROOMSIZE: return model.setroomsize ((get_param (paramid) - offsetroom) / scaleroom);
71 case WIDTH: return model.setwidth (0.01 * get_param (paramid));
72 case MODE:
73 case DAMPING: return model.setdamp (0.01 * get_param (ParamId (DAMPING)),
74 1 - irintf (get_param (ParamId (MODE))));
75 }
76 }
77 void
78 reset (uint64 target_stamp) override
79 {
80 model.setmode (0); // no-freeze, allow mute
81 model.setdry (0); // no dry, we mix the output signal during render
82 model.setwet (1); // only need reverb wet
83 model.mute(); // silence internal buffers
84 mix_smooth_.reset (sample_rate(), 0.020);
85 mix_smooth_reset_ = true;
86 adjust_all_params();
87 }
88 void
89 render_audio (float *input0, float *input1, float *output0, float *output1, uint n_frames)
90 {
91 if (!n_frames)
92 return;
93
94 // this only generates the wet signal
95 model.processreplace (input0, input1, output0, output1, n_frames, 1);
96
97 if (mix_smooth_.is_constant()) // faster version: mix parameter is constant during the block
98 {
99 float mix = mix_smooth_.get_next();
100 for (uint i = 0; i < n_frames; i++)
101 {
102 output0[i] = input0[i] * (1 - mix) + output0[i] * mix;
103 output1[i] = input1[i] * (1 - mix) + output1[i] * mix;
104 }
105 }
106 else
107 {
108 for (uint i = 0; i < n_frames; i++)
109 {
110 float mix = mix_smooth_.get_next();
111 output0[i] = input0[i] * (1 - mix) + output0[i] * mix;
112 output1[i] = input1[i] * (1 - mix) + output1[i] * mix;
113 }
114 }
115 }
116 void
117 render (uint n_frames) override
118 {
119 float *input0 = const_cast<float*> (ifloats (stereoin, 0));
120 float *input1 = const_cast<float*> (ifloats (stereoin, 1));
121 float *output0 = oblock (stereout, 0);
122 float *output1 = oblock (stereout, 1);
123
124 uint offset = 0;
125 MidiEventInput evinput = midi_event_input();
126 for (const auto &ev : evinput)
127 {
128 // process any audio that is before the event
129 render_audio (input0 + offset, input1 + offset, output0 + offset, output1 + offset, ev.frame - offset);
130 offset = ev.frame;
131
132 switch (ev.message())
133 {
134 case MidiMessage::PARAM_VALUE:
135 apply_event (ev);
136 adjust_param (ev.param);
137 break;
138 default: ;
139 }
140 }
141 // process frames after last event
142 render_audio (input0 + offset, input1 + offset, output0 + offset, output1 + offset, n_frames - offset);
143 }
144};
145static auto freeverb = register_audio_processor<Freeverb> ("Ase::Devices::Freeverb");
146
147} // Anon
Audio signal AudioProcessor base class, implemented by all effects and instruments.
Definition processor.hh:76
void remove_all_buses()
Remove existing bus configurations, useful at the start of configure().
Definition processor.cc:646
const float * ifloats(IBusId b, uint c) const
Access readonly float buffer of input bus b, channel c, see also ofloats().
Definition processor.hh:546
MidiEventInput midi_event_input()
Access the current MidiEvent inputs during render(), needs prepare_event_input().
Definition processor.cc:844
OBusId add_output_bus(CString uilabel, SpeakerArrangement speakerarrangement, const String &hints="", const String &blurb="")
Add an output bus with uilabel and channels configured via speakerarrangement.
Definition processor.cc:530
virtual void initialize(SpeakerArrangement busses)=0
Definition processor.cc:432
void apply_event(const MidiEvent &event)
Assign MidiEvent::PARAM_VALUE event values to parameters.
Definition processor.hh:387
IBusId add_input_bus(CString uilabel, SpeakerArrangement speakerarrangement, const String &hints="", const String &blurb="")
Add an input bus with uilabel and channels configured via speakerarrangement.
Definition processor.cc:510
void install_params(const AudioParams::Map &params)
Reset list of parameters, enqueues parameter value initializaiton events.
Definition processor.cc:213
float * oblock(OBusId b, uint c)
Definition processor.hh:561
#define _(...)
Retrieve the translation of a C or C++ string.
Definition internal.hh:18
The Anklang C++ API namespace.
Definition api.hh:9
CString website_url
Website of/about this AudioProcessor.
Definition processor.hh:35
uint64_t uint64
A 64-bit unsigned integer, use PRI*64 in format strings.
Definition cxxaux.hh:25
IBusId
ID type for AudioProcessor input buses, buses are numbered with increasing index.
Definition processor.hh:21
SpeakerArrangement
Definition transport.hh:11
OBusId
ID type for AudioProcessor output buses, buses are numbered with increasing index.
Definition processor.hh:25
CString version
Version identifier.
Definition processor.hh:31
ParamId
ID type for AudioProcessor parameters, the ID numbers are user assignable.
Definition processor.hh:17
CString creator_name
Name of the creator.
Definition processor.hh:36
CString label
Preferred user interface name.
Definition processor.hh:30
std::string String
Convenience alias for std::string.
Definition cxxaux.hh:35
int irintf(float f)
Definition mathutils.hh:14
uint32_t uint
Provide 'uint' as convenience type.
Definition cxxaux.hh:18
CString category
Category to allow grouping for processors of similar function.
Definition processor.hh:32
Detailed information and common properties of AudioProcessor subclasses.
Definition processor.hh:29
Structured initializer for Parameter.
Definition parameter.hh:31
Parameter list construction helper.
Definition parameter.hh:93
String group
Group to be applied to all newly inserted Parameter objects.
Definition parameter.hh:95