Open theyoogle opened 2 years ago
This is indeed an unfinished project. Are you willing to help to improve it ?
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 !
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
/ ------------------------------------------------------------ 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 ------------------------------------------------------------ /
// but we will ignore most of them
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];
}
}
};
#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) \
std::list<GUI*> GUI::fGuiList; ztimedmap GUI::gTimedZoneMap;
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 {
guitar_##ident, FAUST_LIST_ACTIVES(ACTIVE_ENUM_MEMBER) kNumActives, };
AK_REGISTER_DSP(Faustguitar)
AK_REGISTER_PARAMETER(guitar_##ident)
FAUST_LIST_ACTIVES(REGISTER_PARAMETER);
/*** END FaustDSP.mm ****/
`
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")
}
}`
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.
To start again on the project:
faust2audiokit
is here https://github.com/grame-cncm/faust/tree/master-dev/architecture/audiokit and https://github.com/grame-cncm/faust/blob/master-dev/tools/faust2appls/faust2audiokit
faust2audiokit does not work for making AudioKit Nodes. Also there is no documentation on how to use this. need help.
AudioKit 5.4.3