1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
|
/************************************************************************
IMPORTANT NOTE : this file contains two clearly delimited sections :
the ARCHITECTURE section (in two parts) and the USER section. Each section
is governed by its own copyright and license. Please check individually
each section for license and copyright information.
*************************************************************************/
/*******************BEGIN ARCHITECTURE SECTION (part 1/2)****************/
/************************************************************************
FAUST Architecture File
Copyright (C) 2003-2019 GRAME, Centre National de Creation Musicale
---------------------------------------------------------------------
This Architecture section is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 3 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; If not, see <http://www.gnu.org/licenses/>.
EXCEPTION : As a special exception, you may create a larger work
that contains this FAUST architecture section and distribute
that work under terms of your choice, so long as this FAUST
architecture section is not modified.
************************************************************************
************************************************************************/
// faust -a dplug.d -lang dlang noise.dsp -o noise.d
import dplug.core.vec;
import dplug.client;
import core.stdc.stdlib : strtol;
alias FAUSTFLOAT = float;
class Meta {
nothrow:
@nogc:
void declare(string name, string value) {}
}
class UI {
nothrow:
@nogc:
void declare(string id, string key, string value) {}
void declare(int id, string key, string value) {}
void declare(FAUSTFLOAT* id, string key, string value) {}
// -- layout groups
void openTabBox(string label) {}
void openHorizontalBox(string label) {}
void openVerticalBox(string label) {}
void closeBox() {}
// -- active widgets
void addButton(string label, FAUSTFLOAT* val) {}
void addCheckButton(string label, FAUSTFLOAT* val) {}
void addVerticalSlider(string label, FAUSTFLOAT* val, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) {}
void addHorizontalSlider(string label, FAUSTFLOAT* val, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) {}
void addNumEntry(string label, FAUSTFLOAT* val, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) {}
// -- passive display widgets
void addHorizontalBargraph(string label, FAUSTFLOAT* val, FAUSTFLOAT min, FAUSTFLOAT max) {}
void addVerticalBargraph(string label, FAUSTFLOAT* val, FAUSTFLOAT min, FAUSTFLOAT max) {}
}
interface dsp {
nothrow:
@nogc:
public:
void metadata(Meta* m);
int getNumInputs();
int getNumOutputs();
void buildUserInterface(UI* uiInterface);
int getSampleRate();
void instanceInit(int sample_rate);
void instanceResetUserInterface();
void compute(int count, FAUSTFLOAT*[] inputs, FAUSTFLOAT*[] outputs);
void initialize(int sample_rate);
}
/**
* Implements and overrides the methods that would provide parameters for use in
* a plug-in or GUI. These parameters are stored in a vector which can be accesed via
* `readParams()`
*/
class FaustParamAccess : UI {
nothrow:
@nogc:
this()
{
_faustParams = makeVec!FaustParam();
}
override void declare(FAUSTFLOAT* id, string key, string value)
{
if (value == "")
{
nextParamId = cast(int)strtol(key.ptr, null, 0);
}
else if (key == "unit")
{
nextParamUnit = value;
}
}
override void addButton(string label, FAUSTFLOAT* val)
{
_faustParams.pushBack(FaustParam(label, nextParamUnit, val, 0, 0, 0, 0, true, nextParamId));
resetNextParamMeta();
}
override void addCheckButton(string label, FAUSTFLOAT* val)
{
_faustParams.pushBack(FaustParam(label, nextParamUnit, val, 0, 0, 0, 0, true, nextParamId));
resetNextParamMeta();
}
override void addVerticalSlider(string label, FAUSTFLOAT* val, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step)
{
_faustParams.pushBack(FaustParam(label, nextParamUnit, val, init, min, max, step, false, nextParamId));
resetNextParamMeta();
}
override void addHorizontalSlider(string label, FAUSTFLOAT* val, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step)
{
_faustParams.pushBack(FaustParam(label, nextParamUnit, val, init, min, max, step, false, nextParamId));
resetNextParamMeta();
}
override void addNumEntry(string label, FAUSTFLOAT* val, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step)
{
_faustParams.pushBack(FaustParam(label, nextParamUnit, val, init, min, max, step, false, nextParamId));
resetNextParamMeta();
}
FaustParam[] readParams()
{
/* return _faustParams.releaseData(); */
/* Vec!FaustParam _sortedList = makeVec!FaustParam(); */
return sortParams(_faustParams.releaseData());
}
FaustParam readParam(int index)
{
return _faustParams[index];
}
ulong length()
{
return _faustParams.length();
}
private:
Vec!FaustParam _faustParams;
int nextParamId = -1;
string nextParamUnit = "";
void resetNextParamMeta()
{
nextParamId = -1;
nextParamUnit = "";
}
// simple bubble sort
FaustParam[] sortParams(FaustParam[] params)
{
bool success = true;
do
{
success = true;
for(int i = 0; i < params.length - 1; ++i)
{
auto left = params[i];
auto right = params[i + 1];
if (right.ParamId < left.ParamId)
{
params[i] = right;
params[i + 1] = left;
success = false;
}
}
}
while(!success);
return params;
}
}
struct FaustParam
{
string label;
string unit;
FAUSTFLOAT* val;
FAUSTFLOAT initial;
FAUSTFLOAT min;
FAUSTFLOAT max;
FAUSTFLOAT step;
bool isButton = false;
int ParamId;
}
version(unittest){}
version(faustoverride){}
else
mixin(pluginEntryPoints!FaustClient);
class FaustClient : dplug.client.Client
{
public:
nothrow:
@nogc:
this()
{
buildFaustModule();
}
void buildFaustModule()
{
_dsp = mallocNew!(FAUSTCLASS)();
FaustParamAccess _faustUI = mallocNew!FaustParamAccess();
_dsp.buildUserInterface(cast(UI*)(&_faustUI));
_faustParams = _faustUI.readParams();
}
override PluginInfo buildPluginInfo()
{
// Plugin info is parsed from plugin.json here at compile time.
// Indeed it is strongly recommended that you do not fill PluginInfo
// manually, else the information could diverge.
static immutable PluginInfo pluginInfo = parsePluginInfo(import("plugin.json"));
return pluginInfo;
}
// This is an optional overload, default is zero parameter.
// Caution when adding parameters: always add the indices
// in the same order as the parameter enum.
override Parameter[] buildParameters()
{
auto params = makeVec!Parameter();
// Add faust parameters
buildFaustModule();
int faustParamIndexStart = 0;
foreach(param; _faustParams)
{
if (param.isButton)
{
params ~= mallocNew!BoolParameter(faustParamIndexStart++, param.label, cast(bool)(*param.val));
}
else if (param.step == 1.0f) {
params ~= mallocNew!IntegerParameter(faustParamIndexStart++, param.label, param.unit, cast(int)param.min, cast(int)param.max, cast(int)param.initial);
}
else
{
params ~= mallocNew!LinearFloatParameter(faustParamIndexStart++, param.label, param.unit, param.min, param.max, param.initial);
}
}
return params.releaseData();
}
override LegalIO[] buildLegalIO()
{
auto io = makeVec!LegalIO();
if (_dsp is null)
{
_dsp = mallocNew!(FAUSTCLASS)();
}
io ~= LegalIO(_dsp.getNumInputs(), _dsp.getNumOutputs());
return io.releaseData();
}
// This override is optional, the default implementation will
// have one default preset.
override Preset[] buildPresets() nothrow @nogc
{
auto presets = makeVec!Preset();
presets ~= makeDefaultPreset();
return presets.releaseData();
}
// This override is also optional. It allows to split audio buffers in order to never
// exceed some amount of frames at once.
// This can be useful as a cheap chunking for parameter smoothing.
// Buffer splitting also allows to allocate statically or on the stack with less worries.
override int maxFramesInProcess() const //nothrow @nogc
{
return 512;
}
override void reset(double sampleRate, int maxFrames, int numInputs, int numOutputs) nothrow @nogc
{
// Clear here any state and delay buffers you might have.
_dsp.initialize(cast(int)sampleRate);
assert(maxFrames <= 512); // guaranteed by audio buffer splitting
}
void updateFaustParams()
{
foreach(param; params())
{
int paramIndex = param.index();
foreach(faustParam; _faustParams)
{
if (paramIndex == faustParam.ParamId)
{
if (cast(FloatParameter)param)
{
*(faustParam.val) = (cast(FloatParameter)param).valueAtomic();
}
else if (cast(IntegerParameter)param)
{
*(faustParam.val) = cast(FAUSTFLOAT)((cast(IntegerParameter)param).valueAtomic());
}
else if (cast(BoolParameter)param)
{
*(faustParam.val) = cast(FAUSTFLOAT)((cast(BoolParameter)param).valueAtomic());
}
else
{
assert(false, "Parameter type not implemented");
}
}
}
}
}
override void processAudio(const(float*)[] inputs, float*[]outputs, int frames,
TimeInfo info) nothrow @nogc
{
assert(frames <= 512); // guaranteed by audio buffer splitting
int numInputs = cast(int)inputs.length;
int numOutputs = cast(int)outputs.length;
int minChan = numInputs > numOutputs ? numOutputs : numInputs;
// do reverb
updateFaustParams();
_dsp.compute(frames, cast(float*[])inputs, cast(float*[])outputs);
// fill with zero the remaining channels
for (int chan = minChan; chan < numOutputs; ++chan)
outputs[chan][0..frames] = 0; // D has array slices assignments and operations
}
protected:
FAUSTCLASS _dsp;
UI _faustUI;
FaustParam[] _faustParams;
}
/******************************************************************************
*******************************************************************************
VECTOR INTRINSICS
*******************************************************************************
*******************************************************************************/
<<includeIntrinsic>>
/********************END ARCHITECTURE SECTION (part 1/2)****************/
/**************************BEGIN USER SECTION **************************/
<<includeclass>>
/***************************END USER SECTION ***************************/
/*******************BEGIN ARCHITECTURE SECTION (part 2/2)***************/
/********************END ARCHITECTURE SECTION (part 2/2)****************/
|