feat: generate faust C code and Nim wrapper with faustpp

Signed-off-by: Christopher Arndt <chris@chrisarndt.de>
This commit is contained in:
Christopher Arndt 2024-10-08 19:42:50 +02:00
parent aa3bae40fb
commit 9b33bf10bf
5 changed files with 284 additions and 60 deletions

View File

@ -82,9 +82,9 @@ below.
nim c --app:lib --noMain:on --mm:arc \
--out:mydsp.lv2/libmydsp.so mydsp_plugin.nim
See the definition of the `build_ex` task in the
[nymph.nimble](./nymph.nimble#L67) file on how to create a nimble task
to simplify compilation.
See the definition of the `build_ex` task in the
[nymph.nimble](./nymph.nimble#L67) file on how to create a nimble task
to simplify compilation and additional compiler args you might want to use.
## Dependencies

View File

@ -1,31 +1,38 @@
/* ------------------------------------------------------------
author: "Christopher Arndt"
copyright: "Christopher Arndt, 2024"
license: "MIT"
name: "FaustLPF"
version: "0.1.0"
Code generated with Faust 2.74.6 (https://faust.grame.fr)
Compilation options: -a ./examples/minarch.h -lang c -rui -ct 1 -cn faustlpf -es 1 -mcd 16 -mdd 1024 -mdy 33 -single -ftz 0 -vec -lv 0 -vs 32
------------------------------------------------------------ */
#ifndef __faustlpf_H__
#define __faustlpf_H__
/******************* BEGIN minarch.h ****************/
/************************************************************************
FAUST Architecture File for generating a very minimal C interface
************************************************************************/
#include "faust/gui/CInterface.h"
/******************************************************************************
VECTOR INTRINSICS
*******************************************************************************/
//------------------------------------------------------------------------------
// This file was generated using the Faust compiler (https://faust.grame.fr),
// and the Faust post-processor (https://github.com/SpotlightKid/faustpp).
//
// Source: lpf.dsp
// Name: FaustLPF
// Author: Christopher Arndt
// Copyright: Christopher Arndt, 2024
// License: MIT
// Version: 0.1.0
// FAUST version: 2.75.10
// FAUST compilation options: -a /home/chris/tmp/tmp9v2ck7tz.c -lang c -rui -ct 1 -fm def -cn faustlpf -es 1 -mcd 16 -mdd 1024 -mdy 33 -single -ftz 0 -vec -lv 0 -vs 32
//------------------------------------------------------------------------------
/**************************BEGIN USER SECTION **************************/
#include "faustlpf.h"
//------------------------------------------------------------------------------
// Begin the Faust code section
#if defined(__GNUC__)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wunused-parameter"
#endif
// START INTRINSICS
// END INTRINSICS
// START CLASS CODE
#ifndef FAUSTFLOAT
#define FAUSTFLOAT float
#endif
@ -41,6 +48,7 @@ extern "C" {
#define RESTRICT __restrict__
#endif
#include "faust/dsp/fastmath.cpp"
#include <math.h>
#include <stdint.h>
#include <stdlib.h>
@ -58,16 +66,7 @@ static float faustlpf_faustpower2_f(float value) {
#define exp10 __exp10
#endif
typedef struct {
int fSampleRate;
float fConst0;
float fConst1;
float fConst2;
FAUSTFLOAT fHslider0;
float fRec1_perm[4];
float fConst3;
float fRec0_perm[4];
} faustlpf;
faustlpf* newfaustlpf() {
faustlpf* dsp = (faustlpf*)calloc(1, sizeof(faustlpf));
@ -80,7 +79,7 @@ void deletefaustlpf(faustlpf* dsp) {
void metadatafaustlpf(MetaGlue* m) {
m->declare(m->metaInterface, "author", "Christopher Arndt");
m->declare(m->metaInterface, "compile_options", "-a ./examples/minarch.h -lang c -rui -ct 1 -cn faustlpf -es 1 -mcd 16 -mdd 1024 -mdy 33 -single -ftz 0 -vec -lv 0 -vs 32");
m->declare(m->metaInterface, "compile_options", "-a /home/chris/tmp/tmp9v2ck7tz.c -lang c -rui -ct 1 -fm def -cn faustlpf -es 1 -mcd 16 -mdd 1024 -mdy 33 -single -ftz 0 -vec -lv 0 -vs 32");
m->declare(m->metaInterface, "copyright", "Christopher Arndt, 2024");
m->declare(m->metaInterface, "filename", "lpf.dsp");
m->declare(m->metaInterface, "filters.lib/fir:author", "Julius O. Smith III");
@ -112,7 +111,7 @@ void metadatafaustlpf(MetaGlue* m) {
m->declare(m->metaInterface, "platform.lib/name", "Generic Platform Library");
m->declare(m->metaInterface, "platform.lib/version", "1.3.0");
m->declare(m->metaInterface, "signals.lib/name", "Faust Signal Routing Library");
m->declare(m->metaInterface, "signals.lib/version", "1.5.0");
m->declare(m->metaInterface, "signals.lib/version", "1.6.0");
m->declare(m->metaInterface, "version", "0.1.0");
}
@ -230,7 +229,7 @@ void computefaustlpf(faustlpf* dsp, int count, FAUSTFLOAT** RESTRICT inputs, FAU
{
int i;
for (i = 0; i < vsize; i = i + 1) {
fZec0[i] = tanf(dsp->fConst3 * fRec1[i]);
fZec0[i] = fast_tanf(dsp->fConst3 * fRec1[i]);
}
}
/* Vectorizable loop 2 */
@ -322,7 +321,7 @@ void computefaustlpf(faustlpf* dsp, int count, FAUSTFLOAT** RESTRICT inputs, FAU
{
int i;
for (i = 0; i < vsize; i = i + 1) {
fZec0[i] = tanf(dsp->fConst3 * fRec1[i]);
fZec0[i] = fast_tanf(dsp->fConst3 * fRec1[i]);
}
}
/* Vectorizable loop 2 */
@ -383,7 +382,15 @@ void computefaustlpf(faustlpf* dsp, int count, FAUSTFLOAT** RESTRICT inputs, FAU
#ifdef __cplusplus
}
#endif
// END CLASS CODE
/***************************END USER SECTION ***************************/
#if defined(__GNUC__)
# pragma GCC diagnostic pop
#endif
//------------------------------------------------------------------------------
// End the Faust code section

200
examples/faustlpf.h Normal file
View File

@ -0,0 +1,200 @@
#ifndef __faustlpf_H__
#define __faustlpf_H__
#ifndef FAUSTFLOAT
#define FAUSTFLOAT float
#endif
#ifndef FAUSTCLASS
#define FAUSTCLASS faustlpf
#endif
#if defined(_WIN32)
#define RESTRICT __restrict
#else
#define RESTRICT __restrict__
#endif
#include <stdbool.h>
#include <stdint.h>
#include "faust/gui/CInterface.h"
typedef struct {
int fSampleRate;
float fConst0;
float fConst1;
float fConst2;
FAUSTFLOAT fHslider0;
float fRec1_perm[4];
float fConst3;
float fRec0_perm[4];
} faustlpf;
faustlpf* newfaustlpf();
void deletefaustlpf(faustlpf* dsp);
void metadatafaustlpf(MetaGlue* m);
int getSampleRatefaustlpf(faustlpf* RESTRICT dsp);
int getNumInputsfaustlpf(faustlpf* RESTRICT dsp);
int getNumOutputsfaustlpf(faustlpf* RESTRICT dsp);
void classInitfaustlpf(int sample_rate);
void instanceResetUserInterfacefaustlpf(faustlpf* dsp);
void instanceClearfaustlpf(faustlpf* dsp);
void instanceConstantsfaustlpf(faustlpf* dsp, int sample_rate);
void instanceInitfaustlpf(faustlpf* dsp, int sample_rate);
void initfaustlpf(faustlpf* dsp, int sample_rate);
void buildUserInterfacefaustlpf(faustlpf* dsp, UIGlue* ui_interface);
void computefaustlpf(faustlpf* dsp, int count, FAUSTFLOAT** RESTRICT inputs, FAUSTFLOAT** RESTRICT outputs);
int parameter_group(unsigned index) {
switch (index) {
case 0:
return 0;
default:
return -1;
}
}
const char *parameter_label(unsigned index) {
switch (index) {
case 0:
return "Cutoff";
default:
return 0;
}
}
const char *parameter_short_label(unsigned index) {
switch (index) {
case 0:
return "Cutoff";
default:
return 0;
}
}
const char *parameter_style(unsigned index) {
switch (index) {
case 0: {
return "knob";
}
default:
return "";
}
}
const char *parameter_symbol(unsigned index) {
switch (index) {
case 0:
return "cutoff";
default:
return "";
}
}
const char *parameter_unit(unsigned index) {
switch (index) {
case 0:
return "Hz";
default:
return 0;
}
}
bool parameter_is_trigger(unsigned index) {
switch (index) {
default:
return false;
}
}
bool parameter_is_boolean(unsigned index) {
switch (index) {
default:
return false;
}
}
bool parameter_is_enum(unsigned index) {
switch (index) {
default:
return false;
}
}
bool parameter_is_integer(unsigned index) {
switch (index) {
default:
return false;
}
}
bool parameter_is_logarithmic(unsigned index) {
switch (index) {
case 0:
return true;
default:
return false;
}
}
float get_parameter(faustlpf* dsp, unsigned index) {
switch (index) {
case 0:
return dsp->fHslider0;
default:
(void)dsp;
return 0.0;
}
}
void set_parameter(faustlpf* dsp, unsigned index, float value) {
switch (index) {
case 0:
dsp->fHslider0 = value;
break;
default:
(void)dsp;
(void)value;
break;
}
}
float get_cutoff(faustlpf* dsp) {
return dsp->fHslider0;
}
void set_cutoff(faustlpf* dsp, float value) {
dsp->fHslider0 = value;
}
#endif /* __faustlpf_H__ */

33
examples/faustlpf.nim Normal file
View File

@ -0,0 +1,33 @@
{.compile: "faustlpf.c".}
type
faustlpf* = object
SampleBuffer* = UncheckedArray[cfloat]
proc newfaustlpf*(): ptr faustlpf {.importc.}
proc deletefaustlpf*(dsp: ptr faustlpf) {.importc.}
proc initfaustlpf*(dsp: ptr faustlpf, sample_rate: cint) {.importc.}
proc instanceClearfaustlpf*(dsp: ptr faustlpf) {.importc.}
proc computefaustlpf*(dsp: ptr faustlpf, count: cint, inputs, outputs: ptr ptr SampleBuffer) {.importc.}
proc parameter_group*(index: cuint): cint {.importc}
proc parameter_is_boolean*(index: cuint): bool {.importc}
proc parameter_is_enum*(index: cuint): bool {.importc}
proc parameter_is_integer*(index: cuint): bool {.importc}
proc parameter_is_logarithmic*(index: cuint): bool {.importc}
proc parameter_is_trigger*(index: cuint): bool {.importc}
proc parameter_label*(index: cuint): cstring {.importc}
proc parameter_short_label*(index: cuint): cstring {.importc}
proc parameter_style*(index: cuint): cstring {.importc}
proc parameter_symbol*(index: cuint): cstring {.importc}
proc parameter_unit*(index: cuint): cstring {.importc}
proc get_parameter*(dsp: ptr faustlpf, index: cuint): cfloat {.importc}
proc set_parameter*(dsp: ptr faustlpf, index: cuint, value: cfloat) {.importc}
proc get_cutoff*(dsp: ptr faustlpf): cfloat {.importc}
proc set_cutoff*(dsp: ptr faustlpf, value: cfloat) {.importc}

View File

@ -1,37 +1,21 @@
## A FAUST standard library 2-pole lowpass filter LV2 plugin
import nymph
{.emit: """#include "lpf.h"""".}
import faustlpf
const
PluginUri = "urn:nymph:examples:faustlpf"
type
faustlpf {.importc, header: "lpf.h".} = object
# struct field representing the value of the FAUST UI element,
# which controls the filter cutoff frequency
fHslider0: cfloat
PluginPort {.pure.} = enum
Input, Output, Frequency
SampleBuffer = UncheckedArray[cfloat]
FaustLPFPlugin = object
input: ptr SampleBuffer
output: ptr SampleBuffer
freq: ptr cfloat
flt: ptr faustlpf
# wrap only those functions from the C code, which we actually need
proc newfaustlpf(): ptr faustlpf {.importc.}
proc deletefaustlpf(dsp: ptr faustlpf) {.importc.}
proc initfaustlpf(dsp: ptr faustlpf, sample_rate: cint) {.importc.}
proc instanceClearfaustlpf(dsp: ptr faustlpf) {.importc.}
proc computefaustlpf(dsp: ptr faustlpf, count: cint, inputs, outputs: ptr ptr SampleBuffer) {.importc.}
proc NimMain() {.cdecl, importc.}
@ -66,7 +50,7 @@ proc activate(instance: Lv2Handle) {.cdecl.} =
proc run(instance: Lv2Handle; nSamples: cuint) {.cdecl.} =
let plug = cast[ptr FaustLPFPlugin](instance)
plug.flt.fHslider0 = plug.freq[]
set_cutoff(plug.flt, plug.freq[])
computefaustlpf(plug.flt, nSamples.cint, addr plug.input, addr plug.output)