1 /************************************************************************
2 ************************************************************************
3 FAUST compiler
4 Copyright (C) 2003-2018 GRAME, Centre National de Creation Musicale
5 ---------------------------------------------------------------------
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 ************************************************************************
20 ************************************************************************/
21
22 #include "interpreter_dsp.hh"
23 #include "compatibility.hh"
24 #include "libfaust.h"
25 #include "lock_api.hh"
26
27 using namespace std;
28
29 #ifdef MACHINE
30 #include "sha_key.hh"
faustassertaux(bool cond,const string & file,int line)31 void faustassertaux(bool cond, const string& file, int line)
32 {
33 if (!cond) {
34 stringstream str;
35 str << "ASSERT : please report this message, the stack trace, and the failing DSP file to Faust developers (";
36 str << "file: " << file.substr(file.find_last_of('/') + 1) << ", line: " << line << ", ";
37 str << "version: " << FAUSTVERSION;
38 str << ")\n";
39 stacktrace(str, 20);
40 throw faustexception(str.str());
41 }
42 }
43 #endif
44
45 dsp_factory_table<SDsp_factory> gInterpreterFactoryTable;
46
47 // External API
48
getInterpreterDSPFactoryFromSHAKey(const string & sha_key)49 EXPORT interpreter_dsp_factory* getInterpreterDSPFactoryFromSHAKey(const string& sha_key)
50 {
51 LOCK_API
52 return static_cast<interpreter_dsp_factory*>(gInterpreterFactoryTable.getDSPFactoryFromSHAKey(sha_key));
53 }
54
deleteInterpreterDSPFactory(interpreter_dsp_factory * factory)55 EXPORT bool deleteInterpreterDSPFactory(interpreter_dsp_factory* factory)
56 {
57 LOCK_API
58 return (factory) ? gInterpreterFactoryTable.deleteDSPFactory(factory) : false;
59 }
60
getInterpreterDSPFactoryLibraryList(interpreter_dsp_factory * factory)61 EXPORT vector<string> getInterpreterDSPFactoryLibraryList(interpreter_dsp_factory* factory)
62 {
63 // TODO
64 LOCK_API
65 vector<string> res;
66 return res;
67 }
68
getAllInterpreterDSPFactories()69 EXPORT vector<string> getAllInterpreterDSPFactories()
70 {
71 LOCK_API
72 return gInterpreterFactoryTable.getAllDSPFactories();
73 }
74
deleteAllInterpreterDSPFactories()75 EXPORT void deleteAllInterpreterDSPFactories()
76 {
77 LOCK_API
78 gInterpreterFactoryTable.deleteAllDSPFactories();
79 }
80
~interpreter_dsp()81 EXPORT interpreter_dsp::~interpreter_dsp()
82 {
83 LOCK_API
84 gInterpreterFactoryTable.removeDSP(fFactory, this);
85
86 if (fFactory->getMemoryManager()) {
87 fDSP->~interpreter_dsp_base();
88 fFactory->getMemoryManager()->destroy(fDSP);
89 } else {
90 delete fDSP;
91 }
92 }
93
createDSPInstance()94 EXPORT interpreter_dsp* interpreter_dsp_factory::createDSPInstance()
95 {
96 LOCK_API
97 dsp* dsp = fFactory->createDSPInstance(this);
98 gInterpreterFactoryTable.addDSP(this, dsp);
99 return static_cast<interpreter_dsp*>(dsp);
100 }
101
102 // Use the memory manager if needed
operator delete(void * ptr)103 EXPORT void interpreter_dsp::operator delete(void* ptr)
104 {
105 if (ptr) {
106 dsp_memory_manager* manager = static_cast<interpreter_dsp*>(ptr)->fFactory->getMemoryManager();
107 if (manager) {
108 manager->destroy(ptr);
109 } else {
110 ::operator delete(ptr);
111 }
112 }
113 }
114
115 // Read/write
116
read_real_type(istream * in)117 static string read_real_type(istream* in)
118 {
119 string type_line;
120 getline(*in, type_line);
121
122 stringstream type_reader(type_line);
123 string dummy, type;
124 type_reader >> dummy; // Read "interpreter_dsp_factory" token
125 checkToken(dummy, "interpreter_dsp_factory");
126 type_reader >> type;
127
128 return type;
129 }
130
readInterpreterDSPFactoryFromBitcodeAux(const string & bitcode,string & error_msg)131 static interpreter_dsp_factory* readInterpreterDSPFactoryFromBitcodeAux(const string& bitcode, string& error_msg)
132 {
133 try {
134 dsp_factory_table<SDsp_factory>::factory_iterator it;
135
136 string sha_key = generateSHA1(bitcode);
137
138 if (gInterpreterFactoryTable.getFactory(sha_key, it)) {
139 SDsp_factory sfactory = (*it).first;
140 sfactory->addReference();
141 return sfactory;
142 } else {
143 interpreter_dsp_factory* factory = nullptr;
144 stringstream reader(bitcode);
145 string type = read_real_type(&reader);
146
147 if (type == "float") {
148 factory = new interpreter_dsp_factory(interpreter_dsp_factory_aux<float, 0>::read(&reader));
149 } else if (type == "double") {
150 factory = new interpreter_dsp_factory(interpreter_dsp_factory_aux<double, 0>::read(&reader));
151 } else {
152 throw faustexception("ERROR : unrecognized file format\n");
153 }
154
155 gInterpreterFactoryTable.setFactory(factory);
156 factory->setSHAKey(sha_key);
157 factory->setDSPCode(bitcode);
158 return factory;
159 }
160 } catch (faustexception& e) {
161 error_msg = e.Message();
162 return nullptr;
163 }
164 }
165
readInterpreterDSPFactoryFromBitcode(const string & bitcode,string & error_msg)166 EXPORT interpreter_dsp_factory* readInterpreterDSPFactoryFromBitcode(const string& bitcode, string& error_msg)
167 {
168 LOCK_API
169 return readInterpreterDSPFactoryFromBitcodeAux(bitcode, error_msg);
170 }
171
writeInterpreterDSPFactoryToBitcode(interpreter_dsp_factory * factory)172 EXPORT string writeInterpreterDSPFactoryToBitcode(interpreter_dsp_factory* factory)
173 {
174 LOCK_API
175 stringstream writer;
176 factory->write(&writer, true);
177 return writer.str();
178 }
179
readInterpreterDSPFactoryFromBitcodeFile(const string & bitcode_path,string & error_msg)180 EXPORT interpreter_dsp_factory* readInterpreterDSPFactoryFromBitcodeFile(const string& bitcode_path, string& error_msg)
181 {
182 LOCK_API
183 string base = basename((char*)bitcode_path.c_str());
184 size_t pos = bitcode_path.find(".fbc");
185
186 if (pos != string::npos) {
187 ifstream reader(bitcode_path.c_str());
188 if (reader.is_open()) {
189 string bitcode(istreambuf_iterator<char>(reader), {});
190 return readInterpreterDSPFactoryFromBitcodeAux(bitcode, error_msg);
191 } else {
192 error_msg = "ERROR opening file '" + bitcode_path + "'\n";
193 return nullptr;
194 }
195 } else {
196 error_msg = "ERROR : file Extension is not the one expected (.fbc expected)\n";
197 return nullptr;
198 }
199 }
200
writeInterpreterDSPFactoryToBitcodeFile(interpreter_dsp_factory * factory,const string & bitcode_path)201 EXPORT bool writeInterpreterDSPFactoryToBitcodeFile(interpreter_dsp_factory* factory, const string& bitcode_path)
202 {
203 LOCK_API
204 ofstream writer(bitcode_path.c_str());
205 if (writer.is_open()) {
206 factory->write(&writer, true);
207 return true;
208 } else {
209 return false;
210 }
211 }
212
metadata(Meta * meta)213 EXPORT void interpreter_dsp::metadata(Meta* meta)
214 {
215 fDSP->metadata(meta);
216 }
217
clone()218 EXPORT interpreter_dsp* interpreter_dsp::clone()
219 {
220 return fFactory->createDSPInstance();
221 }
222
getSampleRate()223 EXPORT int interpreter_dsp::getSampleRate()
224 {
225 return fDSP->getSampleRate();
226 }
227
getNumInputs()228 EXPORT int interpreter_dsp::getNumInputs()
229 {
230 return fDSP->getNumInputs();
231 }
232
getNumOutputs()233 int EXPORT interpreter_dsp::getNumOutputs()
234 {
235 return fDSP->getNumOutputs();
236 }
237
init(int sample_rate)238 EXPORT void interpreter_dsp::init(int sample_rate)
239 {
240 fDSP->init(sample_rate);
241 }
242
instanceInit(int sample_rate)243 EXPORT void interpreter_dsp::instanceInit(int sample_rate)
244 {
245 fDSP->instanceInit(sample_rate);
246 }
247
instanceConstants(int sample_rate)248 EXPORT void interpreter_dsp::instanceConstants(int sample_rate)
249 {
250 fDSP->instanceConstants(sample_rate);
251 }
252
instanceResetUserInterface()253 EXPORT void interpreter_dsp::instanceResetUserInterface()
254 {
255 fDSP->instanceResetUserInterface();
256 }
257
instanceClear()258 EXPORT void interpreter_dsp::instanceClear()
259 {
260 fDSP->instanceClear();
261 }
262
buildUserInterface(UI * ui_interface)263 EXPORT void interpreter_dsp::buildUserInterface(UI* ui_interface)
264 {
265 UITemplate glue(ui_interface);
266 fDSP->buildUserInterface(&glue);
267 }
268
compute(int count,FAUSTFLOAT ** input,FAUSTFLOAT ** output)269 EXPORT void interpreter_dsp::compute(int count, FAUSTFLOAT** input, FAUSTFLOAT** output)
270 {
271 fDSP->compute(count, input, output);
272 }
273