grame-cncm / faust

Functional programming language for signal processing and sound synthesis
http://faust.grame.fr
Other
2.57k stars 322 forks source link

faust2audiokit does not work (polyphonic node) #772

Open theyoogle opened 2 years ago

theyoogle commented 2 years ago

faust2audiokit does not work for making AudioKit Nodes. Also there is no documentation on how to use this. need help.

AudioKit 5.4.3

sletz commented 2 years ago

This is indeed an unfinished project. Are you willing to help to improve it ?

theyoogle commented 2 years ago

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 !

sletz commented 2 years ago

Read https://faustdoc.grame.fr/manual/midi/#midi-polyphony-support and https://faustdoc.grame.fr/manual/architectures/#polyphonic-instruments

theyoogle commented 2 years ago

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.

sletz commented 2 years ago

Sorry I don't have much experience in swift.

sletz commented 2 years ago

Do you have an example of polyphonic code to show?

theyoogle commented 2 years ago

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
    }
}

}

`

theyoogle commented 2 years ago

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

import

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

include

include

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

`

theyoogle commented 2 years ago

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")
}

}`

emurray2 commented 4 months ago

This is indeed an unfinished project. Are you willing to help to improve it ?

I'd be willing to help. Let me know what I need to do.

We (Audio Kit contributors) made a lot of changes since AudioKit 5 but it seems possible to get this to work.

This seems like it doesn't work because AudioKit 5 removed the old polyphonic oscillator in Swift. As far as I know, we're still working on making a new one or it's also in the beta stages.

sletz commented 4 months ago

To start again on the project: