faust
faust copied to clipboard
faust2audiokit does not work (polyphonic node)
faust2audiokit does not work for making AudioKit Nodes. Also there is no documentation on how to use this. need help.
AudioKit 5.4.3
This is indeed an unfinished project. Are you willing to help to improve it ?
Yes, how to contribute ?
Its working for monophonic node with audiokit 5.0.1 Now struggling, how to make it work for polyphonic node, and how to trigger something like keyOn, keyOff, pitchBend messages to dsp code. Please Help !
Read https://faustdoc.grame.fr/manual/midi/#midi-polyphony-support and https://faustdoc.grame.fr/manual/architectures/#polyphonic-instruments
Thank you for the response but I am trying to access the mydsp_poly -> keyOn( ) from swift to trigger note on. May be it can happen via internalAU or something else. Need some hint only.
Sorry I don't have much experience in swift.
Do you have an example of polyphonic code to show?
Faustguitar.swift
` import AVFoundation import CAudioKit import AudioKit
/// Faust node public class Faustguitar: Node, AudioUnitContainer, Toggleable {
/// Unique four-letter identifier. If using multiple Faust generated nodes, make this unique for each
public static let ComponentDescription = AudioComponentDescription(instrument: "Fdsp")
/// Internal type of audio unit for this node
public typealias AudioUnitType = InternalAU
public private(set) var internalAU: AudioUnitType?
// MARK: - Parameters
// freq
public static var letfreqDef = NodeParameterDef(identifier: "freq", name: "freq", address: akGetParameterAddress("guitar_freq"), range: 20 ... 20000, unit: .customUnit, flags: .default)
@Parameter public var freq: AUValue
// gain
public static var letgainDef = NodeParameterDef(identifier: "gain", name: "gain", address: akGetParameterAddress("guitar_gain"), range: 0 ... 1, unit: .customUnit, flags: .default)
@Parameter public var gain: AUValue
// gate
public static var letgateDef = NodeParameterDef(identifier: "gate", name: "gate", address: akGetParameterAddress("guitar_gate"), range: 0 ... 1, unit: .customUnit, flags: .default)
@Parameter public var gate: AUValue
// MARK: - Audio Unit
public class InternalAU: AudioUnitBase {
/// Get an array of the parameter definitions
/// - Returns: Array of parameter definitions
public override func getParameterDefs() -> [NodeParameterDef] {
[Faustguitar.letfreqDef,
Faustguitar.letgainDef,
Faustguitar.letgateDef]
}
/// Create the DSP Refence for this node
/// - Returns: DSP Reference
public override func createDSP() -> DSPRef { akCreateDSP("Faustguitar") }
}
// MARK: - Initialization
public init(_ input: Node? = nil, freq: AUValue = 440, gain: AUValue = 1, gate: AUValue = 1) {
super.init(avAudioNode: input?.avAudioUnitOrNode ?? AVAudioNode())
instantiateAudioUnit { avAudioUnit in
self.avAudioUnit = avAudioUnit
self.avAudioNode = avAudioUnit
guard let audioUnit = avAudioUnit.auAudioUnit as? AudioUnitType else { fatalError("Couldn't create audio unit") }
self.internalAU = audioUnit
self.stop()
self.freq = freq
self.gain = gain
self.gate = gate
}
}
}
`
FaustDSP.mm
`#define NVOICES 10 #define POLY #define MIDICTRL /* ------------------------------------------------------------ name: "guitar" Code generated with Faust 2.41.1 (https://faust.grame.fr) Compilation options: -a /Users/yoogle/Faust-2.41.1/share/faust/audiokit/FaustDSP.mm -lang cpp -cn guitar -es 1 -mcd 16 -uim -single -ftz 0 ------------------------------------------------------------ */
#ifndef guitar_H #define guitar_H
#import "DSPBase.h"
#import
#include "faust/dsp/dsp.h" #include "faust/misc.h" #include "faust/gui/DecoratorUI.h"
#ifdef MIDICTRL #include "faust/gui/MidiUI.h" #endif
#ifdef POLY #include "faust/dsp/poly-dsp.h" #endif
#define FAUST_UIMACROS 1
// but we will ignore most of them #define FAUST_ADDBUTTON(l,f) #define FAUST_ADDCHECKBOX(l,f) #define FAUST_ADDVERTICALSLIDER(l,f,i,a,b,s) #define FAUST_ADDHORIZONTALSLIDER(l,f,i,a,b,s) #define FAUST_ADDNUMENTRY(l,f,i,a,b,s) #define FAUST_ADDVERTICALBARGRAPH(l,f,a,b) #define FAUST_ADDHORIZONTALBARGRAPH(l,f,a,b)
#ifndef FAUSTFLOAT #define FAUSTFLOAT float #endif
#include
#ifndef FAUSTCLASS #define FAUSTCLASS guitar #endif
#ifdef APPLE #define exp10f __exp10f #define exp10 __exp10 #endif
#if defined(_WIN32) #define RESTRICT __restrict #else #define RESTRICT restrict #endif
class guitar : public dsp {
public:
int fSampleRate;
float fConst0;
float fConst1;
FAUSTFLOAT fEntry0;
float fConst2;
float fRec0[2];
FAUSTFLOAT fEntry1;
float fRec1[2];
float fConst3;
FAUSTFLOAT fEntry2;
float fRec4[2];
float fRec2[2];
public:
void metadata(Meta* m) {
m->declare("compile_options", "-a /Users/yoogle/Faust-2.41.1/share/faust/audiokit/FaustDSP.mm -lang cpp -cn guitar -es 1 -mcd 16 -uim -single -ftz 0");
m->declare("filename", "guitar.dsp");
m->declare("maths.lib/author", "GRAME");
m->declare("maths.lib/copyright", "GRAME");
m->declare("maths.lib/license", "LGPL with exception");
m->declare("maths.lib/name", "Faust Math Library");
m->declare("maths.lib/version", "2.5");
m->declare("name", "guitar");
m->declare("oscillators.lib/name", "Faust Oscillator Library");
m->declare("oscillators.lib/version", "0.3");
m->declare("platform.lib/name", "Generic Platform Library");
m->declare("platform.lib/version", "0.2");
m->declare("signals.lib/name", "Faust Signal Routing Library");
m->declare("signals.lib/version", "0.3");
}
virtual int getNumInputs() {
return 0;
}
virtual int getNumOutputs() {
return 2;
}
static void classInit(int sample_rate) {
}
virtual void instanceConstants(int sample_rate) {
fSampleRate = sample_rate;
fConst0 = std::min<float>(192000.0f, std::max<float>(1.0f, float(fSampleRate)));
fConst1 = 44.0999985f / fConst0;
fConst2 = 1.0f - fConst1;
fConst3 = 1.0f / fConst0;
}
virtual void instanceResetUserInterface() {
fEntry0 = FAUSTFLOAT(1.0f);
fEntry1 = FAUSTFLOAT(1.0f);
fEntry2 = FAUSTFLOAT(440.0f);
}
virtual void instanceClear() {
for (int l0 = 0; l0 < 2; l0 = l0 + 1) {
fRec0[l0] = 0.0f;
}
for (int l1 = 0; l1 < 2; l1 = l1 + 1) {
fRec1[l1] = 0.0f;
}
for (int l2 = 0; l2 < 2; l2 = l2 + 1) {
fRec4[l2] = 0.0f;
}
for (int l3 = 0; l3 < 2; l3 = l3 + 1) {
fRec2[l3] = 0.0f;
}
}
virtual void init(int sample_rate) {
classInit(sample_rate);
instanceInit(sample_rate);
}
virtual void instanceInit(int sample_rate) {
instanceConstants(sample_rate);
instanceResetUserInterface();
instanceClear();
}
virtual guitar* clone() {
return new guitar();
}
virtual int getSampleRate() {
return fSampleRate;
}
virtual void buildUserInterface(UI* ui_interface) {
ui_interface->openVerticalBox("guitar");
ui_interface->addNumEntry("freq", &fEntry2, FAUSTFLOAT(440.0f), FAUSTFLOAT(20.0f), FAUSTFLOAT(20000.0f), FAUSTFLOAT(0.00999999978f));
ui_interface->addNumEntry("gain", &fEntry0, FAUSTFLOAT(1.0f), FAUSTFLOAT(0.0f), FAUSTFLOAT(1.0f), FAUSTFLOAT(0.00999999978f));
ui_interface->addNumEntry("gate", &fEntry1, FAUSTFLOAT(1.0f), FAUSTFLOAT(0.0f), FAUSTFLOAT(1.0f), FAUSTFLOAT(1.0f));
ui_interface->closeBox();
}
virtual void compute(int count, FAUSTFLOAT** RESTRICT inputs, FAUSTFLOAT** RESTRICT outputs) {
FAUSTFLOAT* output0 = outputs[0];
FAUSTFLOAT* output1 = outputs[1];
float fSlow0 = fConst1 * float(fEntry0);
float fSlow1 = fConst1 * float(fEntry1);
float fSlow2 = fConst1 * float(fEntry2);
for (int i0 = 0; i0 < count; i0 = i0 + 1) {
fRec0[0] = fSlow0 + fConst2 * fRec0[1];
fRec1[0] = fSlow1 + fConst2 * fRec1[1];
fRec4[0] = fSlow2 + fConst2 * fRec4[1];
float fTemp0 = std::max<float>(1.1920929e-07f, std::fabs(fRec4[0]));
float fTemp1 = fRec2[1] + fConst3 * fTemp0;
float fTemp2 = fTemp1 + -1.0f;
int iTemp3 = fTemp2 < 0.0f;
fRec2[0] = ((iTemp3) ? fTemp1 : fTemp2);
float fThen1 = fTemp1 + (1.0f - fConst0 / fTemp0) * fTemp2;
float fRec3 = ((iTemp3) ? fTemp1 : fThen1);
float fTemp4 = fRec0[0] * fRec1[0] * (2.0f * fRec3 + -1.0f);
output0[i0] = FAUSTFLOAT(fTemp4);
output1[i0] = FAUSTFLOAT(fTemp4);
fRec0[1] = fRec0[0];
fRec1[1] = fRec1[0];
fRec4[1] = fRec4[0];
fRec2[1] = fRec2[0];
}
}
};
#ifdef FAUST_UIMACROS
#define FAUST_FILE_NAME "guitar.dsp"
#define FAUST_CLASS_NAME "guitar"
#define FAUST_COMPILATION_OPIONS "-a /Users/yoogle/Faust-2.41.1/share/faust/audiokit/FaustDSP.mm -lang cpp -cn guitar -es 1 -mcd 16 -uim -single -ftz 0"
#define FAUST_INPUTS 0
#define FAUST_OUTPUTS 2
#define FAUST_ACTIVES 3
#define FAUST_PASSIVES 0
FAUST_ADDNUMENTRY("freq", fEntry2, 440.0f, 20.0f, 20000.0f, 0.01f);
FAUST_ADDNUMENTRY("gain", fEntry0, 1.0f, 0.0f, 1.0f, 0.01f);
FAUST_ADDNUMENTRY("gate", fEntry1, 1.0f, 0.0f, 1.0f, 1.0f);
#define FAUST_LIST_ACTIVES(p) \
p(NUMENTRY, freq, "freq", fEntry2, 440.0f, 20.0f, 20000.0f, 0.01f) \
p(NUMENTRY, gain, "gain", fEntry0, 1.0f, 0.0f, 1.0f, 0.01f) \
p(NUMENTRY, gate, "gate", fEntry1, 1.0f, 0.0f, 1.0f, 1.0f) \
#define FAUST_LIST_PASSIVES(p) \
#endif
#ifdef POLY std::list<GUI*> GUI::fGuiList; ztimedmap GUI::gTimedZoneMap; #endif
class Faustguitar : public DSPBase, public GenericUI {
private:
dsp* fDSP;
size_t inputChannelCount = 0;
size_t outputChannelCount = 0;
std::vector<FAUSTFLOAT*> fZones;
#ifdef MIDICTRL
midi_handler fMidiHandler;
MidiUI fMidiUI;
#endif
// -- active widgets
void addButton(const char* label, FAUSTFLOAT* zone) override { fZones.push_back(zone); }
void addCheckButton(const char* label, FAUSTFLOAT* zone) override { fZones.push_back(zone); }
void addVerticalSlider(const char*
label,
FAUSTFLOAT* zone,
FAUSTFLOAT init,
FAUSTFLOAT min,
FAUSTFLOAT max,
FAUSTFLOAT step) override
{
fZones.push_back(zone);
}
void addHorizontalSlider(const char*
label,
FAUSTFLOAT* zone,
FAUSTFLOAT init,
FAUSTFLOAT min,
FAUSTFLOAT max,
FAUSTFLOAT step) override
{
fZones.push_back(zone);
}
void addNumEntry(const char*
label,
FAUSTFLOAT* zone,
FAUSTFLOAT init,
FAUSTFLOAT min,
FAUSTFLOAT max,
FAUSTFLOAT step) override
{
fZones.push_back(zone);
}
// -- passive widgets
void addHorizontalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max) override {}
void addVerticalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max) override {}
public:
#ifdef MIDICTRL
Faustguitar():fMidiUI(&fMidiHandler)
#else
Faustguitar()
#endif
{
#ifdef POLY
int nvoices = 0;
bool midi_sync = false;
fDSP = new guitar();
MidiMeta::analyse(fDSP, midi_sync, nvoices);
fDSP = new mydsp_poly(fDSP, nvoices, true, true);
#else
fDSP = new guitar();
#endif
inputChannelCount = fDSP->getNumInputs();
outputChannelCount = fDSP->getNumOutputs();
#ifdef MIDICTRL
fDSP->buildUserInterface(&fMidiUI);
#endif
fDSP->buildUserInterface(this);
//assert(fDSP->getNumInputs() == (fDSP->getNumOutputs()));
}
~Faustguitar()
{
delete fDSP;
}
void setParameter(AUParameterAddress address, float value, bool immediate) override
{
if (address < fZones.size()) {
*fZones[address] = value;
}
}
void init(int channelCount, double sampleRate) override
{
fDSP->init(int(sampleRate));
}
void reset() override
{
fDSP->instanceResetUserInterface();
fDSP->instanceClear();
}
#ifdef MIDICTRL
void handleMIDIEvent(AUMIDIEvent const& ev) override
{
if (ev.length == 1) {
fMidiHandler.handleData1(ev.eventSampleTime, ev.eventType, ev.cable, ev.data[0]);
} else if (ev.length == 2) {
fMidiHandler.handleData2(ev.eventSampleTime, ev.eventType, ev.cable, ev.data[0], ev.data[1]);
}
}
#endif
void startRamp(const AUParameterEvent &event) override
{
auto address = event.parameterAddress;
if (address < fZones.size()) {
*fZones[address] = event.value;
}
}
// Need to override this since it's pure virtual.
void process(AUAudioFrameCount frameCount, AUAudioFrameCount bufferOffset) override
{
float* inputs[inputChannelCount];
float* outputs[outputChannelCount];
for (int channel = 0; channel < inputChannelCount; ++channel) {
inputs[channel] = (float*)inputBufferLists[0]->mBuffers[channel].mData + bufferOffset;
}
for (int channel = 0; channel < outputChannelCount; ++channel) {
outputs[channel] = (float*)outputBufferList->mBuffers[channel].mData + bufferOffset;
}
fDSP->compute(int(frameCount), inputs, outputs);
}
};
// Register AK class and parameters
enum guitarParameter : AUParameterAddress {
#define ACTIVE_ENUM_MEMBER(type, ident, name, var, def, min, max, step)
guitar_##ident,
FAUST_LIST_ACTIVES(ACTIVE_ENUM_MEMBER)
kNumActives,
};
AK_REGISTER_DSP(Faustguitar)
#define REGISTER_PARAMETER(type, ident, name, var, def, min, max, step)
AK_REGISTER_PARAMETER(guitar_##ident)
FAUST_LIST_ACTIVES(REGISTER_PARAMETER);
/******************* END FaustDSP.mm ****************/
#endif `
Working for Monophonic Code, will not work with the above polyphonic code
`class Conductor {
let engine = AudioEngine()
let guitar = Faustguitar()
init() {
guitar.freq = 440
guitar.gain = 1.0
guitar.gate = 1.0
engine.output = guitar
guitar.start()
startEngine()
}
func startEngine() {
do {
try engine.start()
} catch let err {
Log(err)
}
}
func noteOn() {
print("Note On")
}
}`
@theyoogle how about posting a github repository containing your project.
I'm working on understanding how faust2audiokit is supposed to work. It is certainly opaque.