1 /************************************************************************
2 FAUST Architecture File
3 Copyright (C) 2021 GRAME, Centre National de Creation Musicale
4 ---------------------------------------------------------------------
5 This Architecture section is free software; you can redistribute it
6 and/or modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 3 of
8 the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; If not, see <http://www.gnu.org/licenses/>.
17
18 EXCEPTION : As a special exception, you may create a larger work
19 that contains this FAUST architecture section and distribute
20 that work under terms of your choice, so long as this FAUST
21 architecture section is not modified.
22
23 ************************************************************************/
24
25 #include <iostream>
26 #include <ostream>
27 #include <sstream>
28 #include <vector>
29
30 #include "faust/dsp/dsp.h"
31 #include "faust/gui/DecoratorUI.h"
32 #include "faust/misc.h"
33
34 using namespace std;
35
36 <<includeIntrinsic>>
37 <<includeclass>>
38
39 struct SwiftFilePrinter : public GenericUI
40 {
41 ofstream& fOutFile;
42 string fKlassName;
43 string fDSPName;
44 string fUniqueCode;
45 string fUnit;
46 stringstream fInit1;
47 stringstream fInit2;
48 vector<string> fInit3;
49
SwiftFilePrinterSwiftFilePrinter50 SwiftFilePrinter(const string& class_name, ofstream& out_file):fKlassName("Faust" + class_name), fDSPName(class_name), fOutFile(out_file)
51 {
52 fInit1 << "public init(_ input: Node? = nil";
53 // this may need to be unique per node
54 fUniqueCode = "Fdsp";
55 }
56
printHeaderSwiftFilePrinter57 void printHeader()
58 {
59 fOutFile << "// Copyright AudioKit. All Rights Reserved. Revision History at http://github.com/AudioKit/AudioKit/" << endl;
60 fOutFile << "import AVFoundation" << endl;
61 fOutFile << "import CAudioKit" << endl;
62 fOutFile << "import AudioKit" << endl;
63 fOutFile << endl;
64 fOutFile << "/// Faust node" << endl;
65 fOutFile << "public class " << fKlassName << ": Node, AudioUnitContainer, Toggleable {" << endl;
66 fOutFile << endl;
67 fOutFile << "\t" << "/// Unique four-letter identifier. If using multiple Faust generated nodes, make this unique for each" << endl;
68 fOutFile << "\t" << "public static let ComponentDescription = AudioComponentDescription(instrument: \"" << fUniqueCode << "\")" << endl;
69 fOutFile << endl;
70 fOutFile << "\t" << "/// Internal type of audio unit for this node" << endl;
71 fOutFile << "\t" << "public typealias AudioUnitType = InternalAU" << endl;
72 fOutFile << endl;
73 fOutFile << "\t" << "public private(set) var internalAU: AudioUnitType?" << endl;
74 fOutFile << endl;
75 fOutFile << "\t" << "// MARK: - Parameters" << endl;
76 fOutFile << endl;
77 }
78
printFooterSwiftFilePrinter79 void printFooter()
80 {
81
82 fOutFile << "\t" << "// MARK: - Audio Unit" << endl;
83 fOutFile << "\tpublic class InternalAU: AudioUnitBase {" << endl;
84 fOutFile << "\t\t" << "/// Get an array of the parameter definitions" << endl;
85 fOutFile << "\t\t" << "/// - Returns: Array of parameter definitions" << endl;
86 fOutFile << "\t\t" << "public override func getParameterDefs() -> [NodeParameterDef] {" << endl;
87 fOutFile << "\t\t\t" << "[";
88 for (int i = 0; i < fInit3.size(); i++) {
89 fOutFile << fInit3[i];
90 if (i < fInit3.size() - 1) fOutFile << ",\n\t\t\t";
91 }
92 fOutFile << "]" << endl;
93 fOutFile << "\t\t}" << endl;
94
95 fOutFile << "\t\t/// Create the DSP Refence for this node" << endl;
96 fOutFile << "\t\t/// - Returns: DSP Reference" << endl;
97 fOutFile << "\t\tpublic override func createDSP() -> DSPRef { akCreateDSP(\"" << fKlassName << "\") }" << endl;
98 fOutFile << "\t}" << endl << endl;
99
100 fOutFile << "\t" << "// MARK: - Initialization" << endl;
101 fOutFile << "\t" << fInit1.str() << ") {" << endl;
102 fOutFile << "\t\t" << "super.init(avAudioNode: input?.avAudioUnitOrNode ?? AVAudioNode())" << endl;
103 fOutFile << "\t\t" << "instantiateAudioUnit { avAudioUnit in" << endl;
104 fOutFile << "\t\t\t" << "self.avAudioUnit = avAudioUnit" << endl;
105 fOutFile << "\t\t\t" << "self.avAudioNode = avAudioUnit" << endl;
106 fOutFile << "\t\t\t" << "guard let audioUnit = avAudioUnit.auAudioUnit as? AudioUnitType else { fatalError(\"Couldn't create audio unit\") }" << endl;
107 fOutFile << "\t\t\t" << "self.internalAU = audioUnit" << endl;
108 fOutFile << "\t\t\t" << "self.stop()" << endl;
109 fOutFile << fInit2.str();
110 fOutFile << "\t\t}" << endl;
111 fOutFile << "\t}" << endl;
112
113 fOutFile << "}" << endl << endl;
114 }
115
printUnitSwiftFilePrinter116 string printUnit()
117 {
118 if (fUnit == "Hz") {
119 return ".hertz";
120 } else if (fUnit == "dB") {
121 return ".decibels";
122 } else {
123 return ".customUnit";
124 }
125 }
126
printButtonSwiftFilePrinter127 void printButton(const char* label_aux)
128 {
129 string label = label_aux;
130 std::replace(label.begin(), label.end(), ' ', '_');
131 }
132
printParamSwiftFilePrinter133 void printParam(const char* label_aux, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT init)
134 {
135 string label = label_aux;
136 std::replace(label.begin(), label.end(), ' ', '_');
137
138 fOutFile << "\t" << "// " << label << endl;
139 fOutFile << "\t" << "public static var let" << label << "Def = NodeParameterDef(identifier: \"" << label << "\", ";
140 fInit3.push_back(fKlassName + ".let" + string(label) + "Def");
141 fOutFile << "name: \"" << label << "\", ";
142 fOutFile << "address: akGetParameterAddress(\"" << fDSPName << "_" << label << "\"), ";
143 fOutFile << "range: " << min << " ... " << max << ", ";
144 fOutFile << "unit: " << printUnit() << ", ";
145 fOutFile << "flags: .default)";
146 fOutFile << endl << endl;
147 fOutFile << "\t" << "@Parameter public var " << label << ": AUValue" << endl << endl;
148
149 // Complete fInit1
150 fInit1 << ", " << label << ": AUValue = " << init;
151
152 // Complete fInit2
153 fInit2 << "\t\t\t" << "self." << label << " = " << label << endl;
154
155 // Reset unit metadata
156 fUnit = "";
157 }
158
159 // -- active widgets
addButtonSwiftFilePrinter160 virtual void addButton(const char* label, FAUSTFLOAT* zone)
161 {
162 printButton(label);
163 }
addCheckButtonSwiftFilePrinter164 virtual void addCheckButton(const char* label, FAUSTFLOAT* zone)
165 {
166 printButton(label);
167 }
addVerticalSliderSwiftFilePrinter168 virtual void addVerticalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step)
169 {
170 printParam(label, min, max, init);
171 }
addHorizontalSliderSwiftFilePrinter172 virtual void addHorizontalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step)
173 {
174 printParam(label, min, max, init);
175 }
addNumEntrySwiftFilePrinter176 virtual void addNumEntry(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step)
177 {
178 printParam(label, min, max, init);
179 }
180
181 // -- passive widgets
addHorizontalBargraphSwiftFilePrinter182 virtual void addHorizontalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max) {}
addVerticalBargraphSwiftFilePrinter183 virtual void addVerticalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max) {}
184
declareSwiftFilePrinter185 virtual void declare(FAUSTFLOAT* zone, const char* key, const char* val)
186 {
187 if (strcmp(key, "unit") == 0) {
188 fUnit = val;
189 }
190 }
191
192 };
193
194 struct Meta1 : Meta
195 {
196 string fFileName;
declareMeta1197 void declare(const char* key, const char* value)
198 {
199 if (strcmp("filename", key) == 0) {
200 fFileName = value;
201 }
202 }
203 };
204
main(int argc,char * argv[])205 int main(int argc, char* argv[])
206 {
207 mydsp dsp;
208
209 Meta1 meta1;
210 dsp.metadata(&meta1);
211
212 // Generate the swift output file
213 string file_name = meta1.fFileName;
214 file_name.erase(file_name.end() - 4, file_name.end());
215
216 ofstream out_file("Faust" + file_name + ".swift");
217 SwiftFilePrinter printer(file_name, out_file);
218 printer.printHeader();
219 dsp.buildUserInterface(&printer);
220 printer.printFooter();
221
222 return 0;
223 }
224