Codebase list jacktrip / d7ebf4f
Update upstream source from tag 'upstream/1.3.0+ds0' Update to upstream version '1.3.0+ds0' with Debian dir 62b13865b02db959d5aa4a8fde95e2723f3a468c IOhannes m zmölnig 3 years ago
71 changed file(s) with 17648 addition(s) and 1544 deletion(s). Raw diff Collapse all Expand all
88 dist: bionic
99
1010 branches:
11 - main
1112 - dev
12
13
1314 env:
1415 global:
1516 - PKGS_OSX="jack qt rt-audio"
0 ---
1 1.3.0
2 - (added) async networking in hub listener
3 - (added) limiter, compressor, reverb
4 - (added) examine audio delay
5 - (added) jitter buffer alternatives
6 - (added) broadcast output ports
7 - (added) PREFIX variable for installation path
8 - (added) disconnect on timeout
9 - (added) SIGTERM
10 - (added) simulate packet loss, jitter
11 - (added) hubpatch 5, no auto patching
12 - (added) jack client name length check
13 - (added) scripts/hubMode/test_hub_mode_server_and_client.sh
14 - (fixed) misc. typos, indentation
15 - (fixed) short form IO stat options
16 - (fixed) nullptr jack server name when creating jack client
17 - (fixed) stop ring buffer blocking when jack has been stopped
18 - (fixed) JMess handling of non-western characters
19 - (fixed) closing curly brace on mJackTrip client creation
20 - (fixed) Warnings
21 - (fixed) remove rtaudio device and mpeeraddress msgs.
22 - (fixed) signal and slot connections
23 - (fixed) incorrect dependency from jacktrip_main
24 - (update) RT thread priority for network I/O
25 - (update) clipping to saturation
26 - (update) build instructions
27
028 ---
129 1.2.2 (main)
230 - (added) bindPort range to reject oddball connections
+0
-475
JMess.cpp less more
0 /*
1 JMess: A simple utility so save your jack-audio mess.
2
3 Copyright (C) 2007-2010 Juan-Pablo Caceres.
4
5 Permission is hereby granted, free of charge, to any person
6 obtaining a copy of this software and associated documentation
7 files (the "Software"), to deal in the Software without
8 restriction, including without limitation the rights to use,
9 copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the
11 Software is furnished to do so, subject to the following
12 conditions:
13
14 The above copyright notice and this permission notice shall be
15 included in all copies or substantial portions of the Software.
16
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28 /*
29 * JMess.cpp
30 */
31
32 #include "JMess.h"
33 #include "JackTrip.h"
34 #include "jacktrip_globals.h"
35 #include <QDebug>
36
37
38 //-------------------------------------------------------------------------------
39 /*! \brief Constructs a JMess object that has a jack client.
40 *
41 */
42 //-------------------------------------------------------------------------------
43 JMess::JMess()
44 {
45 //Open a client connection to the JACK server. Starting a
46 //new server only to list its ports seems pointless, so we
47 //specify JackNoStartServer.
48 mClient = jack_client_open ("lsp", JackNoStartServer, &mStatus);
49 if (mClient == NULL) {
50 if (mStatus & JackServerFailed) {
51 cerr << "JACK server not running" << endl;
52 } else {
53 cerr << "jack_client_open() failed, "
54 << "status = 0x%2.0x\n" << mStatus << endl;
55 }
56 exit(1);
57 }
58 }
59
60
61 //-------------------------------------------------------------------------------
62 /*! \brief Distructor closes the jmess jack audio client.
63 *
64 */
65 //-------------------------------------------------------------------------------
66 JMess::~JMess()
67 {
68 if (jack_client_close(mClient))
69 cerr << "ERROR: Could not close the hidden jmess jack client." << endl;
70 }
71
72
73 //-------------------------------------------------------------------------------
74 /*! \brief Write an XML file with the name specified at xmlOutFile.
75 *
76 */
77 //-------------------------------------------------------------------------------
78 void JMess::writeOutput(QString xmlOutFile)
79 {
80 // QDomDocument jmess_xml; QDomElement root;
81 // QDomElement connection; QDomElement output;
82 // QDomElement input; QDomText output_name;
83 // QDomText input_name;
84
85 // QVector<QString> OutputInput(2);
86
87 // this->setConnectedPorts();
88
89 // root = jmess_xml.createElement("jmess");
90 // for (QVector<QVector<QString> >::iterator it = mConnectedPorts.begin();
91 // it != mConnectedPorts.end(); ++it) {
92 // OutputInput = *it;
93 // //cout << "Output ===> " <<qPrintable(OutputInput[0]) << endl;
94 // //cout << "Input ===> " <<qPrintable(OutputInput[1]) << endl;
95
96 // //Initialize XML elements
97 // connection = jmess_xml.createElement("connection");
98 // output = jmess_xml.createElement("output");
99 // input = jmess_xml.createElement("input");
100 // output_name = jmess_xml.createTextNode(OutputInput[0]);
101 // input_name = jmess_xml.createTextNode(OutputInput[1]);
102
103 // jmess_xml.appendChild(root); root.appendChild(connection);
104 // connection.appendChild(output); connection.appendChild(input);
105 // output.appendChild(output_name); input.appendChild(input_name);
106 // }
107
108 // //Write output file
109 // QFile file(xmlOutFile);
110 // string answer = "";
111 // //Check for existing file first, and confirm before overwriting
112 // if (file.exists()) {
113 // while ((answer != "yes") && (answer != "no")) {
114 // cout << "WARNING: The File " <<qPrintable(xmlOutFile)
115 // << " exists. Do you want to overwrite it? (yes/no): ";
116 // cin >> answer;
117 // }
118 // }
119 // else {
120 // answer = "yes";
121 // }
122
123 // if (answer == "yes") {
124 // if (!file.open(QIODevice::WriteOnly)) {
125 // cerr << "Cannot open file for writing: "
126 // << qPrintable(file.errorString()) << endl;
127 // exit(1);
128 // }
129
130 // QTextStream out(&file);
131 // jmess_xml.save(out, Indent);
132 // cout << qPrintable(xmlOutFile) << " written." << endl;
133 // }
134 }
135
136
137 //-------------------------------------------------------------------------------
138 /*! \brief Set list of ouput ports that have connections.
139 *
140 */
141 //-------------------------------------------------------------------------------
142 void JMess::setConnectedPorts()
143 {
144 mConnectedPorts.clear();
145
146 const char **ports, **connections; //vector of ports and connections
147 QVector<QString> OutputInput(2); //helper variable
148
149 //Get active output ports.
150 ports = jack_get_ports (mClient, NULL, NULL, JackPortIsOutput);
151
152 for (unsigned int out_i = 0; ports[out_i]; ++out_i) {
153 if ((connections = jack_port_get_all_connections
154 (mClient, jack_port_by_name(mClient, ports[out_i]))) != 0) {
155 for (unsigned int in_i = 0; connections[in_i]; ++in_i) {
156 OutputInput[0] = ports[out_i];
157 // cout << "Output ===> " <<qPrintable(OutputInput[0]) << endl;
158 OutputInput[1] = connections[in_i];
159 // cout << "Input ===> " << qPrintable(OutputInput[1]) << endl;
160 mConnectedPorts.append(OutputInput);
161 }
162 }
163 }
164
165 free(ports);
166 }
167 //*******************************************************************************
168 void JMess::connectSpawnedPorts(int nChans, int hubPatch)
169 // called from UdpHubListener::connectMesh
170 {
171 QString IPS[gMAX_WAIRS];
172 int ctr = 0;
173
174 const char **ports, **connections; //vector of ports and connections
175 QVector<QString> OutputInput(2); //helper variable
176
177 //Get active output ports.
178 ports = jack_get_ports (mClient, NULL, NULL, JackPortIsOutput);
179
180 for (unsigned int out_i = 0; ports[out_i]; ++out_i) {
181 // qDebug() << QString(ports[out_i]);
182 bool systemPort = QString(ports[out_i]).contains(QString("system"));
183
184 QString str = QString(ports[out_i]);
185 // for example "171.64.197.121:receive_1"
186 QString s = str.section(':', 0, 0);
187 // qDebug() << s << systemPort;
188 // for example "171.64.197.121"
189
190 bool newOne = !systemPort;
191 for (int i = 0; i<ctr; i++) if (newOne && (IPS[i]==s)) newOne = false;
192 if (newOne)
193 {
194 IPS[ctr] = s;
195 ctr++;
196 // qDebug() << ports[out_i] << systemPort << s;
197 }
198 }
199 for (int i = 0; i<ctr; i++) qDebug() << IPS[i];
200 disconnectAll();
201
202 int k = 0;
203 int jLimit = 1;
204
205 // FULLMIX is the union of CLIENTFOFI, CLIENTECHO
206
207 // implements CLIENTFOFI, CLIENTECHO -- also FULLMIX part which is CLIENTECHO
208 for (int i = 0; i<ctr; i++) {
209 if (hubPatch == JackTrip::CLIENTFOFI) jLimit = (ctr-1);
210 for (int j = 0; j<jLimit; j++) {
211 if ((hubPatch == JackTrip::CLIENTECHO)||(hubPatch == JackTrip::FULLMIX)) k = i;
212 else if (hubPatch == JackTrip::CLIENTFOFI) k = (j+(i+1))%ctr;
213 for (int l = 1; l<=nChans; l++) { // chans are 1-based
214 qDebug() << "connect " << IPS[i]+":receive_"+QString::number(l)
215 <<"with " << IPS[k]+":send_"+QString::number(l);
216
217 QString left = IPS[i] +
218 ":receive_" + QString::number(l);
219 QString right = IPS[k] +
220 ":send_" + QString::number(l);
221
222 if (0 !=
223 jack_connect(mClient, left.toStdString().c_str(), right.toStdString().c_str())) {
224 qDebug() << "WARNING: port: " << left
225 << "and port: " << right
226 << " could not be connected.";
227 }
228 }
229 }
230 }
231
232 // do it again to implement the FULLMIX part which is CLIENTFOFI
233 if (hubPatch == JackTrip::FULLMIX) {
234 jLimit = (ctr-1); // same as CLIENTFOFI
235 /*************/
236 // todo: the next block should be in a method, it's a repeat of the above
237 for (int i = 0; i<ctr; i++) {
238 for (int j = 0; j<jLimit; j++) {
239 k = (j+(i+1))%ctr;
240 for (int l = 1; l<=nChans; l++) { // chans are 1-based
241 qDebug() << "connect " << IPS[i]+":receive_"+QString::number(l)
242 <<"with " << IPS[k]+":send_"+QString::number(l);
243
244 QString left = IPS[i] +
245 ":receive_" + QString::number(l);
246 QString right = IPS[k] +
247 ":send_" + QString::number(l);
248
249 if (0 !=
250 jack_connect(mClient, left.toStdString().c_str(), right.toStdString().c_str())) {
251 qDebug() << "WARNING: port: " << left
252 << "and port: " << right
253 << " could not be connected.";
254 }
255 }
256 }
257 }
258 }
259
260 free(ports);
261 }
262
263 //*******************************************************************************
264 // connectTUB is called when in hubpatch mode 4 = RESERVEDMATRIX
265 // TU Berlin Raspberry Pi ensemble, Winter 2019
266 // this gets run on the ensemble's hub server with
267 // ./jacktrip -S -p3
268 // it connects a set of client jacktrips with known hardwired IP addresses
269 // to a known hardwired audio process with known hardwired audio port names
270 // when clients connect / disconnect dynamically this just runs through the
271 // audio connection sequence bruteforce at every new connection change
272 // those that are preexisting won't change
273 // a new one will connect accordingly and
274 // those that fail because they don't exist will fail, no worries
275
276 // setting the connections tested with jacktrip_globals.h
277 // const QString gDOMAIN_TRIPLE = QString("130.149.23"); // for TUB multiclient hub
278 // const int gMIN_TUB = 215; // lowest client address
279 // const int gMAX_TUB = 215; // highest client address
280
281 ///////////////////////////////
282 // test NUC as server
283 //#define HARDWIRED_AUDIO_PROCESS_ON_SERVER "par20straightWire"
284 //#define ENUMERATE ""
285 //#define HARDWIRED_AUDIO_PROCESS_ON_SERVER_IN ":in_"
286 //#define HARDWIRED_AUDIO_PROCESS_ON_SERVER_OUT ":out_"
287
288 ///////////////////////////////
289 // test Riviera as server
290 // for deployment change jacktrip_globals.h to
291 // const QString gDOMAIN_TRIPLE = QString("192.168.0"); // for TUB multiclient hub
292 // const int gMIN_TUB = 11; // lowest client address
293 // const int gMAX_TUB = 20; // highest client address
294 // and give the proper audio process and connection names
295
296 #define HARDWIRED_AUDIO_PROCESS_ON_SERVER "SuperCollider"
297 #define HARDWIRED_AUDIO_PROCESS_ON_SERVER_IN ":in_"
298 #define HARDWIRED_AUDIO_PROCESS_ON_SERVER_OUT ":out_"
299 // On server side it is SC jack-clients with indivisual names:
300 // POE_0...POE_16
301 // and each has (at this moment) one port in/out:
302 // receive_1
303 // send_1
304 // I think it should be extended to 4 in/out ports per client.
305
306 // this is brute force, does not look at individual clients, just patches the whole ensemble
307 // each time
308 void JMess::connectTUB(int /*nChans*/)
309 // called from UdpHubListener::connectPatch
310 {
311 for (int i = 0; i<=gMAX_TUB-gMIN_TUB; i++) // last IP decimal octet
312 for (int l = 1; l<=1; l++) // mono for now // chans are 1-based, 1...2
313 {
314 // jacktrip to SC
315 QString client = gDOMAIN_TRIPLE + QString(".") + QString::number(gMIN_TUB+i);
316 QString serverAudio = QString(HARDWIRED_AUDIO_PROCESS_ON_SERVER);
317 int tmp = i + l; // only works for mono... completely wrong for 2 or more chans
318 qDebug() << "connect " << client << ":receive_ " << l
319 <<"with " << serverAudio << HARDWIRED_AUDIO_PROCESS_ON_SERVER_IN << tmp;
320
321 QString left = QString(client + ":receive_" + QString::number(l));
322 QString right = QString(serverAudio + HARDWIRED_AUDIO_PROCESS_ON_SERVER_IN +
323 QString::number(tmp));
324
325 if (0 !=
326 jack_connect(mClient, left.toStdString().c_str(),
327 right.toStdString().c_str())) {
328 qDebug() << "WARNING: port: " << left
329 << "and port: " << right
330 << " could not be connected.";
331 }
332
333 // SC to jacktrip
334 tmp += 4; // increase tmp for port offest
335 qDebug() << "connect " << serverAudio << HARDWIRED_AUDIO_PROCESS_ON_SERVER_OUT
336 << tmp <<"with " << client << ":send_" << l;
337
338 left = QString(serverAudio + HARDWIRED_AUDIO_PROCESS_ON_SERVER_OUT +
339 QString::number(tmp));
340 right = QString(client + ":send_" + QString::number(l));
341
342 if (0 !=
343 jack_connect(mClient, left.toStdString().c_str(),
344 right.toStdString().c_str())) {
345 qDebug() << "WARNING: port: " << left
346 << "and port: " << right
347 << " could not be connected.";
348 }
349
350 }
351 }
352
353 //-------------------------------------------------------------------------------
354 /*! \brief Disconnect all the clients.
355 *
356 */
357 //-------------------------------------------------------------------------------
358 void JMess::disconnectAll()
359 {
360 QVector<QString> OutputInput(2);
361
362 this->setConnectedPorts();
363
364 for (QVector<QVector<QString> >::iterator it = mConnectedPorts.begin();
365 it != mConnectedPorts.end(); ++it) {
366 OutputInput = *it;
367
368 if (jack_disconnect(mClient, OutputInput[0].toLatin1(), OutputInput[1].toLatin1())) {
369 cerr << "WARNING: port: " << qPrintable(OutputInput[0])
370 << "and port: " << qPrintable(OutputInput[1])
371 << " could not be disconnected.\n";
372 }
373 }
374
375 }
376
377
378 //-------------------------------------------------------------------------------
379 /*! \brief Parse the XML input file.
380 *
381 * Returns 0 on success, or 1 if the file has an incorrect format or cannot
382 * read the file.
383 */
384 //-------------------------------------------------------------------------------
385 int JMess::parseXML(QString xmlInFile)
386 {
387 // mPortsToConnect.clear();
388 // QString errorStr;
389 // int errorLine;
390 // int errorColumn;
391
392 // QFile file(xmlInFile);
393 // if (!file.open(QIODevice::ReadOnly)) {
394 // cerr << "Cannot open file for reading: "
395 // << qPrintable(file.errorString()) << endl;
396 // return 1;
397 // }
398
399 // QDomDocument doc;
400 // if (!doc.setContent(&file, true, &errorStr, &errorLine,
401 // &errorColumn)) {
402 // cerr << "===================================================\n"
403 // << "Error parsing XML input file:\n"
404 // << "Parse error at line " << errorLine
405 // << ", column " << errorColumn << "\n"
406 // << qPrintable(errorStr) << "\n"
407 // << "===================================================\n";
408 // return 1;
409 // }
410
411 // QDomElement jmess = doc.documentElement();
412 // if (jmess.tagName() != "jmess") {
413 // cerr << "Error: Root tag should be <jmess>: "
414 // << qPrintable(jmess.tagName()) << endl;
415 // return 1;
416 // }
417
418
419 // QVector<QString> OutputInput(2);
420 // //First check for <connection> tag
421 // for(QDomNode n_cntn = jmess.firstChild();
422 // !n_cntn.isNull(); n_cntn = n_cntn.nextSibling()) {
423 // QDomElement cntn = n_cntn.toElement();
424 // if (cntn.tagName() == "connection") {
425 // //Now check for ouput & input tag
426 // for(QDomNode n_sck = cntn.firstChild();
427 // !n_sck.isNull(); n_sck = n_sck.nextSibling()) {
428 // QDomElement sck = n_sck.toElement();
429 // //cout << qPrintable(sck.tagName()) << endl;
430 // //cout << qPrintable(sck.text()) << endl;
431 // if (sck.tagName() == "output") {
432 // OutputInput[0] = sck.text();
433 // }
434 // else if (sck.tagName() == "input") {
435 // OutputInput[1] = sck.text();
436 // }
437 // }
438 // mPortsToConnect.append(OutputInput);
439 // }
440 // }
441
442 return 0;
443
444 }
445
446
447 //-------------------------------------------------------------------------------
448 /*! \brief Connect ports specified in input XML file xmlInFile
449 *
450 */
451 //-------------------------------------------------------------------------------
452 void JMess::connectPorts(QString xmlInFile)
453 {
454 QVector<QString> OutputInput(2);
455
456 // if ( !(this->parseXML(xmlInFile)) ) {
457 // for (QVector<QVector<QString> >::iterator it = mPortsToConnect.begin();
458 // it != mPortsToConnect.end(); ++it) {
459 // OutputInput = *it;
460
461 // if (jack_connect(mClient, OutputInput[0].toLatin1(), OutputInput[1].toLatin1())) {
462 // //Display a warining only if the error is not because the ports are already
463 // //connected, in case the program doesn't display anyting.
464 // if (EEXIST !=
465 // jack_connect(mClient, OutputInput[0].toLatin1(), OutputInput[1].toLatin1())) {
466 // cerr << "WARNING: port: " << qPrintable(OutputInput[0])
467 // << "and port: " << qPrintable(OutputInput[1])
468 // << " could not be connected.\n";
469 // }
470 // }
471 // }
472 // }
473
474 }
WIN10BUILDINSTRUCTIONS.pdf less more
Binary diff not shown
0 h headers :
1 install -d headersdir
2 $(MAKE) DEST='headersdir/' ARCH='faust2header.cpp' -f Makefile.headers
3
4 ih hi installheaders : headers
5 install -m 0444 headersdir/*.h ../src/
6
7 # The JackTrip project does not need the remaining make targets, except "clean" is nice to have:
8
09 all : jackgtk
110
211 test: jackgtk alsagtk jackqt alsaqt ladspa ossgtk bench plot sndfile jackconsole
312
413 svg:
514 $(MAKE) -f Makefile.svg
6
15
716 puredata :
817 install -d puredatadir
918 $(MAKE) DEST='puredatadir/' ARCH='puredata.cpp' LIB='' -f Makefile.pdcompile
1019
1120 alsagtk :
1221 install -d alsagtkdir
13 $(MAKE) DEST='alsagtkdir/' ARCH='alsa-gtk.cpp' LIB='-lpthread -lasound `pkg-config --cflags --libs gtk+-2.0`' -f Makefile.compile
22 $(MAKE) DEST='alsagtkdir/' ARCH='alsa-gtk.cpp' LIB='-lpthread -lasound `pkg-config --cflags --libs gtk+-2.0`' -f Makefile.compile
1423
1524 jackgtk :
1625 install -d jackgtkdir
2736 ladspa :
2837 install -d ladspadir
2938 $(MAKE) DEST='ladspadir/' ARCH='ladspa.cpp' LIB='-fPIC -shared' EXT='.so' -f Makefile.ladspacompile
30
39
3140 jackwx :
3241 install -d jackwxdir
3342 $(MAKE) DEST='jackwxdir/' ARCH='jack-wx.cpp' LIB='`pkg-config jack --cflags --libs` `wx-config --cflags --libs`' -f Makefile.compile
4655
4756 pawx :
4857 install -d pawxdir
49 $(MAKE) DEST='pawxdir/' ARCH='pa-wx.cpp' LIB='-lpthread -lportaudio `wx-config --cflags --libs`' -f Makefile.compile
58 $(MAKE) DEST='pawxdir/' ARCH='pa-wx.cpp' LIB='-lpthread -lportaudio `wx-config --cflags --libs`' -f Makefile.compile
5059
5160 module :
5261 install -d moduledir
93102 $(MAKE) DEST='jackconsoledir/' ARCH='jack-console.cpp' LIB='`pkg-config --cflags --libs jack `' -f Makefile.compile
94103
95104 clean :
96 rm -rf alsagtkdir jackgtkdir alsaqtdir jackqtdir vecalsagtkdir vecjackgtkdir ladspadir jackwxdir ossgtkdir osswxdir pagtkdir pawxdir moduledir bundledir mspdir vstdir benchdir sndfiledir plotdir benchdir supercolliderdir puredatadir qdir plotdir jackconsoledir matlabplotdir *-ps *-svg
97
98
105 -rm -rf alsagtkdir jackgtkdir alsaqtdir jackqtdir vecalsagtkdir vecjackgtkdir ladspadir jackwxdir ossgtkdir osswxdir pagtkdir pawxdir moduledir bundledir mspdir vstdir benchdir sndfiledir plotdir benchdir supercolliderdir puredatadir qdir plotdir jackconsoledir matlabplotdir *-ps *-svg headersdir
0 dspsrc := $(wildcard *.dsp)
1 headers := $(addprefix $(DEST), $(dspsrc:.dsp=.h))
2
3 all : $(headers)
4
5 FAUST = faust --inline-architecture-files --in-place
6 # --in-place (-inpl) means the input signal array can be used
7 # as the output signal array in the compute() function.
8 # --inline-architecture-files (-i) means that all Faust headers
9 # and include files get included in the output C++ file
10 # so that it can be compiled without a Faust installation
11 # on the compiling machine.
12
13 $(DEST)%.h : %.dsp
14 $(FAUST) $(VEC) -cn $(<:.dsp=) -a $(ARCH) $< -o $(DEST)$(<:.dsp=).h
15 #(cat $(@:.h=).cpp | sed -e s/mydsp/$(<:.dsp=)/g) > $@
16 #/bin/rm $(@:.h=).cpp
17
18 # Probably needed for headers after the first: (cat $(@:.h=).cpp | sed -e /template/d | sed -e s/mydsp/$(<:.dsp=)/g) > $@
19
20 clean :
21 rm -f $(DEST)
22
23 # Working example:
24 # lh limiterdsp.h: limiterdsp.dsp
25 # faust -inpl -cn limiterdsp -a faust2header.cpp limiterdsp.dsp -o limiterdsp.cpp
26 # (cat limiterdsp.cpp | sed -e /template/d | sed -e s/mydsp/limiterdsp/g) > limiterdsp.h
0 The audio limiter in use by jacktrip is limiterdsp.dsp
1
2 To regenerate ../src/limiterdsp.h, you can say (if you have Faust installed)
3
4 make headers
5
6 in this directory to create ./headersdir/limiterdsp.h
7 and then copy that to ../src/ to reinstall it.
8
9 To test the limiter separately, you can load it into
10 fausteditor.grame.fr to compile and download an executable. With
11 Faust installed, you can do it at the command line: To make a
12 standalone JACK app for Mac, say
13
14 faust2jaqt limiterdsp.dsp
15
16 For Linux, you want either that or
17
18 faust2jack limiterdsp.dsp
19
20 (to use GTK in place of Qt for the GUI).
21
22 Then you just run it and patch it in (using qjackctl) between your audio capture and jacktrip input.
0 process = _ : component("compressordsp.dsp") : component("limiterdsp.dsp") <: _,_;
1
0 declare name "compressor";
1 declare version "0.0";
2 declare author "Julius Smith";
3 declare license "MIT Style STK-4.2";
4 declare description "Compressor demo application, adapted from the Faust Library's dm.compressor_demo in demos.lib";
5 declare documentation "https://faustlibraries.grame.fr/libs/compressors/#cocompressor_mono";
6
7 import("stdfaust.lib");
8
9 //----------------------------`(dm.)compressor_mono_demo`-------------------------
10 // Mono Compressor
11 //
12 // #### Usage
13 //
14 // ```
15 // _ : compressor_mono_demo : _;
16 // ```
17 //------------------------------------------------------------
18 compressor_demo = ba.bypass1(cbp,compressor_mono_demo)
19 with {
20 comp_group(x) = vgroup("COMPRESSOR [tooltip: References:
21 https://faustlibraries.grame.fr/libs/compressors/
22 http://en.wikipedia.org/wiki/Dynamic_range_compression]", x);
23
24 meter_group(x) = comp_group(hgroup("[0]", x));
25 knob_group(x) = comp_group(hgroup("[1]", x));
26
27 cbp = meter_group(checkbox("[0] Bypass [tooltip: When this is checked, the compressor
28 has no effect]"));
29 gainview = co.compression_gain_mono(ratio,threshold,attack,release) : ba.linear2db :
30 meter_group(hbargraph("[1] Compressor Gain [unit:dB] [tooltip: Compressor gain in dB]",-50,+10));
31
32 displaygain = _ <: _,abs : _,gainview : attach;
33
34 compressor_stereo_demo =
35 displaygain(co.compressor_stereo(ratio,threshold,attack,release)) :
36 *(makeupgain), *(makeupgain);
37
38 compressor_mono_demo =
39 displaygain(co.compressor_mono(ratio,threshold,attack,release)) :
40 *(makeupgain);
41
42 ctl_group(x) = knob_group(hgroup("[3] Compression Control", x));
43
44 ratio = ctl_group(hslider("[0] Ratio [style:knob]
45 [tooltip: A compression Ratio of N means that for each N dB increase in input
46 signal level above Threshold, the output level goes up 1 dB]",
47 2, 1, 20, 0.1));
48
49 threshold = ctl_group(hslider("[1] Threshold [unit:dB] [style:knob]
50 [tooltip: When the signal level exceeds the Threshold (in dB), its level
51 is compressed according to the Ratio]",
52 -24, -100, 10, 0.1));
53
54 env_group(x) = knob_group(hgroup("[4] Compression Response", x));
55
56 attack = env_group(hslider("[1] Attack [unit:ms] [style:knob] [scale:log]
57 [tooltip: Time constant in ms (1/e smoothing time) for the compression gain
58 to approach (exponentially) a new lower target level (the compression
59 `kicking in')]", 15, 1, 1000, 0.1)) : *(0.001) : max(1/ma.SR);
60
61 release = env_group(hslider("[2] Release [unit:ms] [style: knob] [scale:log]
62 [tooltip: Time constant in ms (1/e smoothing time) for the compression gain
63 to approach (exponentially) a new higher target level (the compression
64 'releasing')]", 40, 1, 1000, 0.1)) : *(0.001) : max(1/ma.SR);
65
66 makeupgain = comp_group(hslider("[5] MakeUpGain [unit:dB]
67 [tooltip: The compressed-signal output level is increased by this amount
68 (in dB) to make up for the level lost due to compression]",
69 2, -96, 96, 0.1)) : ba.db2linear;
70 };
71
72 process = _ : compressor_demo : _;
0 // NOTE: ANY INCLUDE-GUARD HERE MUST BE DERIVED FROM THE CLASS NAME
1 //
2 // faust2header.cpp - FAUST Architecture File
3 // This is a simple variation of matlabplot.cpp in the Faust distribution
4 // aimed at creating a simple C++ header file (.h) containing a Faust DSP.
5 // See the Makefile for how to use it.
6
7 #include <faust/dsp/dsp.h>
8
9 #include <faust/gui/APIUI.h>
10
11 // NOTE: "faust -scn name" changes the last line above to
12 // #include <faust/name/name.h>
13
14 //----------------------------------------------------------------------------
15 // FAUST Generated Code
16 //----------------------------------------------------------------------------
17
18 <<includeIntrinsic>>
19
20 <<includeclass>>
0 declare name "freeverb";
1 declare version "0.0";
2 declare author "Romain Michon";
3 declare license "LGPL";
4 declare description "Freeverb implementation in Faust, from the Faust Library's dm.freeverb_demo in demos.lib";
5
6 import("stdfaust.lib");
7
8 //----------------------------`(dm.)freeverb_demo`-------------------------
9 // Freeverb demo application.
10 //
11 // #### Usage
12 //
13 // ```
14 // _,_ : freeverb_demo : _,_;
15 // ```
16 //------------------------------------------------------------
17 // Author: Romain Michon
18 // License: LGPL
19 freeverb_demo = _,_ <: (*(g)*fixedgain,*(g)*fixedgain :
20 re.stereo_freeverb(combfeed, allpassfeed, damping, spatSpread)),
21 *(1-g), *(1-g) :> _,_
22 with{
23 scaleroom = 0.28;
24 offsetroom = 0.7;
25 allpassfeed = 0.5;
26 scaledamp = 0.4;
27 fixedgain = 0.1;
28 origSR = 44100;
29
30 parameters(x) = hgroup("Freeverb",x);
31 knobGroup(x) = parameters(vgroup("[0]",x));
32 damping = knobGroup(vslider("[0] Damp [style: knob] [tooltip: Somehow control the
33 density of the reverb.]",0.5, 0, 1, 0.025)*scaledamp*origSR/ma.SR);
34 combfeed = knobGroup(vslider("[1] RoomSize [style: knob] [tooltip: The room size
35 between 0 and 1 with 1 for the largest room.]", 0.1, 0, 1, 0.025)*scaleroom*
36 origSR/ma.SR + offsetroom);
37 spatSpread = knobGroup(vslider("[2] Stereo Spread [style: knob] [tooltip: Spatial
38 spread between 0 and 1 with 1 for maximum spread.]",0.5,0,1,0.01)*46*ma.SR/origSR
39 : int);
40 g = parameters(vslider("[1] Wet [tooltip: The amount of reverb applied to the signal
41 between 0 and 1 with 1 for the maximum amount of reverb.]", 0.1, 0, 1, 0.025));
42 };
43
44 process = freeverb_demo;
0 process = _ <: _,_ : component("freeverbdsp.dsp") : _,_ :> _; // there is no mono-to-stereo support in jacktrip
1
0 // Version added to JackTrip (standalone program test):
1
2 import("stdfaust.lib");
3 N = hslider("[0] NumClientsAssumed",2,1,64,1);
4 softClipLevel = 0.5; // start compressing at this amplitude - KEEP IN SYNC with setWarningAmplitude() in ../src/Effects.h
5 gain = 1.0 / sqrt(float(N)); // assume power-based client sum - KEEP IN SYNC with limiterAmp in ../src/Limiter.h
6 // lookahead(s), threshold, attack(s), hold(s), release(s)
7 limiter = co.limiter_lad_mono(0.0001, softClipLevel, 0.00001, 0.1, 0.25); // GPLv3 license
8 // If you need a less restricted license, try co.limiter_1176_R4_mono (MIT style license)
9
10 process = *(gain) : limiter;
0 // Test signal used by ../src/Limiter.cpp
1
2 import("stdfaust.lib");
3 freq = hslider("[0] Freq",110.0,20.0,10000.0,1);
4 amp = hslider("[0] Amp",0.2,0.0,1.0,0.0001);
5 //process = amp * os.oscrs(freq);
6 process = amp * os.sawtooth(freq);
0 // Doc: https://faustlibraries.grame.fr/libs/compressors/
1
2 cs = hslider("Compressor [style:radio{'1':0; '2': 1 }]", 0,0,1,1);
3
4 c1 = component("compressordsp.dsp"); // ./compressordsp.dsp
5 c2 = component("compressor2dsp.dsp"); // ./compressor2dsp.dsp
6 compressor(cs) = _ <: select2(cs,c1,c2);
7
8 limiter_group(x) = vgroup("LIMITER [tooltip: https://faustlibraries.grame.fr/libs/compressors/#functions-reference]",x);
9
10 process = _ : compressor(cs) : limiter_group(component("limiterdsp.dsp")) <: _,_;
11
12 /*
13 * My present conclusion is to continue with c1, because it uses the
14 * more standard 'ratio' parameter, while c2 uses 'strength', which becomes
15 * hard-clipping at strength=1. Also, I hear no compelling difference sonically
16 * (after laboriously finding a strength value that is roughly comparable to ratio).
17 *
18 * Also, c2 is GPL license, which cannot go into closed-source products,
19 * while c1 can be freely used as desired (STK-4.2 license).
20 */
0 declare name "compressor2"; // more modern feedback-compressor with release-to-threshold
1 declare version "0.0";
2 declare author "Julius Smith";
3 declare license "MIT Style STK-4.2"; // but using GPLv3
4 declare description "adapted from ./compressordsp.dsp adding use of co.FBFFcompressor_N_chan";
5 declare documentation "https://faustlibraries.grame.fr/libs/compressors/#cofffbcompressor_n_chan";
6
7 import("stdfaust.lib");
8
9 // #### Usage
10 //
11 // ```
12 // _ : compressor2_mono_demo : _;
13 // ```
14 //------------------------------------------------------------
15 compressor2_demo = ba.bypass1(cbp,compressor2_mono_demo)
16 with {
17 comp_group(x) = vgroup("COMPRESSOR2 [tooltip: Reference:
18 http://en.wikipedia.org/wiki/Dynamic_range_compression]", x);
19
20 meter_group(x) = comp_group(hgroup("[0]", x));
21 knob_group(x) = comp_group(hgroup("[1]", x));
22
23 cbp = meter_group(checkbox("[0] Bypass [tooltip: When this is checked, the compressor2
24 has no effect]"));
25
26 // API: co.FBFFcompressor_N_chan(strength,thresh,att,rel,knee,prePost,link,FBFF,meter,N)
27 // strength = min(ratio-1.0,5)/5.0; // crude hack - will be wrong
28 knee = 5; // dB window about threshold for knee
29 prePost = 1; // level detector location: 0 for input, 1 for output (for feedback compressor)
30 link = 0; // linkage between channels (irrelevant for mono)
31 FBFF = 1; // cross-fade between feedforward (0) and feedback (1) compression
32 maxGR = -50; // dB - Max Gain Reduction (only affects display)
33 meter = _<:(_, (ba.linear2db:max(maxGR):meter_group((hbargraph("[1] Compressor Gain [unit:dB][tooltip: Compressor gain in dB]", maxGR, 10))))):attach;
34 //meter = _; // use gainview below instead to look more like compressordsp.dsp
35 NChans = 1;
36
37 // compressordsp.dsp: gainview = co.compression_gain_mono(strength,threshold,attack,release)
38 // threshold gets doubled for the feedback case, but not for feedforward (see compressors.lib):
39 gainview = co.peak_compression_gain_N_chan(strength,2*threshold,attack,release,knee,prePost,link,NChans)
40 : ba.linear2db : max(maxGR) :
41 meter_group(hbargraph("[1] Compressor2 Gain [unit:dB] [tooltip: Current gain of
42 the compressor2 in dB]",maxGR,+10));
43
44 // use built-in gain display:
45 displaygain = _;
46 // not the same: displaygain = _ <: _,abs : _,gainview : attach;
47
48 compressor2_mono_demo =
49 displaygain(co.FBFFcompressor_N_chan(strength,threshold,attack,release,knee,prePost,link,FBFF,meter,NChans)) :
50 *(makeupgain);
51
52 ctl_group(x) = knob_group(hgroup("[3] Compression Control", x));
53
54 strength = ctl_group(hslider("[0] Strength [style:knob]
55 [tooltip: A compression Strength of 0 means no compression, while 1 yields infinit compression (hard limiting)]",
56 0.1, 0, 1, 0.01)); // 0.1 seems to be pretty close to ratio == 2, based on watching the gain displays
57
58 threshold = ctl_group(hslider("[1] Threshold [unit:dB] [style:knob]
59 [tooltip: When the signal level exceeds the Threshold (in dB), its level
60 is compressed according to the Strength]",
61 -24, -100, 10, 0.1));
62
63 env_group(x) = knob_group(hgroup("[4] Compression Response", x));
64
65 attack = env_group(hslider("[1] Attack [unit:ms] [style:knob] [scale:log]
66 [tooltip: Time constant in ms (1/e smoothing time) for the compression gain
67 to approach (exponentially) a new lower target level (the compression
68 `kicking in')]", 15, 1, 1000, 0.1)) : *(0.001) : max(1/ma.SR);
69
70 release = env_group(hslider("[2] Release [unit:ms] [style: knob] [scale:log]
71 [tooltip: Time constant in ms (1/e smoothing time) for the compression gain
72 to approach (exponentially) a new higher target level (the compression
73 'releasing')]", 40, 1, 1000, 0.1)) : *(0.001) : max(1/ma.SR);
74
75 makeupgain = comp_group(hslider("[5] MakeUpGain [unit:dB]
76 [tooltip: The compressed-signal output level is increased by this amount
77 (in dB) to make up for the level lost due to compression]",
78 2, -96, 96, 0.1)) : ba.db2linear;
79 };
80
81 process = _ : compressor2_demo : _;
0 import("stdfaust.lib");
1
2 // Modified version from Faust Libraries demos.lib
3
4 process = zita_rev1; // same as dm.zita_rev1 but for wetness control and some defaults
5
6 //----------------------------------`(dm.)zita_rev1`------------------------------
7 // Example GUI for `zita_rev1_stereo` (mostly following the Linux `zita-rev1` GUI).
8 //
9 // Only the dry/wet and output level parameters are "dezippered" here. If
10 // parameters are to be varied in real time, use `smooth(0.999)` or the like
11 // in the same way.
12 //
13 // #### Usage
14 //
15 // ```
16 // _,_ : zita_rev1 : _,_
17 // ```
18 //
19 // #### Reference
20 //
21 // <http://www.kokkinizita.net/linuxaudio/zita-rev1-doc/quickguide.html>
22 //------------------------------------------------------------
23 zita_rev1 = _,_ <: re.zita_rev1_stereo(rdel,f1,f2,t60dc,t60m,fsmax),_,_ : out_eq,_,_ :
24 wet_dry_2(wet) : out_level
25 with{
26 fsmax = 48000.0; // highest sampling rate that will be used
27
28 fdn_group(x) = hgroup(
29 "[0] Zita_Rev1 [tooltip: ~ ZITA REV1 FEEDBACK DELAY NETWORK (FDN) & SCHROEDER
30 ALLPASS-COMB REVERBERATOR (8x8). See Faust's reverbs.lib for documentation and
31 references]", x);
32
33 in_group(x) = fdn_group(hgroup("[1] Input", x));
34
35 rdel = in_group(vslider("[1] In Delay [unit:ms] [style:knob] [tooltip: Delay in ms
36 before reverberation begins]",60,20,100,1));
37
38 freq_group(x) = fdn_group(hgroup("[2] Decay Times in Bands (see tooltips)", x));
39
40 f1 = freq_group(vslider("[1] LF X [unit:Hz] [style:knob] [scale:log] [tooltip:
41 Crossover frequency (Hz) separating low and middle frequencies]", 200, 50, 1000, 1));
42
43 t60dc = freq_group(vslider("[2] Low RT60 [unit:s] [style:knob] [scale:log]
44 [style:knob] [tooltip: T60 = time (in seconds) to decay 60dB in low-frequency band]",
45 3, 1, 8, 0.1));
46
47 t60m = freq_group(vslider("[3] Mid RT60 [unit:s] [style:knob] [scale:log] [tooltip:
48 T60 = time (in seconds) to decay 60dB in middle band]",2, 1, 8, 0.1));
49
50 f2 = freq_group(vslider("[4] HF Damping [unit:Hz] [style:knob] [scale:log]
51 [tooltip: Frequency (Hz) at which the high-frequency T60 is half the middle-band's T60]",
52 6000, 1500, 0.49*fsmax, 1));
53
54 out_eq = pareq_stereo(eq1f,eq1l,eq1q) : pareq_stereo(eq2f,eq2l,eq2q);
55 // Zolzer style peaking eq (not used in zita-rev1) (filters.lib):
56 // pareq_stereo(eqf,eql,Q) = peak_eq(eql,eqf,eqf/Q), peak_eq(eql,eqf,eqf/Q);
57 // Regalia-Mitra peaking eq with "Q" hard-wired near sqrt(g)/2 (filters.lib):
58 pareq_stereo(eqf,eql,Q) = fi.peak_eq_rm(eql,eqf,tpbt), fi.peak_eq_rm(eql,eqf,tpbt)
59 with {
60 tpbt = wcT/sqrt(max(0,g)); // tan(PI*B/SR), B bw in Hz (Q^2 ~ g/4)
61 wcT = 2*ma.PI*eqf/ma.SR; // peak frequency in rad/sample
62 g = ba.db2linear(eql); // peak gain
63 };
64
65 eq1_group(x) = fdn_group(hgroup("[3] RM Peaking Equalizer 1", x));
66
67 eq1f = eq1_group(vslider("[1] Eq1 Freq [unit:Hz] [style:knob] [scale:log] [tooltip:
68 Center-frequency of second-order Regalia-Mitra peaking equalizer section 1]",
69 315, 40, 2500, 1));
70
71 eq1l = eq1_group(vslider("[2] Eq1 Level [unit:dB] [style:knob] [tooltip: Peak level
72 in dB of second-order Regalia-Mitra peaking equalizer section 1]", 0, -15, 15, 0.1));
73
74 eq1q = eq1_group(vslider("[3] Eq1 Q [style:knob] [tooltip: Q = centerFrequency/bandwidth
75 of second-order peaking equalizer section 1]", 3, 0.1, 10, 0.1));
76
77 eq2_group(x) = fdn_group(hgroup("[4] RM Peaking Equalizer 2", x));
78
79 eq2f = eq2_group(vslider("[1] Eq2 Freq [unit:Hz] [style:knob] [scale:log] [tooltip:
80 Center-frequency of second-order Regalia-Mitra peaking equalizer section 2]",
81 1500, 160, 10000, 1));
82
83 eq2l = eq2_group(vslider("[2] Eq2 Level [unit:dB] [style:knob] [tooltip: Peak level
84 in dB of second-order Regalia-Mitra peaking equalizer section 2]", 0, -15, 15, 0.1));
85
86 eq2q = eq2_group(vslider("[3] Eq2 Q [style:knob] [tooltip: Q = centerFrequency/bandwidth
87 of second-order peaking equalizer section 2]", 3, 0.1, 10, 0.1));
88
89 out_group(x) = fdn_group(hgroup("[5] Output", x));
90
91 wet_dry(wet,y,x) = wet*y + (1-wet)*x;
92
93 wet_dry_2(wet,y1,y2,x1,x2) = wet_dry(wet,y1,x1), wet_dry(wet,y2,x2);
94
95 wet = out_group(vslider("[1] Wet [style:knob] [tooltip: Dry/Wet Mix: 0 = dry, 1 = wet]",
96 0, 0.0, 1.0, 0.01)) : si.smoo;
97
98 out_level = *(gain),*(gain);
99
100 gain = out_group(vslider("[2] Level [unit:dB] [style:knob] [tooltip: Output scale
101 factor]", -3, -70, 20, 0.1)) : ba.db2linear : si.smoo;
102 };
0 process = _ <: _,_ : component("zitarevdsp.dsp") : _,_ :> _;
1
0 project('jacktrip', 'cpp', version: '1.2')
0 project('jacktrip', 'cpp', version: '1.2',
1 default_options: ['cpp_std=c++11'])
12 qt5 = import('qt5')
23 qt5_dep = dependency('qt5', modules: ['Core', 'Network'])
34 jack_dep = dependency('jack')
4 rtaudio_dep = dependency('rtaudio')
55 thread_dep = dependency('threads')
66
77 defines = []
88 if host_machine.system() == 'linux'
99 defines += '-D__LINUX__'
10 elif host_machine.system() == 'osx'
10 elif host_machine.system() == 'darwin'
1111 defines += '-D__MAC_OSX__'
1212 elif host_machine.system() == 'windows'
1313 defines += '-D__WIN_32__'
2727 src = ['src/DataProtocol.cpp',
2828 'src/JMess.cpp',
2929 'src/JackTrip.cpp',
30 'src/AudioTester.cpp',
3031 'src/jacktrip_globals.cpp',
3132 'src/jacktrip_main.cpp',
3233 'src/JackTripThread.cpp',
3536 'src/PacketHeader.cpp',
3637 'src/ProcessPlugin.cpp',
3738 'src/RingBuffer.cpp',
39 'src/JitterBuffer.cpp',
3840 'src/Settings.cpp',
3941 'src/UdpDataProtocol.cpp',
4042 'src/UdpHubListener.cpp',
4143 'src/AudioInterface.cpp',
42 'src/JackAudioInterface.cpp']
44 'src/JackAudioInterface.cpp',
45 'src/Compressor.cpp',
46 'src/Limiter.cpp',
47 'src/Reverb.cpp']
4348
44 executable('jacktrip', src, moc_files, dependencies: [qt5_dep, jack_dep, rtaudio_dep, thread_dep], cpp_args: defines, install: true )
49 executable('jacktrip', src, moc_files, dependencies: [qt5_dep, jack_dep, thread_dep], cpp_args: defines, install: true )
0 echo calculate audio round trip
1 rm /tmp/art.dat
2 $( jack_iodelay > /tmp/art.dat 2>&1 & )
3 # jack_iodelay &
4 sleep 1
5 # jack_connect jack_delay:out jackloop$1.stanford.edu:send_2
6 # jack_connect jackloop$1.stanford.edu:receive_2 jack_delay:in
7 jack_disconnect __1:receive_1 __1:send_1
8 jack_disconnect __1:receive_2 __1:send_2
9 # jack_disconnect localhost:receive_1 localhost:send_1
10 # jack_disconnect localhost:receive_2 localhost:send_2
11 jack_connect jack_delay:out __1:send_1
12 jack_connect __1:receive_1 jack_delay:in
13
14 sleep 8
15 killall jack_iodelay
16 sleep 1
17
18 killall jacktrip
19 killall jackd
20
21 DEFAULTOUTPUT=-1
22 AWKOUTPUT=$(grep total /tmp/art.dat | \
23 awk '{ sum += $3; n++ } END { if (n > 0) print sum / n; }')
24 printf -v AWKWARDINT %.0f "$AWKOUTPUT"
25 if (($AWKWARDINT > 0 ))
26 then
27 echo $AWKOUTPUT
28 exit 0
29 else
30 echo $DEFAULTOUTPUT
31 exit 1
32 fi
33
34
0 #!/bin/bash
1 # bash script for jacktrip automation, Chris Chafe
2 # startJacktripHubClient.sh <FPP>
3 #
4 # /home/cc/Desktop/sh/startJacktripHubClient.sh /home/cc/jacktrip/builddir/jacktrip %p
5
6 JACKTRIP=$1
7
8 ### qjackctl start / stop example
9 ## qjackctl Setup : Options : Execute scrpt after Startup
10 # /home/cc/Desktop/sh/startJacktripHubClient.sh %p
11 ## qjackctl Setup : Options : Execute scrpt on Shutdown
12 # /home/cc/Desktop/sh/stopJacktrip.sh
13 ## timing of scrpt call means jacktrip is still running and
14 ## an alert will appear for each new server it tries to shutdown
15 ## for both <scripts> do, chmod +x <script>.sh
16
17 ### manual start example
18 # ./jacktrip -C jackloop128.stanford.edu
19
20 ### automatic client start in qjackctl : Setup : Options Execute script after Startup
21 ### examples with line used in qjackctl and corresponding script
22 ## specify full server name
23 # /home/cc/startJacktrip.sh jackloop128.stanford.edu
24 # SERVER=localhost
25
26 ## server name from file
27 # /home/cc/startJacktrip.sh jackloop1024.stanford.edu
28 # SERVER=$(cat ../../server.txt)
29
30 ## composed server name, %p = fpp
31 # /home/cc/startJacktrip.sh %p
32
33
34 if [ -z "$2" ]
35 then
36 SERVER=localhost
37 else
38 FPP=$2
39 SERVER=jackloop$FPP.stanford.edu
40 fi
41
42
43 echo starting hub client of server running on $SERVER
44
45 $( $JACKTRIP -C $SERVER > /dev/null 2>&1 & )
46
47
48
49
0 #!/bin/bash
1 # bash script for jacktrip automation, Chris Chafe
2 # startJacktripHubServer.sh <FPP>
3
4 JACKTRIP=$1
5
6
7 echo starting $JACKTRIP server
8
9 $( $JACKTRIP -S -p1 > /dev/null 2>&1 & )
10
11
12
13
0 #!/bin/bash
1 # test_hub_mode_server_and_client.sh
2 # bash script for automatic testing of jacktrip in hub mode , Chris Chafe
3 # connects a hub client to a hub server (started with with -p1) on the same host
4 # prints avg audio RTT after 8 sec, or -1 if fail
5 # ./test_hub_mode_server_and_client.sh <path-to-executable> <FPP>
6 # requires 3 helper scripts
7 # -- startJacktripHubServer.sh
8 # -- startJacktripHubClient.sh
9 # -- art.sh
10 # requires jackd be available on the host
11 # uses the "dummy" interface, so no audio interface needed
12 # first does some jackd cleanup
13 # takes approx. 20 sec to complete
14
15 # a passing test prints to the console
16 # [cc@localhost sh]$ ./test.sh /home/cc/jacktrip/builddir/jacktrip 32
17 # starting /home/cc/jacktrip/builddir/jacktrip hub mode test at 32 FPP
18 # starting hub client for server localhost
19 # calculate audio round trip
20 # 4
21
22 # a failed test prints to the console
23 # [cc@localhost functionTests]$ ./test.sh ~/jacktrip/builddir/jacktrip 32
24 # starting /home/cc/jacktrip/builddir/jacktrip hub mode test at 32 FPP
25 # starting /home/cc/jacktrip/builddir/jacktrip server
26 # starting hub client of server running on localhost
27 # calculate audio round trip
28 # ERROR ..1:send_1 not a valid port
29 # ERROR ..1:send_2 not a valid port
30 # ERROR ..1:send_1 not a valid port
31 # ERROR ..1:receive_1 not a valid port
32 # jacktrip: no process found
33 # -1
34
35
36 JACKTRIP=$1
37
38 if [ -z "$2" ]
39 then
40 FPP=128
41 else
42 FPP=$2
43 fi
44
45 # killall jackd
46 if [ "$(ps -aux | grep -c jackd)" != 1 ]; then killall jackd; fi;
47 # if jackd is or has been running with another driver
48 # much experimenation shows it literally takes this long
49 sleep 17
50 # to flush old connections before starting the dummy driver
51
52 # start jack with dummy driver, or change to an audio interface by switching these lines
53 $( /usr/bin/jackd -ddummy -r48000 -p$FPP > /dev/null 2>&1 & )
54 # $( /usr/bin/jackd -dalsa -dhw:A96 -r48000 -p$FPP -n2 > /dev/null 2>&1 & )
55 # $( /usr/bin/jackd -dalsa -dhw:PCH -r48000 -p$FPP -n2 > /dev/null 2>&1 & )
56
57 sleep 1
58
59 echo starting $JACKTRIP hub mode test at $FPP FPP
60
61 $PWD/startJacktripHubServer.sh $JACKTRIP
62 sleep 1
63 $PWD/startJacktripHubClient.sh $JACKTRIP
64
65 sleep 1
66
67 # start measuring audio RTT
68 $PWD/art.sh
69
3838 #include "JackTrip.h"
3939 #include <iostream>
4040 #include <cmath>
41 #include <assert.h>
4142
4243 using std::cout; using std::endl;
4344
5657 mAudioBitResolution(AudioBitResolution*8),
5758 mBitResolutionMode(AudioBitResolution),
5859 mSampleRate(gDefaultSampleRate), mBufferSizeInSamples(gDefaultBufferSizeInSamples),
59 mInputPacket(NULL), mOutputPacket(NULL)
60 mInputPacket(NULL), mOutputPacket(NULL), mLoopBack(false), mProcessingAudio(false)
6061 {
6162 #ifndef WAIR
6263 //cc
8485 mAPInBuffer[i] = NULL;
8586 }
8687 #endif // endwhere
88
89 mInBufCopy.resize(mNumInChans);
90 for (int i=0; i<mNumInChans; i++) {
91 mInBufCopy[i] = new sample_t[MAX_AUDIO_BUFFER_SIZE]; // required for processing audio input
92 }
8793 }
8894
8995
9298 {
9399 delete[] mInputPacket;
94100 delete[] mOutputPacket;
95 #ifndef WAIR // WAIR
101 #ifndef WAIR // NOT WAIR:
96102 for (int i = 0; i < mNumInChans; i++) {
97103 delete[] mInProcessBuffer[i];
98104 }
114120 delete[] mAPInBuffer[i];
115121 }
116122 #endif // endwhere
123
124 for (int i = 0; i < mProcessPluginsFromNetwork.size(); i++) {
125 delete mProcessPluginsFromNetwork[i];
126 }
127 for (int i = 0; i < mProcessPluginsToNetwork.size(); i++) {
128 delete mProcessPluginsToNetwork[i];
129 }
130 for (int i=0; i<mNumInChans; i++) {
131 delete mInBufCopy[i];
132 }
117133 }
118134
119135
152168
153169 int nframes = getBufferSizeInSamples();
154170
155 #ifndef WAIR // WAIR
171 #ifndef WAIR // NOT WAIR:
156172 for (int i = 0; i < mNumInChans; i++) {
157173 mInProcessBuffer[i] = new sample_t[nframes];
158174 // set memory to 0
207223 // ----------------------------------
208224
209225 #ifdef WAIR // WAIR
210 // qDebug() << "--" << mProcessPlugins.size();
211 bool client = (mProcessPlugins.size() == 2);
226 // qDebug() << "--" << mProcessPluginsFromNetwork.size();
227 bool client = (mProcessPluginsFromNetwork.size() == 2);
212228 #define COMBDSP 1 // client
213229 #define APDSP 0 // client
214230 #define DCBDSP 0 // server
217233 }
218234 #endif // endwhere
219235
236 // ==== RECEIVE AUDIO CHANNELS FROM NETWORK ====
220237 computeProcessFromNetwork(out_buffer, n_frames);
238 // =============================================
239
240 // out_buffer is from the network and goes "out" to local audio
241 // hardware via JACK:
242
243 // mAudioTesterP will be nullptr for hub server's JackTripWorker instances
244 if (mAudioTesterP && mAudioTesterP->getEnabled()) {
245 mAudioTesterP->lookForReturnPulse(out_buffer, n_frames);
246 }
247
221248 #ifdef WAIR // WAIR
222249 // nib16 result now in mNetInBuffer
223250 #endif // endwhere
228255 /// \todo Implement for more than one process plugin, now it just works propertely with one.
229256 /// do it chaining outputs to inputs in the buffers. May need a tempo buffer
230257
231 #ifndef WAIR // WAIR
232 for (int i = 0; i < mNumInChans; i++) {
233 std::memset(mInProcessBuffer[i], 0, sizeof(sample_t) * n_frames);
234 std::memcpy(mInProcessBuffer[i], out_buffer[i], sizeof(sample_t) * n_frames);
235 }
236 for (int i = 0; i < mNumOutChans; i++) {
237 std::memset(mOutProcessBuffer[i], 0, sizeof(sample_t) * n_frames);
238 }
239
240 for (int i = 0; i < mProcessPlugins.size(); i++) {
241 mProcessPlugins[i]->compute(n_frames, mInProcessBuffer.data(), mOutProcessBuffer.data());
242 }
243 #else // WAIR
258 #ifndef WAIR // NOT WAIR:
259 for (int i = 0; i < mProcessPluginsFromNetwork.size(); i++) {
260 ProcessPlugin* p = mProcessPluginsFromNetwork[i];
261 if (p->getInited()) {
262 p->compute(n_frames, out_buffer.data(), out_buffer.data());
263 }
264 }
265 #else // WAIR:
244266 for (int i = 0; i < ((mNumNetRevChans)?mNumNetRevChans:mNumOutChans); i++) {
245267 std::memset(mOutProcessBuffer[i], 0, sizeof(sample_t) * n_frames);
246268 }
256278 }
257279 // nib16 to cib16
258280
259 if (mNumNetRevChans && client) mProcessPlugins[COMBDSP]->compute(n_frames,
260 mInProcessBuffer.data(), mOutProcessBuffer.data());
281 if (mNumNetRevChans && client) {
282 mProcessPluginsFromNetwork[COMBDSP]->compute(n_frames, mInProcessBuffer.data(), mOutProcessBuffer.data());
283 }
261284 // compute cob16
262285 #endif // endwhere
263286
264 // 3) Finally, send packets to peer
265 // --------------------------------
266 computeProcessToNetwork(in_buffer, n_frames);
287 // 3) Send packets to network:
288 // mAudioTesterP will be nullptr for hub server's JackTripWorker instances:
289 bool audioTesting = (mAudioTesterP && mAudioTesterP->getEnabled());
290 int nop = mProcessPluginsToNetwork.size(); // number of OUTGOING processing modules
291 if (nop>0 || audioTesting) { // cannot modify in_buffer, so make a copy
292 // in_buffer is "in" from local audio hardware via JACK
293 if (mInBufCopy.size() < mNumInChans) { // created in constructor above
294 std::cerr << "*** AudioInterface.cpp: Number of Input Channels changed - insufficient room reserved\n";
295 exit(1);
296 }
297 if (MAX_AUDIO_BUFFER_SIZE < n_frames) { // allocated in constructor above
298 std::cerr << "*** AudioInterface.cpp: n_frames = " << n_frames
299 << " larger than expected max = " << MAX_AUDIO_BUFFER_SIZE << "\n";
300 exit(1);
301 }
302 for (int i=0; i<mNumInChans; i++) {
303 std::memcpy(mInBufCopy[i], in_buffer[i], sizeof(sample_t) * n_frames);
304 }
305 for (int i = 0; i < nop; i++) {
306 // process all outgoing channels with ProcessPlugins:
307 ProcessPlugin* p = mProcessPluginsToNetwork[i];
308 if (p->getInited()) {
309 p->compute(n_frames, mInBufCopy.data(), mInBufCopy.data());
310 }
311 }
312 if (audioTesting) {
313 mAudioTesterP->writeImpulse(mInBufCopy, n_frames); // writes last channel of mInBufCopy with test impulse
314 }
315 computeProcessToNetwork(mInBufCopy, n_frames);
316 } else { // copy saved if no plugins and no audio testing in progress:
317 computeProcessToNetwork(in_buffer, n_frames); // send processed input audio to network - OUTGOING
318 }
267319
268320 #ifdef WAIR // WAIR
269321 // aib2 + cob16 to nob16
301353 for (int i = 0; i < mNumOutChans; i++) {
302354 std::memset(out_buffer[i], 0, sizeof(sample_t) * n_frames);
303355 }
304 mProcessPlugins[APDSP]->compute(n_frames, mAPInBuffer.data(), out_buffer.data());
356 mProcessPluginsFromNetwork[APDSP]->compute(n_frames, mAPInBuffer.data(), out_buffer.data());
305357 // compute ap2 into aob2
306358
307359 //#define ADD_DIRECT
318370 }
319371 #endif // endwhere
320372
321
322 ///************PROTORYPE FOR CELT**************************
373 ///************PROTOTYPE FOR CELT**************************
323374 ///********************************************************
324375 /*
325376 CELTMode* mode;
336387
337388 }
338389
390 //*******************************************************************************
391 void AudioInterface::broadcastCallback(QVarLengthArray<sample_t*>& mon_buffer,
392 unsigned int n_frames)
393 {
394 /// \todo cast *mInBuffer[i] to the bit resolution
395 // Output Process (from NETWORK to JACK)
396 // ----------------------------------------------------------------
397 // Read Audio buffer from RingBuffer (read from incoming packets)
398 mJackTrip->receiveBroadcastPacket(mOutputPacket);
399 // Extract separate channels to send to Jack
400 for (int i = 0; i < mNumOutChans; i++) {
401 sample_t* tmp_sample = mon_buffer[i]; //sample buffer for channel i
402 for (unsigned int j = 0; j < n_frames; j++) {
403 // Change the bit resolution on each sample
404 fromBitToSampleConversion(
405 // use interleaved channel layout
406 //&mOutputPacket[(i*mSizeInBytesPerChannel) + (j*mBitResolutionMode)],
407 &mOutputPacket[(j*mBitResolutionMode*mNumOutChans) + (i*mBitResolutionMode)],
408 &tmp_sample[j], mBitResolutionMode );
409 }
410 }
411 }
339412
340413 //*******************************************************************************
341414 // Before sending and reading to Jack, we have to round to the sample resolution
358431 for (unsigned int j = 0; j < n_frames; j++) {
359432 // Change the bit resolution on each sample
360433 fromBitToSampleConversion(
361 &mOutputPacket[(i*mSizeInBytesPerChannel) + (j*mBitResolutionMode)],
434 // use interleaved channel layout
435 //&mOutputPacket[(i*mSizeInBytesPerChannel) + (j*mBitResolutionMode)],
436 &mOutputPacket[(j*mBitResolutionMode*mNumOutChans) + (i*mBitResolutionMode)],
362437 &tmp_sample[j], mBitResolutionMode );
363438 }
364439 }
370445 //--------
371446 // This should be faster for 32 bits
372447 //std::memcpy(mOutBuffer[i], &mOutputPacket[i*mSizeInBytesPerChannel],
373 // mSizeInBytesPerChannel);
448 // mSizeInBytesPerChannel);
374449 //--------
375450 sample_t* tmp_sample = out_buffer[i]; //sample buffer for channel i
376451 for (unsigned int j = 0; j < n_frames; j++) {
377452 // Change the bit resolution on each sample
378453 fromBitToSampleConversion(
379 &mOutputPacket[(i*mSizeInBytesPerChannel) + (j*mBitResolutionMode)],
454 // use interleaved channel layout
455 //&mOutputPacket[(i*mSizeInBytesPerChannel) + (j*mBitResolutionMode)],
456 &mOutputPacket[(j*mBitResolutionMode*mNumOutChans) + (i*mBitResolutionMode)],
380457 &tmp_sample[j], mBitResolutionMode );
381458 }
382459 }
405482 tmp_result = INGAIN*tmp_sample[j] + COMBGAIN*tmp_process_sample[j];
406483 fromSampleToBitConversion(
407484 &tmp_result,
408 &mInputPacket[(i*mSizeInBytesPerChannel) + (j*mBitResolutionMode)],
485 // use interleaved channel layout
486 //&mInputPacket[(i*mSizeInBytesPerChannel) + (j*mBitResolutionMode)],
487 &mInputPacket[(j*mBitResolutionMode*mNumOutChans) + (i*mBitResolutionMode)],
409488 mBitResolutionMode );
410489 }
411490 }
416495 //--------
417496 // This should be faster for 32 bits
418497 //std::memcpy(&mInputPacket[i*mSizeInBytesPerChannel], mInBuffer[i],
419 // mSizeInBytesPerChannel);
498 // mSizeInBytesPerChannel);
420499 //--------
421500 sample_t* tmp_sample = in_buffer[i]; //sample buffer for channel i
422501 sample_t* tmp_process_sample = mOutProcessBuffer[i]; //sample buffer from the output process
427506 tmp_result = tmp_sample[j] + tmp_process_sample[j];
428507 fromSampleToBitConversion(
429508 &tmp_result,
430 &mInputPacket[(i*mSizeInBytesPerChannel) + (j*mBitResolutionMode)],
509 // use interleaved channel layout
510 //&mInputPacket[(i*mSizeInBytesPerChannel) + (j*mBitResolutionMode)],
511 &mInputPacket[(j*mBitResolutionMode*mNumOutChans) + (i*mBitResolutionMode)],
431512 mBitResolutionMode );
432513 }
433514 }
434515 // Send Audio buffer to Network
435516 mJackTrip->sendNetworkPacket( mInputPacket );
436 }
437
517 } // /computeProcessToNetwork
438518
439519 //*******************************************************************************
440520 // This function quantize from 32 bit to a lower bit resolution
447527 int8_t tmp_8;
448528 uint8_t tmp_u8; // unsigned to quantize the remainder in 24bits
449529 int16_t tmp_16;
450 sample_t tmp_sample;
530 double tmp_sample;
451531 sample_t tmp_sample16;
452532 sample_t tmp_sample8;
453533 switch (targetBitResolution)
454534 {
455535 case BIT8 :
456536 // 8bit integer between -128 to 127
457 tmp_sample = floor( (*input) * 128.0 ); // 2^7 = 128.0
537 tmp_sample = std::max(-127.0, std::min(127.0, std::round( (*input) * 127.0 ))); // 2^7 = 128
458538 tmp_8 = static_cast<int8_t>(tmp_sample);
459539 std::memcpy(output, &tmp_8, 1); // 8bits = 1 bytes
460540 break;
461541 case BIT16 :
462542 // 16bit integer between -32768 to 32767
463 tmp_sample = floor( (*input) * 32768.0 ); // 2^15 = 32768.0
543 // original scaling: tmp_sample = floor( (*input) * 32768.0 ); // 2^15 = 32768.0
544 tmp_sample = std::max(-32767.0, std::min(32767.0, std::round( (*input) * 32767.0 ))); // 2^15 = 32768
464545 tmp_16 = static_cast<int16_t>(tmp_sample);
465 std::memcpy(output, &tmp_16, 2); // 16bits = 2 bytes
546 std::memcpy(output, &tmp_16, 2); // 2 bytes output in Little Endian order (LSB -> smallest address)
466547 break;
467548 case BIT24 :
468549 // To convert to 24 bits, we first quantize the number to 16bit
482563 std::memcpy(output+2, &tmp_u8, 1); // 8bits = 1 bytes
483564 break;
484565 case BIT32 :
485 std::memcpy(output, input, 4); // 32bit = 4 bytes
566 tmp_sample = *input;
567 // not necessary yet:
568 // tmp_sample = std::max(-1.0, std::min(1.0, tmp_sample));
569 std::memcpy(output, &tmp_sample, 4); // 32bit = 4 bytes
486570 break;
487571 }
488572 }
531615
532616
533617 //*******************************************************************************
534 void AudioInterface::appendProcessPlugin(ProcessPlugin* plugin)
535 {
536 /// \todo check that channels in ProcessPlugins are less or same that jack channels
537 if ( plugin->getNumInputs() ) {}
538 mProcessPlugins.append(plugin);
539 }
540
618 void AudioInterface::appendProcessPluginToNetwork(ProcessPlugin* plugin)
619 {
620 if (not plugin) { return; }
621 int nTestChans = (mAudioTesterP && mAudioTesterP->getEnabled()) ? 1 : 0;
622 int nPluginChans = mNumInChans - nTestChans;
623 assert(nTestChans==0 || (mAudioTesterP->getSendChannel() == mNumInChans-1));
624 if (plugin->getNumInputs() < nPluginChans) {
625 std::cerr << "*** AudioInterface.cpp: appendProcessPluginToNetwork: ProcessPlugin "
626 << typeid(plugin).name() << " REJECTED due to having "
627 << plugin->getNumInputs() << " inputs, while the audio to JACK needs "
628 << nPluginChans << " inputs\n";
629 return;
630 }
631 mProcessPluginsToNetwork.append(plugin);
632 }
633
634 void AudioInterface::appendProcessPluginFromNetwork(ProcessPlugin* plugin)
635 {
636 if (not plugin) { return; }
637 int nTestChans = (mAudioTesterP && mAudioTesterP->getEnabled()) ? 1 : 0;
638 int nPluginChans = mNumOutChans - nTestChans;
639 assert(nTestChans==0 || (mAudioTesterP->getSendChannel() == mNumOutChans-1));
640 if (plugin->getNumOutputs() > nPluginChans) {
641 std::cerr << "*** AudioInterface.cpp: appendProcessPluginFromNetwork: ProcessPlugin "
642 << typeid(plugin).name() << " REJECTED due to having "
643 << plugin->getNumOutputs() << " inputs, while the JACK audio output requires "
644 << nPluginChans << " outputs\n";
645 return;
646 }
647 mProcessPluginsFromNetwork.append(plugin);
648 }
649
650 void AudioInterface::initPlugins()
651 {
652 int nPlugins = mProcessPluginsFromNetwork.size() + mProcessPluginsToNetwork.size();
653 if (nPlugins > 0) {
654 std::cout << "Initializing Faust plugins (have " << nPlugins
655 << ") at sampling rate " << mSampleRate << "\n";
656 for (ProcessPlugin* plugin : mProcessPluginsFromNetwork) {
657 plugin->init(mSampleRate);
658 }
659 for (ProcessPlugin* plugin : mProcessPluginsToNetwork) {
660 plugin->init(mSampleRate);
661 }
662 }
663 }
541664
542665 //*******************************************************************************
543666 AudioInterface::samplingRateT AudioInterface::getSampleRateType() const
544667 {
545 uint32_t rate = getSampleRate();
546
547 if ( rate == 22050 ) {
668 int32_t rate = getSampleRate();
669
670 if ( 100 > qAbs(rate - 22050) ) {
548671 return AudioInterface::SR22; }
549 else if ( rate == 32000 ) {
672 else if ( 100 > qAbs(rate - 32000) ) {
550673 return AudioInterface::SR32; }
551 else if ( rate == 44100 ) {
674 else if ( 100 > qAbs(rate - 44100) ) {
552675 return AudioInterface::SR44; }
553 else if ( rate == 48000 ) {
676 else if ( 100 > qAbs(rate - 48000) ) {
554677 return AudioInterface::SR48; }
555 else if ( rate == 88200 ) {
678 else if ( 100 > qAbs(rate - 88200) ) {
556679 return AudioInterface::SR88; }
557 else if ( rate == 96000 ) {
680 else if ( 100 > qAbs(rate - 96000) ) {
558681 return AudioInterface::SR96; }
559 else if ( rate == 19200 ) {
682 else if ( 100 > qAbs(rate - 19200) ) {
560683 return AudioInterface::SR192; }
561684
562685 return AudioInterface::UNDEF;
3939
4040 #include "ProcessPlugin.h"
4141 #include "jacktrip_types.h"
42 #include "AudioTester.h"
4243
4344 #include <QVarLengthArray>
4445 #include <QVector>
114115 * \param in_buffer Array of output audio samplers for each channel. The user
115116 * is reponsible to check that each channel has n_frames samplers
116117 */
118 virtual void broadcastCallback(QVarLengthArray<sample_t*>& mon_buffer,
119 unsigned int n_frames);
117120 virtual void callback(QVarLengthArray<sample_t*>& in_buffer,
118121 QVarLengthArray<sample_t*>& out_buffer,
119122 unsigned int n_frames);
120 /** \brief Append a ProcessPlugin. The order of processing is determined by
121 * the order by which appending is done.
122 * \param plugin a ProcesPlugin smart pointer. Create the object instance
123 /** \brief appendProcessPluginToNetwork(): Append a ProcessPlugin for outgoing audio.
124 * The processing order equals order they were appended.
125 * This processing is in the JackTrip client before sending to the network.
126 * \param plugin a ProcessPlugin smart pointer. Create the object instance
123127 * using something like:\n
124128 * <tt>std::tr1::shared_ptr<ProcessPluginName> loopback(new ProcessPluginName);</tt>
125129 */
126 virtual void appendProcessPlugin(ProcessPlugin* plugin);
130 virtual void appendProcessPluginToNetwork(ProcessPlugin* plugin);
131 /** \brief appendProcessPluginFromNetwork():
132 * Same as appendProcessPluginToNetwork() except that these plugins operate
133 * on the audio received from the network (typically from a JackTrip server).
134 * The complete processing chain then looks like this:
135 * audio -> JACK -> JackTrip client -> processPlugin to network
136 * -> remote JackTrip server
137 * -> JackTrip client -> processPlugin from network -> JACK -> audio
138 */
139 virtual void appendProcessPluginFromNetwork(ProcessPlugin* plugin);
140 /** \brief initPlugins():
141 * Initialize all ProcessPlugin modules.
142 * The audio sampling rate (mSampleRate) must be set at this time.
143 */
144 void initPlugins();
127145 virtual void connectDefaultPorts() = 0;
128146 /** \brief Convert a 32bit number (sample_t) into one of the bit resolution
129147 * supported (audioBitResolutionT).
159177 { mBufferSizeInSamples = buf_size; }
160178 /// \brief Set Client Name to something different that the default (JackTrip)
161179 virtual void setClientName(QString ClientName) = 0;
180 virtual void setLoopBack(bool b) { mLoopBack = b; }
181 virtual void enableBroadcastOutput() {}
182 virtual void setAudioTesterP(AudioTester* atp) { mAudioTesterP = atp; }
162183 //------------------------------------------------------------------
163184
164185 //--------------GETTERS---------------------------------------------
208229 QVarLengthArray<sample_t*> mNetInBuffer; ///< Vector of Input buffers/channel read from net
209230 QVarLengthArray<sample_t*> mAPInBuffer; ///< Vector of Input buffers/channel for AllPass input
210231 #endif // endwhere
232 QVarLengthArray<sample_t*> mInBufCopy; ///< needed in callback() to modify JACK audio input
211233 int mAudioBitResolution; ///< Bit resolution in audio samples
212234 AudioInterface::audioBitResolutionT mBitResolutionMode; ///< Bit resolution (audioBitResolutionT) mode
213235 uint32_t mSampleRate; ///< Sampling Rate
214236 uint32_t mDeviceID; ///< RTAudio DeviceID
215237 uint32_t mBufferSizeInSamples; ///< Buffer size in samples
216238 size_t mSizeInBytesPerChannel; ///< Size in bytes per audio channel
217 QVector<ProcessPlugin*> mProcessPlugins; ///< Vector of ProcesPlugin<EM>s</EM>
239 QVector<ProcessPlugin*> mProcessPluginsFromNetwork; ///< Vector of ProcessPlugin<EM>s</EM>
240 QVector<ProcessPlugin*> mProcessPluginsToNetwork; ///< Vector of ProcessPlugin<EM>s</EM>
218241 QVarLengthArray<sample_t*> mInProcessBuffer;///< Vector of Input buffers/channel for ProcessPlugin
219242 QVarLengthArray<sample_t*> mOutProcessBuffer;///< Vector of Output buffers/channel for ProcessPlugin
220243 int8_t* mInputPacket; ///< Packet containing all the channels to read from the RingBuffer
221244 int8_t* mOutputPacket; ///< Packet containing all the channels to send to the RingBuffer
245 bool mLoopBack;
246 AudioTester* mAudioTesterP { nullptr };
247 protected:
248 bool mProcessingAudio; ///< Set when processing an audio callback buffer pair
249 const uint32_t MAX_AUDIO_BUFFER_SIZE = 8192;
222250 };
223251
224252 #endif // __AUDIOINTERFACE_H__
0 //*****************************************************************
1 /*
2 JackTrip: A System for High-Quality Audio Network Performance
3 over the Internet
4
5 Copyright (c) 2020 Julius Smith, Juan-Pablo Caceres, Chris Chafe.
6 SoundWIRE group at CCRMA, Stanford University.
7
8 Permission is hereby granted, free of charge, to any person
9 obtaining a copy of this software and associated documentation
10 files (the "Software"), to deal in the Software without
11 restriction, including without limitation the rights to use,
12 copy, modify, merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom the
14 Software is furnished to do so, subject to the following
15 conditions:
16
17 The above copyright notice and this permission notice shall be
18 included in all copies or substantial portions of the Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 OTHER DEALINGS IN THE SOFTWARE.
28 */
29 //*****************************************************************
30
31 /**
32 * \file AudioTester.cpp
33 * \author Julius Smith
34 * \license MIT
35 * \date Aug-Oct 2020
36 */
37
38 #include "AudioTester.h"
39 #include <assert.h>
40
41 // Called 1st in Audiointerface.cpp
42 void AudioTester::lookForReturnPulse(QVarLengthArray<sample_t*>& out_buffer,
43 unsigned int n_frames) {
44 if (not enabled) {
45 std::cerr << "*** AudioTester.h: lookForReturnPulse: NOT ENABLED\n";
46 return;
47 }
48 if (impulsePending) { // look for return impulse in channel sendChannel:
49 assert(sendChannel<out_buffer.size());
50 for (uint n=0; n<n_frames; n++) {
51 float amp = out_buffer[sendChannel][n];
52 if (amp > 0.5 * ampCellHeight) { // got something
53 int cellNum = getImpulseCellNum(out_buffer[sendChannel][n]);
54 if (cellNum != pendingCell) { // not our impulse!
55 std::cerr <<
56 "*** AudioTester.h: computeProcessFromNetwork: Received pulse amplitude "
57 << amp << " (cell " << cellNum << ") while looking for cell "
58 << pendingCell << "\n";
59
60 if (cellNum > pendingCell) { // we missed it
61 std::cerr << " - ABORTING CURRENT PULSE\n";
62 impulsePending = false;
63 } else { // somehow we got the previous pulse again - repeated packet or underrun-caused repetition (old buffer)
64 std::cerr << " - IGNORING FOUND PULSE WAITING FURTHER\n";
65 }
66 } else { // found our impulse:
67 int64_t elapsedSamples = -1;
68 if (n >= n_frames-1) {
69 // Impulse timestamp didn't make it so we skip this one.
70 } else {
71 float sampleCountWhenImpulseSent = - 32768.0f * out_buffer[sendChannel][n+1];
72 elapsedSamples = sampleCountSinceImpulse + n - int64_t(sampleCountWhenImpulseSent);
73 sampleCountSinceImpulse = 1; // reset sample counter between impulses
74 roundTripCount += 1.0;
75 }
76 // int64_t curTimeUS = timeMicroSec(); // time since launch in us
77 // int64_t impulseDelayUS = curTimeUS - ImpulseTimeUS;
78 // float impulseDelaySec = float(impulseDelayUS) * 1.0e-6;
79 // float impulseDelayBuffers = impulseDelaySec / (float(n_frames)/float(sampleRate));
80 // int64_t impulseDelayMS = (int64_t)round(double(impulseDelayUS)/1000.0);
81 if (elapsedSamples > 0) { // found impulse and reset, time to print buffer results:
82 double elapsedSamplesMS = 1000.0 * double(elapsedSamples)/double(sampleRate); // ms
83 extendLatencyHistogram(elapsedSamplesMS);
84 if (roundTripCount > 1.0) {
85 double prevSum = roundTripMean * (roundTripCount-1.0); // undo previous normalization
86 roundTripMean = (prevSum + elapsedSamplesMS) / roundTripCount; // add latest and renormalize
87 double prevSumSq = roundTripMeanSquare * (roundTripCount-1.0); // undo previous normalization
88 roundTripMeanSquare = (prevSumSq + elapsedSamplesMS*elapsedSamplesMS) / roundTripCount;
89 } else { // just getting started:
90 roundTripMean = elapsedSamplesMS;
91 roundTripMeanSquare = elapsedSamplesMS * elapsedSamplesMS;
92 }
93 if (roundTripCount == 1.0) {
94 printf("JackTrip Test Mode (option -x printIntervalInSeconds=%0.3f)\n",printIntervalSec);
95 printf("\tA test impulse-train is output on channel %d (from 0) with repeatedly ramping amplitude\n",
96 sendChannel);
97 if (printIntervalSec == 0.0) {
98 printf("\tPrinting each audio buffer round-trip latency in ms followed by cumulative (mean and [standard deviation])");
99 } else {
100 printf("\tPrinting cumulative mean and [standard deviation] of audio round-trip latency in ms");
101 printf(" every %0.3f seconds", printIntervalSec);
102 }
103 printf(" after skipping first %d buffers:\n", bufferSkipStart);
104 // not printing this presently: printf("( * means buffer skipped due missing timestamp or lost impulse)\n");
105 lastPrintTimeUS = timeMicroSec();
106 }
107 //printf("%d (%d) ", elapsedSamplesMS, impulseDelayMS); // measured time is "buffer time" not sample time
108 int64_t curTimeUS = timeMicroSec(); // time since launch in us
109 double timeSinceLastPrintUS = double(curTimeUS - lastPrintTimeUS);
110 double stdDev = sqrt(std::max(0.0, (roundTripMeanSquare - (roundTripMean*roundTripMean))));
111 if (timeSinceLastPrintUS >= printIntervalSec * 1.0e6) {
112 if (printIntervalSec == 0.0) { printf("%0.1f (", elapsedSamplesMS); }
113 printf("%0.1f [%0.1f]", roundTripMean, stdDev);
114 if (printIntervalSec == 0.0) { printf(") "); } else { printf(" "); }
115 lastPrintTimeUS = curTimeUS;
116 if (printIntervalSec >= 1.0) { // print histogram
117 std::cout << "\n" << getLatencyHistogramString() << "\n";
118 }
119 }
120 std::cout << std::flush;
121 } else {
122 // not printing this presently: printf("* "); // we got the impulse but lost its timestamp in samples
123 }
124 impulsePending = false;
125 } // found our impulse
126 // remain pending until timeout, hoping to find our return pulse
127 } // got something
128 } // loop over samples
129 sampleCountSinceImpulse += n_frames; // gets reset to 1 when impulse is found, counts freely until then
130 } // ImpulsePending
131 }
132
133 // Called 2nd in Audiointerface.cpp
134 void AudioTester::writeImpulse(QVarLengthArray<sample_t*>& mInBufCopy,
135 unsigned int n_frames) {
136 if (not enabled) {
137 std::cerr << "*** AudioTester.h: writeImpulse: NOT ENABLED\n";
138 return;
139 }
140 if (bufferSkip <= 0) { // send test signals (-x option)
141 bool sendImpulse;
142 if (impulsePending) {
143 sendImpulse = false; // unless:
144 const uint64_t timeOut = 500e3; // time out after waiting 500 ms
145 if (timeMicroSec() > (impulseTimeUS + timeOut)) {
146 sendImpulse = true;
147 std::cout << "\n*** Audio Latency Test (-x): TIMED OUT waiting for return impulse *** sending a new one\n";
148 }
149 } else { // time for the next repeating impulse:
150 sendImpulse = true;
151 }
152 if (sendImpulse) {
153 assert(sendChannel < mInBufCopy.size());
154 mInBufCopy[sendChannel][0] = getImpulseAmp();
155 for (uint n=1; n<n_frames; n++) {
156 mInBufCopy[sendChannel][n] = 0;
157 }
158 impulsePending = true;
159 impulseTimeUS = timeMicroSec();
160 impulseTimeSamples = sampleCountSinceImpulse; // timer in samples for current impulse loopback test
161 // Also send impulse time:
162 if (n_frames>1) { // always true?
163 mInBufCopy[sendChannel][1] = -float(impulseTimeSamples)/32768.0f; // survives if there is no digital processing at the server
164 } else {
165 std::cerr << "\n*** AudioTester.h: Timestamp cannot fit into a lenth " << n_frames << " buffer ***\n";
166 }
167 } else {
168 mInBufCopy[sendChannel][0] = 0.0f; // send zeros until a new impulse is needed
169 if (n_frames>1) {
170 mInBufCopy[sendChannel][1] = 0.0f;
171 }
172 }
173 } else {
174 bufferSkip--;
175 }
176 }
177
178 void AudioTester::printHelp(char* command, [[maybe_unused]] char helpCase) {
179 std::cout << "HELP for \"" << command << " printIntervalSec\" // (end-of-line comments start with `//'):\n";
180 std::cout << "\n";
181 std::cout << "Print roundtrip audio delay statistics for the highest-numbered audio channel every printIntervalSec seconds,\n";
182 std::cout << "including an ASCII latency histogram if printIntervalSec is 1.0 or more.\n";
183 std::cout << "\n";
184 std::cout << "A test impulse is sent to the server in the last audio channel,\n";
185 std::cout << " the number of samples until it returns is measured, and this repeats.\n";
186 std::cout << "The jacktrip server must provide audio loopback (e.g., -p4).\n";
187 std::cout << "The cumulative mean and standard-deviation (\"statistics\") are computed for the measured loopback times,\n";
188 std::cout << " and printed every printIntervalSec seconds.\n";
189 std::cout << "If printIntervalSec is zero, the roundtrip-time and statistics in milliseconds are printed for each individual impulse.\n";
190 std::cout << "If printIntervalSec is positive, statistics are printed after each print interval, with no individual measurements.\n";
191 std::cout << "If printIntervalSec is 1.0 or larger, a cumulative histogram of all impulse roundtrip-times is printed as well.\n";
192 std::cout << "The first 100 audio buffers are skipped in order to measure only steady-state network-audio-delay performance.\n";
193 std::cout << "Lower audio channels are not affected, enabling latency measurement and display during normal operation.\n";
194 }
0 //*****************************************************************
1 /*
2 JackTrip: A System for High-Quality Audio Network Performance
3 over the Internet
4
5 Copyright (c) 2020 Julius Smith, Juan-Pablo Caceres, Chris Chafe.
6 SoundWIRE group at CCRMA, Stanford University.
7
8 Permission is hereby granted, free of charge, to any person
9 obtaining a copy of this software and associated documentation
10 files (the "Software"), to deal in the Software without
11 restriction, including without limitation the rights to use,
12 copy, modify, merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom the
14 Software is furnished to do so, subject to the following
15 conditions:
16
17 The above copyright notice and this permission notice shall be
18 included in all copies or substantial portions of the Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 OTHER DEALINGS IN THE SOFTWARE.
28 */
29 //*****************************************************************
30
31 /**
32 * \file AudioTester.h
33 * \author Julius Smith
34 * \license MIT
35 * \date Aug-Oct 2020
36 */
37
38 #pragma once
39
40 #include "jacktrip_types.h" // sample_t
41
42 #include <iostream>
43 //#include <ctime>
44 #include <chrono>
45 #include <cstdint>
46 #include <cmath>
47 #include <string>
48 #include <map>
49
50 #include <QVarLengthArray>
51
52 class AudioTester
53 {
54 bool enabled { false };
55 float printIntervalSec { 1.0f };
56 int sendChannel { 0 };
57
58 bool impulsePending { false };
59 int64_t lastPrintTimeUS { 0 };
60 int64_t impulseTimeUS { 0 };
61 int64_t impulseTimeSamples { 0 };
62 uint64_t sampleCountSinceImpulse { 1 }; // 0 not used
63 double roundTripMean { 0.0 };
64 double roundTripMeanSquare { 0.0 };
65 double roundTripCount { 0.0 };
66 const int bufferSkipStart { 100 };
67 int bufferSkip { bufferSkipStart };
68 const float impulseAmplitude { 0.1f };
69 const int numAmpCells { 10 };
70 const float ampCellHeight { impulseAmplitude/numAmpCells };
71
72 const double latencyHistogramCellWidth { 5.0 }; // latency range in ms covered one cell
73 const double latencyHistogramCellMin { 0.0 };
74 const double latencyHistogramCellMax { 19.0 }; // in cells, so 5x this is max latency in ms
75 const int latencyHistogramPrintCountMax { 72 }; // normalize when asterisks exceed this number
76
77 int pendingCell { 0 }; // 0 is not used
78 float sampleRate { 48000.0f };
79
80 public:
81 AudioTester() {}
82 ~AudioTester() = default;
83
84 void lookForReturnPulse(QVarLengthArray<sample_t*>& out_buffer,
85 unsigned int n_frames);
86
87 void writeImpulse(QVarLengthArray<sample_t*>& mInBufCopy,
88 unsigned int n_frames);
89
90 bool getEnabled() { return enabled; }
91 void setEnabled(bool e) { enabled = e; }
92 void setPrintIntervalSec(float s) { printIntervalSec = s; }
93 void setSendChannel(int c) { sendChannel = c; }
94 int getSendChannel() { return sendChannel; }
95 int getPendingCell() { return pendingCell; }
96 void setPendingCell(int pc) { pendingCell = pc; }
97 void setSampleRate(float fs) { sampleRate = fs; }
98 int getBufferSkip() { return bufferSkip; } // used for debugging breakpoints
99 void printHelp(char* command, char helpCase);
100
101 private:
102
103 float getImpulseAmp() {
104 pendingCell += 1; // only called when no impulse is pending
105 if (pendingCell >= numAmpCells) {
106 pendingCell = 1; // wrap-around, not using zero
107 }
108 float imp = float(pendingCell) * (impulseAmplitude/float(numAmpCells));
109 return imp;
110 }
111
112 int getImpulseCellNum(float amp) {
113 float ch = ampCellHeight;
114 float cell = amp / ch;
115 int iCell = int(std::floor(0.5f + cell));
116 if (iCell > numAmpCells - 1) {
117 std::cerr << "*** AudioTester.h: getImpulseCellNum("<<amp<<"): Return pulse amplitude is beyond maximum expected\n";
118 iCell = numAmpCells-1;
119 } else if (iCell < 0) {
120 std::cerr << "*** AudioTester.h: getImpulseCellNum("<<amp<<"): Return pulse amplitude is below minimum expected\n";
121 iCell = 0;
122 }
123 return iCell;
124 }
125
126 uint64_t timeMicroSec() {
127 #if 1
128 using namespace std::chrono;
129 // return duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
130 return duration_cast<microseconds>(high_resolution_clock::now().time_since_epoch()).count();
131 #else
132 clock_t tics_since_launch = std::clock();
133 double timeUS = double(tics_since_launch)/double(CLOCKS_PER_SEC);
134 return (uint64_t)timeUS;
135 #endif
136 }
137
138 std::map<int, int> latencyHistogram;
139
140 std::map<int, int> getLatencyHistogram() {
141 return latencyHistogram;
142 }
143
144 void extendLatencyHistogram(double latencyMS) {
145 int latencyCell = static_cast<int>(floor(std::max(latencyHistogramCellMin,
146 std::min(latencyHistogramCellMax,
147 std::floor(latencyMS / latencyHistogramCellWidth)))));
148 latencyHistogram[latencyCell] += 1;
149 }
150
151 int latencyHistogramCountMax() {
152 int lhMax = 0;
153 int histStart = latencyHistogramFirstNonzeroCellIndex();
154 int histLast = latencyHistogramLastNonzeroCellIndex();
155 for (int i = histStart; i <= histLast; ++i) {
156 int lhi = latencyHistogram[i];
157 if (lhi > lhMax) {
158 lhMax = lhi;
159 }
160 }
161 return lhMax;
162 }
163
164 int latencyHistogramFirstNonzeroCellIndex() {
165 for (int i=latencyHistogramCellMin; i <= latencyHistogramCellMax; i++) {
166 if (latencyHistogram[i]>0) {
167 return i;
168 }
169 }
170 std::cerr << "*** AudioTester: LATENCY HISTOGRAM IS EMPTY!\n";
171 return -1;
172 }
173
174 int latencyHistogramLastNonzeroCellIndex() {
175 for (int i=latencyHistogramCellMax; i>=latencyHistogramCellMin; i--) {
176 if (latencyHistogram[i]>0) {
177 return i;
178 }
179 }
180 std::cerr << "*** AudioTester: LATENCY HISTOGRAM IS EMPTY!\n";
181 return -1;
182 }
183
184 std::string getLatencyHistogramString() {
185 int histStart = latencyHistogramFirstNonzeroCellIndex();
186 int histLast = latencyHistogramLastNonzeroCellIndex();
187 std::string marker = "*";
188 double histScale = 1.0;
189 int lhcm = latencyHistogramCountMax();
190 int lhpcm = latencyHistogramPrintCountMax;
191 bool normalizing = lhpcm < lhcm;
192 if (normalizing) {
193 marker = "#";
194 histScale = double(lhpcm) / double(lhcm);
195 }
196 std::string rows = "";
197 for (int i = histStart; i <= histLast; ++i) {
198 int hi = latencyHistogram[i];
199 int hin = int(std::round(histScale * double(hi)));
200 std::string istrm1 = std::to_string(int(latencyHistogramCellWidth * double(i)));
201 std::string istr = std::to_string(int(latencyHistogramCellWidth * double(i+1)));
202 // std::string histr = boost::format("%02d",hi);
203 std::string histr = std::to_string(hi);
204 while (histr.length()<3) {
205 histr = " " + histr;
206 }
207 std::string row = "["+istrm1+"-"+istr+"ms]="+histr+":";
208 for (int j=0; j<hin; j++) {
209 row += marker;
210 }
211 rows += row + "\n";
212 }
213 if (histLast == latencyHistogramCellMax) {
214 rows += " and above\n";
215 }
216 return rows;
217 }
218
219 };
0 //*****************************************************************
1 /*
2 JackTrip: A System for High-Quality Audio Network Performance
3 over the Internet
4
5 Copyright (c) 2020 Julius Smith, Juan-Pablo Caceres, Chris Chafe.
6 SoundWIRE group at CCRMA, Stanford University.
7
8 Permission is hereby granted, free of charge, to any person
9 obtaining a copy of this software and associated documentation
10 files (the "Software"), to deal in the Software without
11 restriction, including without limitation the rights to use,
12 copy, modify, merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom the
14 Software is furnished to do so, subject to the following
15 conditions:
16
17 The above copyright notice and this permission notice shall be
18 included in all copies or substantial portions of the Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 OTHER DEALINGS IN THE SOFTWARE.
28 */
29 //*****************************************************************
30
31 /**
32 * \file Compressor.cpp
33 * \author Julius Smith, based on LoopBack.h
34 * \date July 2008
35 */
36
37
38 #include "Compressor.h"
39
40 #include <iostream>
41
42 //*******************************************************************************
43 void Compressor::compute(int nframes, float** inputs, float** outputs)
44 {
45 if (not inited) {
46 std::cerr << "*** Compressor " << this << ": init never called! Doing it now.\n";
47 if (fSamplingFreq <= 0) {
48 fSamplingFreq = 48000;
49 std::cout << "Compressor " << this << ": *** HAD TO GUESS the sampling rate (chose 48000 Hz) ***\n";
50 }
51 init(fSamplingFreq);
52 }
53 for ( int i = 0; i < mNumChannels; i++ ) {
54 compressorP[i]->compute(nframes, &inputs[i], &outputs[i]);
55 }
56 }
0 //*****************************************************************
1 /*
2 JackTrip: A System for High-Quality Audio Network Performance
3 over the Internet
4
5 Copyright (c) 2020 Julius Smith, Juan-Pablo Caceres, Chris Chafe.
6 SoundWIRE group at CCRMA, Stanford University.
7
8 Permission is hereby granted, free of charge, to any person
9 obtaining a copy of this software and associated documentation
10 files (the "Software"), to deal in the Software without
11 restriction, including without limitation the rights to use,
12 copy, modify, merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom the
14 Software is furnished to do so, subject to the following
15 conditions:
16
17 The above copyright notice and this permission notice shall be
18 included in all copies or substantial portions of the Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 OTHER DEALINGS IN THE SOFTWARE.
28 */
29 //*****************************************************************
30
31 /**
32 * \file Compressor.h
33 * \author Julius Smith, starting from Limiter.h
34 * \date August 2020
35 */
36
37
38 /** \brief Applies compressor_mono from the faustlibraries distribution, compressors.lib
39 *
40 */
41 #ifndef __COMPRESSOR_H__
42 #define __COMPRESSOR_H__
43
44 #include "ProcessPlugin.h"
45 #include "compressordsp.h"
46 #include "CompressorPresets.h"
47 #include <vector>
48
49 /** \brief A Compressor reduces the output dynamic range when the
50 * signal level exceeds the threshold.
51 */
52 class Compressor : public ProcessPlugin
53 {
54 public:
55 /// \brief The class constructor sets the number of audio channels and default parameters.
56 Compressor(int numchans, // xtor
57 bool verboseIn = false,
58 float ratioIn = 2.0f,
59 float thresholdDBIn = -24.0f,
60 float attackMSIn = 15.0f,
61 float releaseMSIn = 40.0f,
62 float makeUpGainDBIn = 2.0f)
63 : mNumChannels(numchans)
64 , ratio(ratioIn)
65 , thresholdDB(thresholdDBIn)
66 , attackMS(attackMSIn)
67 , releaseMS(releaseMSIn)
68 , makeUpGainDB(makeUpGainDBIn)
69 {
70 setVerbose(verboseIn);
71 // presets.push_back(std::make_unique<CompressorPreset>(ratio,thresholdDB,attackMS,releaseMS,makeUpGainDB));
72 for ( int i = 0; i < mNumChannels; i++ ) {
73 compressorP.push_back(new compressordsp);
74 compressorUIP.push_back(new APIUI); // #included in compressordsp.h
75 compressorP[i]->buildUserInterface(compressorUIP[i]);
76 }
77 }
78
79 Compressor(int numchans, // xtor
80 bool verboseIn = false,
81 CompressorPreset preset = CompressorPresets::voice) :
82 Compressor(numchans,verboseIn,
83 preset.ratio,
84 preset.thresholdDB,
85 preset.attackMS,
86 preset.releaseMS,
87 preset.makeUpGainDB)
88 {}
89 /// \brief The class destructor
90 virtual ~Compressor() {
91 for ( int i = 0; i < mNumChannels; i++ ) {
92 delete compressorP[i];
93 delete compressorUIP[i];
94 }
95 compressorP.clear();
96 compressorUIP.clear();
97 }
98
99 // void setParamAllChannels(std::string& pName, float p) {
100 void setParamAllChannels(const char pName[], float p) {
101 for ( int i = 0; i < mNumChannels; i++ ) {
102 int ndx = compressorUIP[i]->getParamIndex(pName);
103 if (ndx >= 0) {
104 compressorUIP[i]->setParamValue(ndx, p);
105 if (verbose) {
106 std::cout << "Compressor.h: parameter " << pName << " set to " << p << " on audio channel " << i << "\n";
107 }
108 } else {
109 std::cerr << "*** Compressor.h: Could not find parameter named " << pName << "\n";
110 }
111 }
112 }
113
114 void init(int samplingRate) override {
115 ProcessPlugin::init(samplingRate);
116 if (samplingRate != fSamplingFreq) {
117 std::cerr << "Sampling rate not set by superclass!\n";
118 std::exit(1); }
119 fs = float(fSamplingFreq);
120 for ( int i = 0; i < mNumChannels; i++ ) {
121 compressorP[i]->init(fs); // compression filter parameters depend on sampling rate
122 }
123 setParamAllChannels("Ratio", ratio);
124 setParamAllChannels("Threshold", thresholdDB);
125 setParamAllChannels("Attack", attackMS);
126 setParamAllChannels("Release", releaseMS);
127 setParamAllChannels("MakeUpGain", makeUpGainDB);
128 inited = true;
129 }
130
131 int getNumInputs() override { return(mNumChannels); }
132 int getNumOutputs() override { return(mNumChannels); }
133 void compute(int nframes, float** inputs, float** outputs) override;
134
135 private:
136 float fs;
137 int mNumChannels;
138 std::vector<compressordsp*> compressorP;
139 std::vector<APIUI*> compressorUIP;
140 float ratio;
141 float thresholdDB;
142 float attackMS;
143 float releaseMS;
144 float makeUpGainDB;
145 };
146
147 #endif
0 #pragma once
1
2 #include <array>
3
4 struct CompressorPreset {
5 float ratio;
6 float thresholdDB;
7 float attackMS;
8 float releaseMS;
9 float makeUpGainDB;
10 CompressorPreset(float r, float t, float a, float rel, float m)
11 : ratio(r)
12 , thresholdDB(t)
13 , attackMS(a)
14 , releaseMS(rel)
15 , makeUpGainDB(m)
16 {}
17 ~CompressorPreset() = default;
18 };
19
20 namespace CompressorPresets
21 {
22 // name ratio thresh attack rel mugain
23 const CompressorPreset voice { 2.0f, -24.0f, 15.0f, 40.0f, 2.0f };
24 const CompressorPreset horns { 3.0f, -10.0f, 100.0f, 250.0f, 2.0f };
25 const CompressorPreset snare { 5.0f, -4.0f, 5.0f, 150.0f, 3.0f };
26 const uint numPresets { 3 };
27 const std::array<CompressorPreset,numPresets> standardPresets { voice, horns, snare };
28 enum CompressorPresetNames { CPN_VOICE, CPN_BRASS, CPN_SNARE, CPN_NUMPRESETS };
29 }
30
31 #if 0 // not yet using this
32 // Dynamic extension of CompressorPresets:
33 struct CompressorPresetList {
34 std::vector<CompressorPreset*> presets;
35 CompressorPresetList() { // define some standard presets
36 presets.push_back( new CompressorPreset(CompressorPresets::voice) );
37 presets.push_back( new CompressorPreset(CompressorPresets::horns) );
38 presets.push_back( new CompressorPreset(CompressorPresets::snare) );
39 }
40 ~CompressorPresetList() = default;
41 };
42 #endif
43
44 /* Settings from http://www.anythingpeaceful.org/sonar/settings/comp.html
45
46 Name Thresh(dB) Att(ms) Rel(ms) Ratio:1 Gain(dB) Comments
47 Vocal 1 -20 31 342 2.5 2 Compressor for Solo Vocal
48 Vocal 2 -8 26 331 2.5 1.5 Variation of Solo 1
49 Full Comp 1 -8 60 2500 2.5 0 For Overall Volume Level
50 Full Comp 2 -18 94 447 3.5 2.5 Variation of Total Comp 1: Harder ratio
51 Full Comp 3 -16 11 180 6 6 Nearly a limiter effect
52 Kick Comp -24 9 58 3 5.5 Compressor for Acoustic Bass Drum
53 Snare Comp -17 8 12 2.5 3.5 Compressor for Acoustic Snare Drum
54 Guitar -10 5 238 2.5 1.5 Compressor for Acoustic Guitar
55 Brass Sec -18 18 226 1.7 4 Brass Sounds for Strong Attacks
56 Bass 1 -12 15 470 2 4.5 Finger Picked Bass Guitar
57 Bass 2 -12 6 133 1.7 4 Slap Electric Bass
58 E Guitar -8 7 261 3.5 2.5 Electric Guitar Compressor
59 Piano 1 -9 17 238 2.5 1 Brightens Piano
60 Piano 2 -18 7 174 3.5 6 Variation of Piano 1
61 Kick -14 2 35 2 3.5 For sampled Bass Drum
62 Snare -18 8 354 4 8 For sampled Snare Drum
63 Strings 1 -11 33 749 2 1.5 For String instruments
64 Strings 2 -12 93 2500 1.5 1.5 For Violas and Cellos
65 Strings 3 -17 76 186 1.5 2.5 Cellos or DoubleBass
66 Syn Bass -10 9 250 3.5 3 Adjust level of Synth Bass
67 Syn Pad -13 58 238 2 2 Prevents diffusion of sound in synth pad
68 Limiting -1 0.1 325 20 0 Slow release limiter
69 Chorusing -9 39 225 1.7 2.5 For vocal Chorusing
70
71 From https://www.dummies.com/art-center/music/recording-music/dynamic-music-compression-settings-for-horns-piano-and-percussion/
72
73 Horns –8 100 300 2.5-3 2 Brasses not normally compressed [jos gain estimate based on above table]
74 Piano -10 100-105 115 1.5-2 2 Normally not compressed ["]
75 Kick -6 40-50 200-300 4-6 3 Looks more like a limiter to me [jos] ["]
76 Snare -4 5-10 125-175 4-6 3 Crucial for a tight, punchy sound
77 Bongos -6 10-25 100-300 3-6 3 "Hand Drums" - protect against excess "slap"
78 Perc. -10 10-20 50 3-6 3 Transient overdrive protection in mix
79
80 */
5151 DataProtocol::DataProtocol(JackTrip* jacktrip,
5252 const runModeT runmode,
5353 int /*bind_port*/, int /*peer_port*/) :
54 mStopped(false), mHasPacketsToReceive(false), mRunMode(runmode), mJackTrip(jacktrip)
54 mStopped(false), mHasPacketsToReceive(false), mRunMode(runmode), mJackTrip(jacktrip), mUseRtPriority(false)
5555 {}
5656
5757
179179 };
180180 virtual bool getStats(PktStat*) {return false;}
181181
182 virtual void setIssueSimulation(double /*loss*/, double /*jitter*/, double /*max_delay*/) {}
183 void setUseRtPriority(bool use) {mUseRtPriority = use;}
184
182185 signals:
183186
184187 void signalError(const char* error_message);
185188 void signalReceivedConnectionFromPeer();
186
189 void signalCeaseTransmission(const QString &reason = "");
187190
188191 protected:
189192
221224 protected:
222225 //PacketHeader* mHeader; ///< Packet Header
223226 JackTrip* mJackTrip; ///< JackTrip mediator class
227 bool mUseRtPriority;
224228
225229 };
226230
0 //*****************************************************************
1 /*
2 JackTrip: A System for High-Quality Audio Network Performance
3 over the Internet
4
5 Copyright (c) 2020 Julius Smith.
6 SoundWIRE group at CCRMA, Stanford University.
7
8 Permission is hereby granted, free of charge, to any person
9 obtaining a copy of this software and associated documentation
10 files (the "Software"), to deal in the Software without
11 restriction, including without limitation the rights to use,
12 copy, modify, merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom the
14 Software is furnished to do so, subject to the following
15 conditions:
16
17 The above copyright notice and this permission notice shall be
18 included in all copies or substantial portions of the Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 OTHER DEALINGS IN THE SOFTWARE.
28 */
29 //*****************************************************************
30
31 /**
32 * \file Effects.h
33 * \author Julius Smith
34 * \date Aug 2020
35 */
36
37 #pragma once
38
39 #include "ProcessPlugin.h"
40 #include "Limiter.h"
41 #include "Compressor.h"
42 #include "CompressorPresets.h"
43 #include "Reverb.h"
44 #include <assert.h>
45 #include <vector>
46
47 class Effects
48 {
49 int mNumIncomingChans;
50 int mNumOutgoingChans;
51 int gVerboseFlag = 0;
52 public:
53 enum LIMITER_MODE {
54 LIMITER_NONE,
55 LIMITER_INCOMING, // from network
56 LIMITER_OUTGOING, // to network
57 LIMITER_BOTH
58 };
59 private:
60 LIMITER_MODE mLimit; ///< audio limiter controls
61 unsigned int mNumClientsAssumed; ///< assumed number of clients (audio sources)
62 double limiterWarningAmplitude;
63
64 enum InOrOut { IO_NEITHER, IO_IN, IO_OUT } io;
65 bool inCompressor = false;
66 bool outCompressor = false;
67 bool inZitarev = false;
68 bool outZitarev = false;
69 bool inFreeverb = false;
70 bool outFreeverb = false;
71 bool incomingEffectsAllocated = false;
72 bool outgoingEffectsAllocated = false;
73 Compressor* inCompressorP = nullptr;
74 Compressor* outCompressorP = nullptr;
75 CompressorPreset inCompressorPreset = CompressorPresets::voice; // ./CompressorPresets.h
76 CompressorPreset outCompressorPreset = CompressorPresets::voice;
77 Reverb* inZitarevP = nullptr;
78 Reverb* outZitarevP = nullptr;
79 Reverb* inFreeverbP = nullptr;
80 Reverb* outFreeverbP = nullptr;
81 int parenLevel = 0;
82 char lastEffect = '\0';
83 float zitarevInLevel = 1.0f; // "Level" = wetness from 0 to 1
84 float freeverbInLevel = 1.0f;
85 float zitarevOutLevel = 1.0f;
86 float freeverbOutLevel = 1.0f;
87 float mReverbLevel; // for backward compatibility: 0-1 Freeverb, 1-2 Zitarev
88 Limiter* inLimiterP = nullptr;
89 Limiter* outLimiterP = nullptr;
90
91 public:
92
93 Effects(bool outGoingLimiterOn=true) :
94 mNumIncomingChans(2),
95 mNumOutgoingChans(2),
96 mLimit(outGoingLimiterOn ? LIMITER_OUTGOING : LIMITER_NONE),
97 mNumClientsAssumed(2),
98 limiterWarningAmplitude(0.0)
99 {}
100
101 ~Effects() {
102 /*
103 Plugin ownership presently passes to JackTrip,
104 and deletion occurs in AudioInterface.cpp. See
105 delete mProcessPluginsFromNetwork[i];
106 delete mProcessPluginsToNetwork[i];
107 there. If/when we ever do it here:
108 if (inCompressor) { delete inCompressorP; }
109 if (outCompressor) { delete outCompressorP; }
110 if (inZitarev) { delete inZitarevP; }
111 if (outZitarev) { delete outZitarevP; }
112 if (inFreeverb) { delete inFreeverbP; }
113 if (outFreeverb) { delete outFreeverbP; }
114 but if everyone can compile C++11,
115 let's switch to using std::unique_ptr.
116 */
117 }
118
119 unsigned int getNumClientsAssumed() { return mNumClientsAssumed; }
120
121 LIMITER_MODE getLimit() { return mLimit; }
122 void setNoLimiters() { mLimit = LIMITER_NONE; }
123
124 ProcessPlugin* getInCompressor() { return inCompressorP; }
125 ProcessPlugin* getOutCompressor() { return outCompressorP; }
126 ProcessPlugin* getInZitarev() { return inZitarevP; }
127 ProcessPlugin* getOutZitarev() { return outZitarevP; }
128 ProcessPlugin* getInFreeverb() { return inFreeverbP; }
129 ProcessPlugin* getOutFreeverb() { return outFreeverbP; }
130 ProcessPlugin* getInLimiter() { return inLimiterP; }
131 ProcessPlugin* getOutLimiter() { return outLimiterP; }
132
133 bool getHaveEffect() {
134 return
135 inCompressor || outCompressor ||
136 inZitarev || outZitarev ||
137 inFreeverb || outFreeverb ;
138 }
139
140 bool getHaveLimiter() {
141 return mLimit != LIMITER_NONE;
142 }
143
144 void setVerboseFlag(int v) {
145 gVerboseFlag = v;
146 }
147
148 int getNumIncomingChans() {
149 return mNumIncomingChans;
150 }
151
152 int getOutgoingNumChans() {
153 return mNumOutgoingChans;
154 }
155
156 // call these next two after it is decided what effects we will be using for the duration:
157
158 std::vector<ProcessPlugin*> allocateIncomingEffects(int nIncomingChans) {
159 mNumIncomingChans = nIncomingChans;
160 if (incomingEffectsAllocated) {
161 std::cerr << "*** Effects.h: attempt to allocate incoming effects more than once\n";
162 std::exit(1);
163 }
164 std::vector<ProcessPlugin*> incomingEffects;
165 if (inCompressor) {
166 assert(inCompressorP == nullptr);
167 inCompressorP = new Compressor(mNumIncomingChans, gVerboseFlag, inCompressorPreset);
168 if (gVerboseFlag) { std::cout << "Set up INCOMING COMPRESSOR\n"; }
169 incomingEffects.push_back(inCompressorP);
170 }
171 if (inZitarev) {
172 assert(inZitarevP == nullptr);
173 inZitarevP = new Reverb(mNumIncomingChans,mNumIncomingChans, 1.0 + zitarevInLevel);
174 if (gVerboseFlag) { std::cout << "Set up INCOMING REVERB (Zitarev)\n"; }
175 incomingEffects.push_back(inZitarevP);
176 }
177 if (inFreeverb) {
178 assert(inFreeverbP == nullptr);
179 inFreeverbP = new Reverb(mNumIncomingChans, mNumIncomingChans, freeverbInLevel);
180 if (gVerboseFlag) { std::cout << "Set up INCOMING REVERB (Freeverb)\n"; }
181 incomingEffects.push_back(inFreeverbP);
182 }
183 // LIMITER MUST GO LAST:
184 if ( mLimit == LIMITER_INCOMING || mLimit == LIMITER_BOTH) {
185 if (gVerboseFlag) {
186 std::cout << "Set up INCOMING LIMITER for " << mNumIncomingChans << " input channels\n";
187 }
188 assert(inLimiterP == nullptr);
189 inLimiterP = new Limiter(mNumIncomingChans, 1, gVerboseFlag); // mNumClientsAssumed not needed this direction
190 // Never needed in normal practice for incoming limiter: inLimiterP->setWarningAmplitude(limiterWarningAmplitude);
191 incomingEffects.push_back(inLimiterP);
192 }
193 incomingEffectsAllocated = true;
194 return incomingEffects;
195 }
196
197 std::vector<ProcessPlugin*> allocateOutgoingEffects(int nOutgoingChans) {
198 mNumOutgoingChans = nOutgoingChans;
199 if (outgoingEffectsAllocated) {
200 std::cerr << "*** Effects.h: attempt to allocate outgoing effects more than once\n";
201 std::exit(1);
202 }
203 std::vector<ProcessPlugin*> outgoingEffects;
204 if (outCompressor) {
205 assert(outCompressorP == nullptr);
206 outCompressorP = new Compressor(mNumOutgoingChans, gVerboseFlag, outCompressorPreset);
207 if (gVerboseFlag) { std::cout << "Set up OUTGOING COMPRESSOR\n"; }
208 outgoingEffects.push_back(outCompressorP);
209 }
210 if (outZitarev) {
211 assert(outZitarevP == nullptr);
212 outZitarevP = new Reverb(mNumOutgoingChans, mNumOutgoingChans, 1.0 + zitarevOutLevel);
213 if (gVerboseFlag) { std::cout << "Set up OUTGOING REVERB (Zitarev)\n"; }
214 outgoingEffects.push_back(outZitarevP);
215 }
216 if (outFreeverb) {
217 assert(outFreeverbP == nullptr);
218 outFreeverbP = new Reverb(mNumOutgoingChans, mNumOutgoingChans, freeverbOutLevel);
219 if (gVerboseFlag) { std::cout << "Set up OUTGOING REVERB (Freeverb)\n"; }
220 outgoingEffects.push_back(outFreeverbP);
221 }
222 // LIMITER MUST GO LAST:
223 if ( mLimit != LIMITER_NONE) {
224 if ( mLimit == LIMITER_OUTGOING || mLimit == LIMITER_BOTH) {
225 if (gVerboseFlag) {
226 std::cout << "Set up OUTGOING LIMITER for "
227 << mNumOutgoingChans << " output channels and "
228 << mNumClientsAssumed << " assumed client(s) ...\n";
229 }
230 assert(outLimiterP == nullptr);
231 outLimiterP = new Limiter(mNumOutgoingChans,mNumClientsAssumed);
232 outLimiterP->setWarningAmplitude(limiterWarningAmplitude);
233 // do not have mSampleRate yet, so cannot call limiter->init(mSampleRate) here
234 outgoingEffects.push_back(outLimiterP);
235 }
236 }
237 outgoingEffectsAllocated = true;
238 return outgoingEffects;
239 }
240
241 void printHelp(char* command, char helpCase) {
242 std::cout << "HELP for `" << command << "' (end-of-line comments start with `//')\n";
243 std::cout << "\n";
244 std::cout << "Examples:\n";
245 std::cout << "\n";
246 if (helpCase == 0 || helpCase == 'f') { //
247 std::cout << command << " 0.3 // add a default outgoing compressor (for voice) and incoming reverb (freeverb) with wetness 0.3 (wetness from 0 to 1)\n";
248 std::cout << command << " 1.3 // add a default outgoing compressor (for voice) and incoming reverb (zitarev) with wetness 0.3 = 1.3-1 (i.e., 1+ to 2 is for zitarev)\n";
249 std::cout << "\n";
250 std::cout << command << " \"o:c i:f(0.3)\" // outgoing-compressor and incoming-freeverb example above using more general string argument\n";
251 std::cout << command << " \"o:c i:z(0.3)\" // outgoing-compressor and incoming-zitarev example above using more general string argument\n";
252 std::cout << command << " \"o:c(1)\" // outgoing compressor, using preset 1 (designed for voice - see below for details)\n";
253 std::cout << command << " \"o:c(2)\" // outgoing compressor, using preset 2 (for horns)\n";
254 std::cout << command << " \"o:c(3)\" // outgoing compressor, using preset 3 (for snare)\n";
255 std::cout << command << " \"o:c(c:compressionRatio t:thresholdDB a:attackTimeMS r:releaseTimeMS g:makeUpGainDB)\" // general compression parameter specification (all floats)\n";
256 std::cout << command << " \"o:c(c:2 t:-24 a:15 r:40 g:2)\" // outgoing compressor, preset 1 details\n";
257 std::cout << command << " \"o:c(c:3 t:-10 a:100 r:250 g:2)\" // outgoing compressor, preset 2 details\n";
258 std::cout << command << " \"o:c(c:5 t:-4 a:5 r:150 g:3)\" // outgoing compressor, preset 3 details\n";
259 std::cout << " For these and more suggested compression settings, see http://www.anythingpeaceful.org/sonar/settings/comp.html\n";
260 std::cout << "\n";
261 }
262 if (helpCase == 0 || helpCase == 'O') { // limiter (-O option most likely)
263 std::cout << command << " i // add limiter to INCOMING audio from network (only helpful for floats, i.e., -b32 used by server)\n";
264 std::cout << command << " o // add limiter to OUTGOING audio to network (prevents your sound from harshly clipping going out)\n";
265 std::cout << command << " ow // also warn and advise on levels when outgoing limiter compresses audio near clipping\n";
266 std::cout << command << " io // add limiter to both INCOMING and OUTGOING audio\n";
267 std::cout << command << " iow // limiters both ways and compression warnings on outgoing direction only\n";
268 std::cout << "\n";
269 }
270 if (helpCase == 0 || helpCase == 'a') { // assumedNumClients (-a option)
271 std::cout << command << " 1 // assume 1 client - fine for loopback test, or if only one client plays at a time, or server uses -b32 and -Oi is used\n";
272 std::cout << command << " 2 // assume 2 clients possibly playing at the same time\n";
273 std::cout << command << " N // any integer N>0 can be used - the outgoing limiter will divide final amplitude by 1/sqrt(N) to reduce overages in server\n";
274 std::cout << "\n";
275 }
276 }
277
278 // ----------- Compressor stuff --------------
279
280 int setCompressorPresetIndexFrom1(unsigned long presetIndexFrom1, InOrOut io) {
281 int returnCode = 0;
282 if (presetIndexFrom1 <= 0 || presetIndexFrom1 > CompressorPresets::numPresets) {
283 std::cerr << "*** Effects.h: setCompressorPresetFrom1: Index " << presetIndexFrom1 << " out of range\n";
284 returnCode = 1;
285 } else {
286 CompressorPreset stdPreset = CompressorPresets::standardPresets[presetIndexFrom1-1];
287 if (io == IO_IN) {
288 inCompressorPreset = stdPreset;
289 } else if (io == IO_OUT) {
290 outCompressorPreset = stdPreset;
291 } else if (io != IO_NEITHER) {
292 std::cerr << "*** Effects.h: setCompressorPresetFrom1: Invalid InOrOut value " << io << "\n";
293 returnCode = 1;
294 }
295 }
296 return returnCode;
297 }
298
299 int parseCompresserArgs(char* args, InOrOut inOrOut) {
300 // args can be integerPresetNumberFrom1 or (all optional, any order):
301 // c:compressionRatio, a:attackTimeMS, r:releaseTimeMS, g:makeUpGain
302 int returnCode = 0;
303 if (not isalpha(args[0])) {
304 int presetIndexFrom1 = atoi(args);
305 setCompressorPresetIndexFrom1(presetIndexFrom1,inOrOut);
306 } else {
307 // args can be presetIndexFrom1, handled above, or (all optional, any order):
308 // c(c:compressionRatio, t:thresholdDB, a:attackTimeMS, r:releaseTimeMS, g:makeUpGainDB)
309 // See ./CompressorPresets.h for example settings.
310 if (gVerboseFlag) {
311 std::cout << "parseCompressorArgs = " << args << std::endl;
312 }
313 ulong argLen = strlen(args);
314 char lastParam = '\0';
315
316 CompressorPreset newPreset(CompressorPresets::voice); // Anything unset gets voice value (most gentle)
317
318 int nSkip = 0;
319 for (ulong i=0; i<argLen; i++) {
320 if (nSkip > 0) {
321 nSkip--;
322 continue;
323 }
324 char ch = args[i];
325 switch(ch) {
326 case ' ': break;
327 case '\t': break;
328 case 'c': case 't': case 'a': case 'r': case 'g':
329 lastParam = ch;
330 break;
331 case ':': break;
332 default: // must be a floating-point number at this point:
333 if (ch!='-' && isalpha(ch)) {
334 std::cerr << "*** Effects.h: parseCompressorArgs: " << ch << " not recognized in args = " << args << "\n";
335 returnCode = 2;
336 } else { // must have a digit or '-' or '.'
337 assert(ch=='-'||ch=='.'||isdigit(ch));
338 float paramValue = -1.0e10;
339 for (ulong j=i; j<argLen; j++) { // scan ahead for end of number
340 if (args[j] == ',' || args[j] == ' ' || j==argLen-1) { // comma or space required between parameters
341 char argsj = args[j];
342 if (j<argLen-1) { // there's more
343 args[j] = '\0';
344 }
345 paramValue = atof(&args[i]);
346 args[j] = argsj;
347 nSkip = j-i;
348 break;
349 }
350 }
351 if (paramValue == -1.0e10) {
352 std::cerr << "*** Effects.h: parseCompressorArgs: Could not find parameter for "
353 << lastParam << " in args = " << args << "\n";
354 returnCode = 2;
355 } else {
356 switch (lastParam) {
357 case 'c':
358 newPreset.ratio = paramValue;
359 break;
360 case 't':
361 newPreset.thresholdDB = paramValue;
362 break;
363 case 'a':
364 newPreset.attackMS = paramValue;
365 break;
366 case 'r':
367 newPreset.releaseMS = paramValue;
368 break;
369 case 'g':
370 newPreset.makeUpGainDB = paramValue;
371 break;
372 default: // cannot happen:
373 std::cerr << "*** Effects.h: parseCompressorArgs: lastParam " << lastParam << " invalid\n";
374 returnCode = 3; // "reality failure"
375 } // switch(lastParam)
376 } // have valid parameter from atof
377 } // have valid non-alpha char for parameter
378 } // switch(ch)
379 } // for (ulong i=0; i<argLen; i++) {
380 if (inOrOut == IO_IN) {
381 inCompressorPreset = newPreset;
382 } else if (inOrOut == IO_OUT) {
383 outCompressorPreset = newPreset;
384 } else if (inOrOut != IO_NEITHER) {
385 std::cerr << "*** Effects.h: parseCompressorArgs: invalid InOrOut value " << inOrOut << "\n";
386 returnCode = 2;
387 }
388 } // long-form compressor args
389 return returnCode;
390 } // int parseCompresserArgs(char* args, InOrOut inOrOut)
391
392 // ============== General argument processing for all effects =================
393
394 int parseEffectsOptArg(char* cmd, char* optarg) {
395 int returnCode = 0; // 0 means go, 1 means exit without error, higher => error exit
396
397 char c = optarg[0];
398 if (c == '-' || c==0) {
399 // happens when no -f argument specified
400 returnCode = 2;
401 } else if (not isalpha(c)) { // backward compatibility why not?, e.g., "-f 0.5"
402 // -f reverbLevelFloat
403 mReverbLevel = atof(optarg);
404 outCompressor = true;
405 inZitarev = mReverbLevel > 1.0;
406 inFreeverb = mReverbLevel <= 1.0;
407 if (inZitarev) {
408 zitarevInLevel = mReverbLevel - 1.0; // wetness from 0 to 1
409 }
410 if (inFreeverb) {
411 freeverbInLevel = mReverbLevel; // wetness from 0 to 1
412 }
413 } else { // long-form argument:
414 // -f "i:[c][f|z][(reverbLevel)]], o:[c][f|z][(rl)]"
415 // c can be c(integerPresetNumberFrom1) or (all optional, any order):
416 // c(c:compressionRatio, a:attackTimeMS, r:releaseTimeMS, g:makeUpGain)
417 if (gVerboseFlag) {
418 std::cout << cmd << " argument = " << optarg << std::endl;
419 }
420 ulong argLen = strlen(optarg);
421
422 for (ulong i=0; i<argLen; i++) {
423 if (optarg[i]!=')' && parenLevel>0) { continue; }
424 switch(optarg[i]) {
425 case ' ': break;
426 case ',': break;
427 case ';': break;
428 case '\t': break;
429 case 'h': printHelp(cmd,'f'); returnCode = 1; break;
430 case 'i': io=IO_IN; break;
431 case 'o': io=IO_OUT; break;
432 case ':': break;
433 case 'c': if (io==IO_IN) { inCompressor = true; } else if (io==IO_OUT) { outCompressor = true; }
434 else { std::cerr << "-f arg `" << optarg << "' malformed\n"; exit(1); }
435 lastEffect = 'c';
436 break;
437 case 'f': if (io==IO_IN) { inFreeverb = true; } else if (io==IO_OUT) { outFreeverb = true; }
438 else { std::cerr << "-f arg `" << optarg << "' malformed\n"; exit(1); }
439 lastEffect = 'f';
440 break;
441 case 'z': if (io==IO_IN) { inZitarev = true; } else if (io==IO_OUT) { outZitarev = true; }
442 else { std::cerr << "-f arg `" << optarg << "' malformed\n"; exit(1); }
443 lastEffect = 'z';
444 break;
445 case '(': parenLevel++;
446 for (ulong j=i+1; j<argLen; j++) {
447 if (optarg[j] == ')') {
448 optarg[j] = '\0';
449 switch(lastEffect) {
450 case 'c': {
451 returnCode += parseCompresserArgs(&optarg[i+1],io);
452 break; }
453 case 'z': {
454 float farg = atof(&optarg[i+1]);
455 if (io==IO_IN) {
456 zitarevInLevel = farg;
457 } else if (io==IO_OUT) {
458 zitarevOutLevel = farg;
459 } // else ignore the argument
460 break; }
461 case 'f': {
462 float farg = atof(&optarg[i+1]);
463 if (io==IO_IN) {
464 freeverbInLevel = farg;
465 } else if (io==IO_OUT) {
466 freeverbOutLevel = farg;
467 } // else ignore the argument
468 break; }
469 default: { // ignore
470 break; }
471 }
472 optarg[j] = ')';
473 break;
474 }
475 }
476 break;
477 case ')': parenLevel--;
478 break;
479 default:
480 break; // ignore
481 } // switch(optarg[i])
482 }
483 }
484 return returnCode;
485 }
486
487 int parseLimiterOptArg(char* cmd, char* optarg) {
488 int returnCode = 0;
489 lastEffect = 'O'; // OverflowLimiter
490 char ch = tolower(optarg[0]);
491 if (ch == '-' || ch == 0) {
492 std::cerr << cmd << " argument i, o, or io is REQUIRED\n";
493 returnCode = 2;
494 } else if (ch == 'h') {
495 printHelp(cmd,'O');
496 returnCode = 1;
497 } else {
498 bool haveIncoming = false;
499 bool haveOutgoing = false;
500 bool haveWarnings = false;
501 for (int i=0; i<strlen(optarg); i++) {
502 ch = tolower(optarg[i]);
503 switch(ch) {
504 case ' ': break;
505 case '\t': break;
506 case 'i':
507 haveIncoming = true;
508 break;
509 case 'o':
510 haveOutgoing = true;
511 break;
512 case 'w':
513 haveWarnings = true;
514 break;
515 case 'n':
516 haveIncoming = false;
517 haveOutgoing = false;
518 break;
519 default:
520 std::cerr << "*** Effects.h: parseLimiterOptArg: Unrecognized option " << ch << "\n";
521 returnCode = 2;
522 } // switch(ch)
523 } // process optarg char ch
524 mLimit = (haveIncoming && haveOutgoing ? LIMITER_BOTH
525 : (haveIncoming ? LIMITER_INCOMING
526 : (haveOutgoing ? LIMITER_OUTGOING : LIMITER_NONE)));
527 if (haveWarnings) {
528 limiterWarningAmplitude = 0.5; // KEEP IN SYNC WITH LIMITER THRESHOLD/CEILING 'softClipLevel' in ../faust-src/limiterdsp.dsp
529 // the warning amplitude and limiter compression threshold can of course be brought as a parameters, e.g. w(0.5)
530 }
531 if (gVerboseFlag) {
532 if(haveIncoming) {
533 std::cout << "Set up INCOMING Overflow Limiter\n";
534 }
535 if(haveOutgoing) {
536 std::cout << "Set up OUTGOING Overflow Limiter\n";
537 }
538 if(haveWarnings) {
539 std::cout << "Enable DISTORTION WARNINGS in Overflow Limiters\n";
540 }
541 if(not haveIncoming and not haveOutgoing) {
542 std::cout << "Set up NO Overflow Limiters\n";
543 }
544 } // gVerboseFlag
545 } // optarg cases
546 return returnCode;
547 } // parseLimiterOptArg()
548
549 int parseAssumedNumClientsOptArg(char* cmd, char* optarg) {
550 int returnCode = 0;
551 lastEffect = 'a'; // assumedNumClients
552 char ch = optarg[0];
553 if (ch == 'h') {
554 printHelp(cmd,'a');
555 returnCode = 1;
556 } else if (ch == '-' || isalpha(ch) || ch == 0) {
557 std::cerr << cmd << " argument help or integer > 0 is REQUIRED\n";
558 returnCode = 2;
559 } else {
560 mNumClientsAssumed = atoi(optarg);
561 if(mNumClientsAssumed < 1) {
562 std::cerr << "-p ERROR: Must have at least one assumed sound source: "
563 << atoi(optarg) << " is not supported." << std::endl;
564 returnCode = 2;
565 }
566 }
567 return returnCode;
568 }
569
570 };
7777 *
7878 */
7979 //-------------------------------------------------------------------------------
80 void JMess::writeOutput(QString xmlOutFile)
80 void JMess::writeOutput(__attribute__((unused)) QString xmlOutFile)
8181 {
8282 // QDomDocument jmess_xml; QDomElement root;
8383 // QDomElement connection; QDomElement output;
170170 void JMess::connectSpawnedPorts(int nChans, int hubPatch)
171171 // called from UdpHubListener::connectMesh
172172 {
173
174173 QMutexLocker locker(&sJMessMutex);
175
174
176175 QString IPS[gMAX_WAIRS];
177176 int ctr = 0;
178177
179 const char **ports, **connections; //vector of ports and connections
178 const char **ports; //, **connections; //vector of ports and connections
180179 QVector<QString> OutputInput(2); //helper variable
181180
182181 //Get active output ports.
201200 // qDebug() << ports[out_i] << systemPort << s;
202201 }
203202 }
204 // for (int i = 0; i<ctr; i++) qDebug() << IPS[i];
203 //for (int i = 0; i<ctr; i++) qDebug() << IPS[i];
205204 disconnectAll();
206205
207206 int k = 0;
216215 if ((hubPatch == JackTrip::CLIENTECHO)||(hubPatch == JackTrip::FULLMIX)) k = i;
217216 else if (hubPatch == JackTrip::CLIENTFOFI) k = (j+(i+1))%ctr;
218217 for (int l = 1; l<=nChans; l++) { // chans are 1-based
219 // qDebug() << "connect " << IPS[i]+":receive_"+QString::number(l)
220 // <<"with " << IPS[k]+":send_"+QString::number(l);
218 //qDebug() << "connect " << IPS[i]+":receive_"+QString::number(l)
219 //<<"with " << IPS[k]+":send_"+QString::number(l);
221220
222221 QString left = IPS[i] +
223222 ":receive_" + QString::number(l);
243242 for (int j = 0; j<jLimit; j++) {
244243 k = (j+(i+1))%ctr;
245244 for (int l = 1; l<=nChans; l++) { // chans are 1-based
246 // qDebug() << "connect " << IPS[i]+":receive_"+QString::number(l)
247 // <<"with " << IPS[k]+":send_"+QString::number(l);
245 //qDebug() << "connect " << IPS[i]+":receive_"+QString::number(l)
246 //<<"with " << IPS[k]+":send_"+QString::number(l);
248247
249248 QString left = IPS[i] +
250249 ":receive_" + QString::number(l);
370369 it != mConnectedPorts.end(); ++it) {
371370 OutputInput = *it;
372371
373 if (jack_disconnect(mClient, OutputInput[0].toLatin1(), OutputInput[1].toLatin1())) {
372 if (jack_disconnect(mClient, OutputInput[0].toUtf8(), OutputInput[1].toUtf8())) {
374373 cerr << "WARNING: port: " << qPrintable(OutputInput[0])
375374 << "and port: " << qPrintable(OutputInput[1])
376375 << " could not be disconnected.\n";
387386 * read the file.
388387 */
389388 //-------------------------------------------------------------------------------
390 int JMess::parseXML(QString xmlInFile)
389 int JMess::parseXML(__attribute__((unused)) QString xmlInFile)
391390 {
392391 // mPortsToConnect.clear();
393392 // QString errorStr;
454453 *
455454 */
456455 //-------------------------------------------------------------------------------
457 void JMess::connectPorts(QString xmlInFile)
456 void JMess::connectPorts(__attribute__((unused)) QString xmlInFile)
458457 {
459458 QVector<QString> OutputInput(2);
460459
6565 int NumNetRevChans,
6666 #endif // endwhere
6767 AudioInterface::audioBitResolutionT AudioBitResolution,
68 const char* ClientName) :
68 QString ClientName) :
6969 AudioInterface(jacktrip,
7070 NumInChans, NumOutChans,
7171 #ifdef WAIR // wair
8080 mBitResolutionMode(AudioBitResolution),
8181 mClient(NULL),
8282 mClientName(ClientName),
83 mBroadcast(false),
8384 mJackTrip(jacktrip)
8485 {}
8586
170171 // Initialize Buffer array to read and write audio
171172 mInBuffer.resize(mNumInChans);
172173 mOutBuffer.resize(mNumOutChans);
174 mBroadcastBuffer.resize(mNumOutChans);
173175 }
174176
175177
197199 JACK_DEFAULT_AUDIO_TYPE,
198200 JackPortIsOutput, 0);
199201 }
202 //Create Broadcast Ports
203 if (mBroadcast) {
204 mBroadcastPorts.resize(mNumOutChans);
205 for (int i = 0; i < mNumInChans; i++)
206 {
207 QString outName;
208 QTextStream (&outName) << "broadcast_" << i+1;
209 mBroadcastPorts[i] = jack_port_register (mClient, outName.toLatin1(),
210 JACK_DEFAULT_AUDIO_TYPE,
211 JackPortIsOutput, 0);
212 }
213 }
200214 }
201215
202216
272286 void JackAudioInterface::jackShutdown (void*)
273287 {
274288 //std::cout << "The Jack Server was shut down!" << std::endl;
275 throw std::runtime_error("The Jack Server was shut down!");
289 JackTrip::sJackStopped = true;
290 std::cout << "The Jack Server was shut down!" << std::endl;
291 //throw std::runtime_error("The Jack Server was shut down!");
276292 //std::cout << "Exiting program..." << std::endl;
277293 //std::exit(1);
278294 }
282298 //*******************************************************************************
283299 int JackAudioInterface::processCallback(jack_nframes_t nframes)
284300 {
301 if(mProcessingAudio) {
302 std::cerr << "*** JackAudioInterface.cpp: DROPPED A BUFFER because AudioInterface::callback() not finished\n";
303 return 1;
304 }
305
285306 // Get input and output buffers from JACK
286307 //-------------------------------------------------------------------
287308 for (int i = 0; i < mNumInChans; i++) {
288 // Input Ports are READ ONLY
309 // Input Ports are READ ONLY and change as needed (no locks) - make a copy for debugging
289310 mInBuffer[i] = (sample_t*) jack_port_get_buffer(mInPorts[i], nframes);
290311 }
291312 for (int i = 0; i < mNumOutChans; i++) {
301322 //-------------------------------------------------------------------
302323
303324 AudioInterface::callback(mInBuffer, mOutBuffer, nframes);
325
326 if (mBroadcast) {
327 for (int i = 0; i < mNumOutChans; i++) {
328 // Broadcast Ports are WRITABLE
329 mBroadcastBuffer[i] = (sample_t*) jack_port_get_buffer(mBroadcastPorts[i], nframes);
330 }
331 AudioInterface::broadcastCallback(mBroadcastBuffer, nframes);
332 }
304333 return 0;
305334 }
306335
376405
377406
378407
379 // OLD CODE
408 // OLD CODE (some moved to parent class AudioInterface.cpp)
380409 // ==============================================================================
381410
382411 //*******************************************************************************
7777 int NumNetRevChans,
7878 #endif // endwhere
7979 AudioInterface::audioBitResolutionT AudioBitResolution = AudioInterface::BIT16,
80 const char* ClientName = "JackTrip");
80 QString ClientName = "JackTrip");
8181 /// \brief The class destructor
8282 virtual ~JackAudioInterface();
8383
103103 { std::cout << "WARNING: Setting the Sample Rate in Jack mode has no effect." << std::endl; }
104104 virtual void setBufferSizeInSamples(uint32_t /*buf_size*/)
105105 { std::cout << "WARNING: Setting the Sample Rate in Jack mode has no effect." << std::endl; }
106 virtual void enableBroadcastOutput() {mBroadcast = true;}
106107 //------------------------------------------------------------------
107108
108109 //--------------GETTERS---------------------------------------------
112113 virtual uint32_t getBufferSizeInSamples() const;
113114 /// \brief Get the Jack Server Buffer Size, in bytes
114115 virtual uint32_t getBufferSizeInBytes() const
115 { return (getBufferSizeInSamples() * getAudioBitResolution()/8); }
116 { return (getBufferSizeInSamples() * getAudioBitResolution() / 8); }
116117 /// \brief Get size of each audio per channel, in bytes
117118 virtual size_t getSizeInBytesPerChannel() const;
118119 //------------------------------------------------------------------
176177 QString mClientName; ///< Jack Client Name
177178 QVarLengthArray<jack_port_t*> mInPorts; ///< Vector of Input Ports (Channels)
178179 QVarLengthArray<jack_port_t*> mOutPorts; ///< Vector of Output Ports (Channels)
180 QVarLengthArray<jack_port_t*> mBroadcastPorts; ///< Vector of Output Ports (Channels)
179181 QVarLengthArray<sample_t*> mInBuffer; ///< Vector of Input buffers/channel read from JACK
180182 QVarLengthArray<sample_t*> mOutBuffer; ///< Vector of Output buffer/channel to write to JACK
183 QVarLengthArray<sample_t*> mBroadcastBuffer; ///< Vector of Output buffer/channel to write to JACK
184 bool mBroadcast;
181185 size_t mSizeInBytesPerChannel; ///< Size in bytes per audio channel
182186 QVector<ProcessPlugin*> mProcessPlugins; ///< Vector of ProcesPlugin<EM>s</EM>
183187 JackTrip* mJackTrip; ///< JackTrip mediator class
3737 #include "JackTrip.h"
3838 #include "UdpDataProtocol.h"
3939 #include "RingBufferWavetable.h"
40 #include "JitterBuffer.h"
4041 #include "jacktrip_globals.h"
4142 #include "JackAudioInterface.h"
4243 #ifdef __RT_AUDIO__
5051 #include <QHostAddress>
5152 #include <QHostInfo>
5253 #include <QThread>
53 #include <QTcpSocket>
5454 #include <QTimer>
5555 #include <QDateTime>
5656
5858
5959 //the following function has to remain outside the Jacktrip class definition
6060 //its purpose is to close the app when control c is hit by the user in rtaudio/asio4all mode
61 #if defined __WIN_32__
61 /*if defined __WIN_32__
6262 void sigint_handler(int sig)
6363 {
6464 exit(0);
6565 }
66 #endif
66 #endif*/
67
68 bool JackTrip::sSigInt = false;
69 bool JackTrip::sJackStopped = false;
6770
6871 //*******************************************************************************
6972 JackTrip::JackTrip(jacktripModeT JacktripMode,
8891 mNumNetRevChans(NumNetRevChans),
8992 #endif // endwhere
9093 mBufferQueueLength(BufferQueueLength),
94 mBufferStrategy(1),
95 mBroadcastQueueLength(0),
9196 mSampleRate(gDefaultSampleRate),
9297 mDeviceID(gDefaultDeviceID),
9398 mAudioBufferSize(gDefaultBufferSizeInSamples),
9499 mAudioBitResolution(AudioBitResolution),
100 mLoopBack(false),
95101 mDataProtocolSender(NULL),
96102 mDataProtocolReceiver(NULL),
97103 mAudioInterface(NULL),
98104 mPacketHeader(NULL),
99105 mUnderRunMode(UnderRunMode),
106 mStopOnTimeout(false),
100107 mSendRingBuffer(NULL),
101108 mReceiveRingBuffer(NULL),
102109 mReceiverBindPort(receiver_bind_port),
107114 mRedundancy(redundancy),
108115 mJackClientName(gJackDefaultClientName),
109116 mConnectionMode(JackTrip::NORMAL),
117 mTimeoutTimer(this),
118 mSleepTime(100),
119 mElapsedTime(0),
120 mEndTime(0),
121 mTcpClient(this),
122 mUdpSockTemp(this),
110123 mReceivedConnection(false),
111124 mTcpConnectionError(false),
112125 mStopped(false),
126 mHasShutdown(false),
113127 mConnectDefaultAudioPorts(true),
114 mIOStatLogStream(std::cout.rdbuf())
128 mIOStatTimeout(0),
129 mIOStatLogStream(std::cout.rdbuf()),
130 mSimulatedLossRate(0.0),
131 mSimulatedJitterRate(0.0),
132 mSimulatedDelayRel(0.0),
133 mUseRtUdpPriority(false),
134 mAudioTesterP(nullptr)
115135 {
116136 createHeader(mPacketHeaderType);
137 sJackStopped = false;
117138 }
118139
119140
120141 //*******************************************************************************
121142 JackTrip::~JackTrip()
122143 {
123 wait();
144 //wait();
124145 delete mDataProtocolSender;
125146 delete mDataProtocolReceiver;
126147 delete mAudioInterface;
133154 //*******************************************************************************
134155 void JackTrip::setupAudio(
135156 #ifdef WAIRTOHUB // WAIR
136 int ID
157 __attribute__((unused)) int ID
137158 #endif // endwhere
138159 )
139160 {
140161 // Check if mAudioInterface has already been created or not
141162 if (mAudioInterface != NULL) { // if it has been created, disconnet it from JACK and delete it
142163 cout << "WARINING: JackAudio interface was setup already:" << endl;
143 cout << "It will be errased and setup again." << endl;
164 cout << "It will be erased and setup again." << endl;
144165 cout << gPrintSeparator << endl;
145166 closeAudio();
146167 }
156177 mAudioBitResolution);
157178
158179 #ifdef WAIRTOHUB // WAIR
159 // qDebug() << "mPeerAddress" << mPeerAddress << mPeerAddress.contains(gDOMAIN_TRIPLE);
160180 QString VARIABLE_AUDIO_NAME = WAIR_AUDIO_NAME; // legacy for WAIR
161 QByteArray tmp = QString(mPeerAddress).replace(":", ".").toLatin1();
162181 //Set our Jack client name if we're a hub server or a custom name hasn't been set
163182 if (!mPeerAddress.isEmpty() && (mJackClientName.constData() == gJackDefaultClientName.constData())) {
164183 mJackClientName = QString(mPeerAddress).replace(":", "_");
165184 }
166 // if ( mPeerAddress.toStdString() != "" &&
167 // (mJackClientName == gJackDefaultClientName || mJackTripMode == SERVERPINGSERVER)) {
168 // mJackClientName = QString(mPeerAddress).replace(":", ".").toLatin1().constData();
169 // }
170
171 // std::cout << "WAIR ID " << ID << " jacktrip client name set to=" <<
172 // mJackClientName << std::endl;
185 //std::cout << "WAIR ID " << ID << " jacktrip client name set to=" <<
186 // mJackClientName.toStdString() << std::endl;
187
173188 #endif // endwhere
174
175189 mAudioInterface->setClientName(mJackClientName);
190 if (0 < mBroadcastQueueLength) {
191 mAudioInterface->enableBroadcastOutput();
192 }
176193
177194 if (gVerboseFlag) std::cout << " JackTrip:setupAudio before mAudioInterface->setup" << std::endl;
178195 mAudioInterface->setup();
204221 #endif
205222 }
206223
224 mAudioInterface->setLoopBack(mLoopBack);
225 if (mAudioTesterP) { // if we're a hub server, this will be a nullptr - MAJOR REFACTOR NEEDED, in my opinion
226 mAudioTesterP->setSampleRate(mSampleRate);
227 }
228 mAudioInterface->setAudioTesterP(mAudioTesterP);
229
207230 std::cout << "The Sampling Rate is: " << mSampleRate << std::endl;
208231 std::cout << gPrintSeparator << std::endl;
209232 int AudioBufferSizeInBytes = mAudioBufferSize*sizeof(sample_t);
210233 std::cout << "The Audio Buffer Size is: " << mAudioBufferSize << " samples" << std::endl;
211234 std::cout << " or: " << AudioBufferSizeInBytes
212235 << " bytes" << std::endl;
236 if (0 < mBroadcastQueueLength) {
237 std::cout << gPrintSeparator << std::endl;
238 cout << "Broadcast Output is enabled, delay = "
239 << mBroadcastQueueLength * mAudioBufferSize * 1000 / mSampleRate << " ms"
240 << " (" << mBroadcastQueueLength * mAudioBufferSize << " samples)" << endl;
241 }
213242 std::cout << gPrintSeparator << std::endl;
214243 cout << "The Number of Channels is: " << mAudioInterface->getNumInputChannels() << endl;
215 std::cout << gPrintSeparator << std::endl;
216 cout << "The RTAudio device ID is: " << mAudioInterface->getDeviceID() << endl;
217244 std::cout << gPrintSeparator << std::endl;
218245 QThread::usleep(100);
219246 }
234261 //*******************************************************************************
235262 void JackTrip::setupDataProtocol()
236263 {
264 double simulated_max_delay = mSimulatedDelayRel * getBufferSizeInSamples() / getSampleRate();
237265 // Create DataProtocol Objects
238266 switch (mDataProtocol) {
239267 case UDP:
240268 std::cout << "Using UDP Protocol" << std::endl;
241 std::cout << gPrintSeparator << std::endl;
242269 QThread::usleep(100);
243270 mDataProtocolSender = new UdpDataProtocol(this, DataProtocol::SENDER,
244271 //mSenderPeerPort, mSenderBindPort,
247274 mDataProtocolReceiver = new UdpDataProtocol(this, DataProtocol::RECEIVER,
248275 mReceiverBindPort, mReceiverPeerPort,
249276 mRedundancy);
277 if (0.0 < mSimulatedLossRate || 0.0 < mSimulatedJitterRate || 0.0 < simulated_max_delay) {
278 mDataProtocolReceiver->setIssueSimulation(mSimulatedLossRate, mSimulatedJitterRate, simulated_max_delay);
279 }
280 mDataProtocolSender->setUseRtPriority(mUseRtUdpPriority);
281 mDataProtocolReceiver->setUseRtPriority(mUseRtUdpPriority);
282 if (mUseRtUdpPriority) {
283 cout << "Using RT thread priority for UDP data" << endl;
284 }
285 std::cout << gPrintSeparator << std::endl;
250286 break;
251287 case TCP:
252288 throw std::invalid_argument("TCP Protocol is not implemented");
276312 /// \todo Make all this operations cleaner
277313 //int total_audio_packet_size = getTotalAudioPacketSizeInBytes();
278314 int slot_size = getRingBuffersSlotSize();
315 if (0 <= mBufferStrategy) {
316 mUnderRunMode = ZEROS;
317 }
318 else if (0 > mBufferQueueLength) {
319 throw std::invalid_argument("Auto queue is not supported by RingBuffer");
320 }
279321
280322 switch (mUnderRunMode) {
281323 case WAVETABLE:
289331 mReceiveRingBuffer = new RingBufferWavetable(mAudioInterface->getSizeInBytesPerChannel() * mNumChans,
290332 mBufferQueueLength);
291333 */
292
293334 break;
294335 case ZEROS:
295336 mSendRingBuffer = new RingBuffer(slot_size,
296337 gDefaultOutputQueueLength);
297 mReceiveRingBuffer = new RingBuffer(slot_size,
298 mBufferQueueLength);
338 if (0 > mBufferStrategy) {
339 mReceiveRingBuffer = new RingBuffer(slot_size,
340 mBufferQueueLength);
341 }
342 else {
343 cout << "Using JitterBuffer strategy " << mBufferStrategy << endl;
344 if (0 > mBufferQueueLength) {
345 cout << "Using AutoQueue 1/" << -mBufferQueueLength << endl;
346 }
347 mReceiveRingBuffer = new JitterBuffer(mAudioBufferSize, mBufferQueueLength,
348 mSampleRate, mBufferStrategy,
349 mBroadcastQueueLength, mNumChans, mAudioBitResolution);
350 }
299351 /*
300352 mSendRingBuffer = new RingBuffer(mAudioInterface->getSizeInBytesPerChannel() * mNumChans,
301353 gDefaultOutputQueueLength);
311363
312364
313365 //*******************************************************************************
314 void JackTrip::setPeerAddress(const char* PeerHostOrIP)
366 void JackTrip::setPeerAddress(QString PeerHostOrIP)
315367 {
316368 mPeerAddress = PeerHostOrIP;
317369 }
318370
319371
320372 //*******************************************************************************
321 void JackTrip::appendProcessPlugin(ProcessPlugin* plugin)
322 {
323 mProcessPlugins.append(plugin);
324 //mAudioInterface->appendProcessPlugin(plugin);
373 void JackTrip::appendProcessPluginToNetwork(ProcessPlugin* plugin)
374 {
375 if (plugin) {
376 mProcessPluginsToNetwork.append(plugin); // ownership transferred
377 //mAudioInterface->appendProcessPluginToNetwork(plugin);
378 }
379 }
380
381 //*******************************************************************************
382 void JackTrip::appendProcessPluginFromNetwork(ProcessPlugin* plugin)
383 {
384 if (plugin) {
385 mProcessPluginsFromNetwork.append(plugin); // ownership transferred
386 //mAudioInterface->appendProcessPluginFromNetwork(plugin);
387 }
325388 }
326389
327390
332395 #endif // endwhere
333396 )
334397 { //signal that catches ctrl c in rtaudio-asio mode
335 #if defined (__WIN_32__)
398 /*#if defined (__WIN_32__)
336399 if (signal(SIGINT, sigint_handler) == SIG_ERR) {
337400 perror("signal");
338401 exit(1);
339402 }
340 #endif
403 #endif*/
341404 // Check if ports are already binded by another process on this machine
342405 // ------------------------------------------------------------------
343406 if (gVerboseFlag) std::cout << "step 1" << std::endl;
344407
345408 if (gVerboseFlag) std::cout << " JackTrip:startProcess before checkIfPortIsBinded(mReceiverBindPort)" << std::endl;
346409 #if defined __WIN_32__
347 //cc fixed windows crash with this print statement! hope to delete
348 // qDebug() << "before mJackTrip->startProcess" << mReceiverBindPort<< mSenderBindPort;
410 //cc fixed windows crash with this print statement!
411 //qDebug() << "before mJackTrip->startProcess" << mReceiverBindPort<< mSenderBindPort;
349412 #endif
350413 checkIfPortIsBinded(mReceiverBindPort);
351414 if (gVerboseFlag) std::cout << " JackTrip:startProcess before checkIfPortIsBinded(mSenderBindPort)" << std::endl;
364427 setupRingBuffers();
365428 // Connect Signals and Slots
366429 // -------------------------
367 QObject::connect(mPacketHeader, SIGNAL(signalError(const char*)),
368 this, SLOT(slotStopProcesses()), Qt::QueuedConnection);
430 QObject::connect(mPacketHeader, &PacketHeader::signalError,
431 this, &JackTrip::slotStopProcessesDueToError, Qt::QueuedConnection);
369432 QObject::connect(mDataProtocolReceiver, SIGNAL(signalReceivedConnectionFromPeer()),
370433 this, SLOT(slotReceivedConnectionFromPeer()),
371434 Qt::QueuedConnection);
372 QObject::connect(this, SIGNAL(signalUdpTimeOut()),
373 this, SLOT(slotStopProcesses()), Qt::QueuedConnection);
435 //QObject::connect(this, SIGNAL(signalUdpTimeOut()),
436 // this, SLOT(slotStopProcesses()), Qt::QueuedConnection);
437 QObject::connect((UdpDataProtocol *)mDataProtocolReceiver, &UdpDataProtocol::signalUdpWaitingTooLong, this,
438 &JackTrip::slotUdpWaitingTooLong, Qt::QueuedConnection);
439 QObject::connect(mDataProtocolSender, &DataProtocol::signalCeaseTransmission,
440 this, &JackTrip::slotStopProcessesDueToError, Qt::QueuedConnection);
441 QObject::connect(mDataProtocolReceiver, &DataProtocol::signalCeaseTransmission,
442 this, &JackTrip::slotStopProcessesDueToError, Qt::QueuedConnection);
374443
375444 //QObject::connect(mDataProtocolSender, SIGNAL(signalError(const char*)),
376445 // this, SLOT(slotStopProcesses()), Qt::QueuedConnection);
377 //QObject::connect(mDataProtocolReceiver, SIGNAL(signalError(const char*)),
378 // this, SLOT(slotStopProcesses()), Qt::QueuedConnection);
446 QObject::connect(mDataProtocolReceiver, SIGNAL(signalError(const char*)),
447 this, SLOT(slotStopProcesses()), Qt::QueuedConnection);
379448
380449 // Start the threads for the specific mode
381450 // ---------------------------------------
395464 if (gVerboseFlag) std::cout << "step 2C client only" << std::endl;
396465 if (gVerboseFlag) std::cout << " JackTrip:startProcess case CLIENTTOPINGSERVER before clientPingToServerStart" << std::endl;
397466 if ( clientPingToServerStart() == -1 ) { // if error on server start (-1) we return inmediatly
398 mTcpConnectionError = true;
399 slotStopProcesses();
467 stop("Peer Address has to be set if you run in CLIENTTOPINGSERVER mode");
400468 return;
401469 }
402470 break;
404472 if (gVerboseFlag) std::cout << "step 2S server only (same as 2s)" << std::endl;
405473 if (gVerboseFlag) std::cout << " JackTrip:startProcess case SERVERPINGSERVER before serverStart" << std::endl;
406474 if ( serverStart(true) == -1 ) { // if error on server start (-1) we return inmediatly
407 slotStopProcesses();
475 stop();
408476 return;
409477 }
410478 break;
411479 default:
412 throw std::invalid_argument("Jacktrip Mode undefined");
413 break;
414 }
415
480 throw std::invalid_argument("Jacktrip Mode undefined");
481 break;
482 }
483 }
484
485 void JackTrip::completeConnection()
486 {
416487 // Have the threads share a single socket that operates at full duplex.
417488 #if defined (__WIN_32__)
418489 SOCKET sock_fd = INVALID_SOCKET;
438509 QThread::msleep(1);
439510 if (gVerboseFlag) std::cout << "step 5" << std::endl;
440511 if (gVerboseFlag) std::cout << " JackTrip:startProcess before mAudioInterface->startProcess" << std::endl;
441 mAudioInterface->startProcess();
442
443 for (int i = 0; i < mProcessPlugins.size(); ++i) {
444 mAudioInterface->appendProcessPlugin(mProcessPlugins[i]);
445 }
512 for (int i = 0; i < mProcessPluginsFromNetwork.size(); ++i) {
513 mAudioInterface->appendProcessPluginFromNetwork(mProcessPluginsFromNetwork[i]);
514 }
515 for (int i = 0; i < mProcessPluginsToNetwork.size(); ++i) {
516 mAudioInterface->appendProcessPluginToNetwork(mProcessPluginsToNetwork[i]);
517 }
518 mAudioInterface->initPlugins(); // mSampleRate known now, which plugins require
519 mAudioInterface->startProcess(); // Tell JACK server we are ready for audio flow now
520
446521 if (mConnectDefaultAudioPorts) { mAudioInterface->connectDefaultPorts(); }
447 }
448
449 //*******************************************************************************
450 void JackTrip::startIOStatTimer(int timeout_sec, const std::ostream& log_stream)
451 {
452 mIOStatLogStream.rdbuf(log_stream.rdbuf());
453 QTimer *timer = new QTimer(this);
454 connect(timer, SIGNAL(timeout()), this, SLOT(onStatTimer()));
455 timer->start(timeout_sec*1000);
522
523 //Start our IO stat timer
524 if (mIOStatTimeout > 0) {
525 cout << "STATS" << mIOStatTimeout << endl;
526 if (!mIOStatStream.isNull()) {
527 mIOStatLogStream.rdbuf(((std::ostream *)mIOStatStream.data())->rdbuf());
528 }
529 QTimer *timer = new QTimer(this);
530 connect(timer, SIGNAL(timeout()), this, SLOT(onStatTimer()));
531 timer->start(mIOStatTimeout*1000);
532 }
456533 }
457534
458535 //*******************************************************************************
472549 return;
473550 }
474551 QString now = QDateTime::currentDateTime().toString(Qt::ISODate);
475 int32_t skew = recv_io_stat.underruns - recv_io_stat.overflows
476 - pkt_stat.lost + pkt_stat.revived;
477552
478553 static QMutex mutex;
479554 QMutexLocker locker(&mutex);
555 if (mAudioTesterP && mAudioTesterP->getEnabled()) {
556 mIOStatLogStream << "\n";
557 }
480558 mIOStatLogStream << now.toLocal8Bit().constData()
481559 << " " << getPeerAddress().toLocal8Bit().constData()
482560 << " send: "
491569 << "/" << pkt_stat.revived
492570 << " tot: "
493571 << pkt_stat.tot
494 << " skew: " << skew
572 << " sync: "
573 << recv_io_stat.level
574 << "/" << recv_io_stat.buf_inc_underrun
575 << "/" << recv_io_stat.buf_inc_compensate
576 << "/" << recv_io_stat.buf_dec_overflows
577 << "/" << recv_io_stat.buf_dec_pktloss
578 << " skew: " << recv_io_stat.skew
579 << "/" << recv_io_stat.skew_raw
580 << " bcast: " << recv_io_stat.broadcast_skew
581 << "/" << recv_io_stat.broadcast_delta
582 << " autoq: " << 0.1*recv_io_stat.autoq_corr
583 << "/" << 0.1*recv_io_stat.autoq_rate
495584 << endl;
496585 }
497586
498 //*******************************************************************************
499 void JackTrip::stop()
500 {
501 // Stop The Sender
502 mDataProtocolSender->stop();
503 mDataProtocolSender->wait();
504
505 // Stop The Receiver
506 mDataProtocolReceiver->stop();
507 mDataProtocolReceiver->wait();
508
509 // Stop the audio processes
510 //mAudioInterface->stopProcess();
511 closeAudio();
512
513 cout << "JackTrip Processes STOPPED!" << endl;
587 void JackTrip::receivedConnectionTCP()
588 {
589 mTimeoutTimer.stop();
590 if (gVerboseFlag) cout << "TCP Socket Connected to Server!" << endl;
591 emit signalTcpClientConnected();
592
593 // Send Client Port Number to Server
594 // ---------------------------------
595 char port_buf[sizeof(mReceiverBindPort) + gMaxRemoteNameLength];
596 std::memcpy(port_buf, &mReceiverBindPort, sizeof(mReceiverBindPort));
597 std::memset(port_buf + sizeof(mReceiverBindPort), 0, gMaxRemoteNameLength);
598 if (!mRemoteClientName.isEmpty()) {
599 //If our remote client name is set, send it too.
600 QByteArray name = mRemoteClientName.toUtf8();
601 // Find a clean place to truncate if we're over length.
602 // (Make sure we're not in the middle of a multi-byte characetr.)
603 int length = name.length();
604 //Need to take the final null terminator into account here.
605 if (length > gMaxRemoteNameLength - 1) {
606 length = gMaxRemoteNameLength - 1;
607 while ((length > 0) && ((name.at(length) & 0xc0) == 0x80)) {
608 //We're in the middle of a multi-byte character. Work back.
609 length--;
610 }
611 }
612 name.truncate(length);
613 std::memcpy(port_buf + sizeof(mReceiverBindPort), name.data(), length + 1);
614 }
615
616 mTcpClient.write(port_buf, sizeof(port_buf));
617 /*while ( mTcpClient.bytesToWrite() > 0 ) {
618 mTcpClient.waitForBytesWritten(-1);
619 }*/
620 if (gVerboseFlag) cout << "Port " << mReceiverBindPort << " sent to Server" << endl;
621 //Continued in receivedDataTCP slot
622 }
623
624 void JackTrip::receivedDataTCP()
625 {
626 if (mTcpClient.bytesAvailable() < (int)sizeof(uint16_t)) {
627 return;
628 }
629
630 // Read the size of the package
631 // ----------------------------
632 if (gVerboseFlag) cout << "Reading UDP port from Server..." << endl;
633 if (gVerboseFlag) cout << "Ready To Read From Socket!" << endl;
634
635 // Read UDP Port Number from Server
636 // --------------------------------
637 uint32_t udp_port;
638 int size = sizeof(udp_port);
639 char port_buf[sizeof(mReceiverBindPort)];
640 //char port_buf[size];
641 mTcpClient.read(port_buf, size);
642 std::memcpy(&udp_port, port_buf, size);
643 //cout << "Received UDP Port Number: " << udp_port << endl;
644
645 // Close the TCP Socket
646 // --------------------
647 mTcpClient.close(); // Close the socket
648 //cout << "TCP Socket Closed!" << endl;
649 if (gVerboseFlag) cout << "Connection Succesfull!" << endl;
650
651 // Set with the received UDP port
652 // ------------------------------
653 setPeerPorts(udp_port);
654 mDataProtocolReceiver->setPeerAddress( mPeerAddress.toLatin1().data() );
655 mDataProtocolSender->setPeerAddress( mPeerAddress.toLatin1().data() );
656 mDataProtocolSender->setPeerPort(udp_port);
657 mDataProtocolReceiver->setPeerPort(udp_port);
658 cout << "Server Address set to: " << mPeerAddress.toStdString() << " Port: " << udp_port << std::endl;
514659 cout << gPrintSeparator << endl;
515
516 // Emit the jack stopped signal
517 emit signalProcessesStopped();
518 }
519
520
521 //*******************************************************************************
522 void JackTrip::waitThreads()
523 {
524 mDataProtocolSender->wait();
525 mDataProtocolReceiver->wait();
526 }
527
528
529 //*******************************************************************************
530 void JackTrip::clientStart()
531 {
532 // For the Client mode, the peer (or server) address has to be specified by the user
533 if ( mPeerAddress.isEmpty() ) {
534 throw std::invalid_argument("Peer Address has to be set if you run in CLIENT mode");
535 }
536 else {
537 mDataProtocolSender->setPeerAddress( mPeerAddress.toLatin1().data() );
538 mDataProtocolReceiver->setPeerAddress( mPeerAddress.toLatin1().data() );
539 cout << "Peer Address set to: " << mPeerAddress.toStdString() << std::endl;
540 cout << gPrintSeparator << endl;
541 }
542 }
543
544
545 //*******************************************************************************
546 int JackTrip::serverStart(bool timeout, int udpTimeout) // udpTimeout unused
547 {
548 // Set the peer address
549 if ( !mPeerAddress.isEmpty() ) {
550 if (gVerboseFlag) std::cout << "WARNING: SERVER mode: Peer Address was set but will be deleted." << endl;
551 //throw std::invalid_argument("Peer Address has to be set if you run in CLIENT mode");
552 mPeerAddress.clear();
553 //return;
554 }
555
556 // Get the client address when it connects
660 completeConnection();
661 }
662
663 void JackTrip::receivedDataUDP()
664 {
665 //Stop our timer.
666 mTimeoutTimer.stop();
667
557668 QHostAddress peerHostAddress;
558669 uint16_t peer_port;
559 if (gVerboseFlag) std::cout << "JackTrip:serverStart before QUdpSocket UdpSockTemp" << std::endl;
560 QUdpSocket UdpSockTemp;// Create socket to wait for client
561
562 if (gVerboseFlag) std::cout << "JackTrip:serverStart before UdpSockTemp.bind(Any)" << std::endl;
563 // Bind the socket
564 if ( !UdpSockTemp.bind(QHostAddress::Any, mReceiverBindPort,
565 QUdpSocket::DefaultForPlatform) )
566 {
567 std::cerr << "in JackTrip: Could not bind UDP socket. It may be already binded." << endl;
568 throw std::runtime_error("Could not bind UDP socket. It may be already binded.");
569 }
570 // Listen to client
571 int sleepTime = 100; // ms
572 int elapsedTime = 0;
573 if (timeout) {
574 while ( (!UdpSockTemp.hasPendingDatagrams()) && (elapsedTime <= udpTimeout) ) {
575 if (mStopped == true) { emit signalUdpTimeOut(); UdpSockTemp.close(); return -1; }
576 QThread::msleep(sleepTime);
577 elapsedTime += sleepTime;
578 }
579 if (!UdpSockTemp.hasPendingDatagrams()) {
580 emit signalUdpTimeOut();
581 cout << "JackTrip Server Timed Out!" << endl;
582 return -1;
583 }
584 } else {
585 if (gVerboseFlag) std::cout << "JackTrip:serverStart before !UdpSockTemp.hasPendingDatagrams()" << std::endl;
586 cout << "Waiting for Connection From a Client..." << endl;
587 while ( !UdpSockTemp.hasPendingDatagrams() ) {
588 if (mStopped == true) { emit signalUdpTimeOut(); return -1; }
589 if (gVerboseFlag) std::cout << sleepTime << "ms " << std::flush;
590 QThread::msleep(sleepTime);
591 }
592 }
593 // char buf[1];
594 // // set client address
595 // UdpSockTemp.readDatagram(buf, 1, &peerHostAddress, &peer_port);
596 // UdpSockTemp.close(); // close the socket
597
670
598671 // IPv6 addition from fyfe
599672 // Get the datagram size to avoid problems with IPv6
600 qint64 datagramSize = UdpSockTemp.pendingDatagramSize();
673 qint64 datagramSize = mUdpSockTemp.pendingDatagramSize();
601674 char buf[datagramSize];
602675 // set client address
603 UdpSockTemp.readDatagram(buf, datagramSize, &peerHostAddress, &peer_port);
604 UdpSockTemp.close(); // close the socket
676 mUdpSockTemp.readDatagram(buf, datagramSize, &peerHostAddress, &peer_port);
677 mUdpSockTemp.close(); // close the socket
605678
606679 // Check for mapped IPv4->IPv6 addresses that look like ::ffff:x.x.x.x
607680 if (peerHostAddress.protocol() == QAbstractSocket::IPv6Protocol) {
635708 mDataProtocolSender->setPeerPort(peer_port);
636709 mDataProtocolReceiver->setPeerPort(peer_port);
637710 setPeerPorts(peer_port);
711 completeConnection();
712 }
713
714 void JackTrip::udpTimerTick()
715 {
716 if (mStopped || sSigInt || sJackStopped) {
717 //Stop everything.
718 mUdpSockTemp.close();
719 mTimeoutTimer.stop();
720 stop();
721 }
722
723 if (gVerboseFlag) std::cout << mSleepTime << "ms " << std::flush;
724 mElapsedTime += mSleepTime;
725 if (mEndTime > 0 && mElapsedTime >= mEndTime) {
726 mUdpSockTemp.close();
727 mTimeoutTimer.stop();
728 cout << "JackTrip Server Timed Out!" << endl;
729 stop("JackTrip Server Timed Out");
730 }
731 }
732
733 void JackTrip::tcpTimerTick()
734 {
735 if (mStopped || sSigInt || sJackStopped) {
736 //Stop everything.
737 mTcpClient.close();
738 mTimeoutTimer.stop();
739 stop();
740 }
741
742 mElapsedTime += mSleepTime;
743 if (mEndTime > 0 && mElapsedTime >= mEndTime) {
744 mTcpClient.close();
745 mTimeoutTimer.stop();
746 cout << "JackTrip Server Timed Out!" << endl;
747 stop("Initial TCP Connection Timed Out");
748 }
749
750 }
751
752 //*******************************************************************************
753 void JackTrip::stop(QString errorMessage)
754 {
755 mStopped = true;
756 //Make sure we're only run once
757 if (mHasShutdown) {
758 return;
759 }
760 mHasShutdown = true;
761 std::cout << "Stopping JackTrip..." << std::endl;
762
763 // Stop The Sender
764 mDataProtocolSender->stop();
765 mDataProtocolSender->wait();
766
767 // Stop The Receiver
768 mDataProtocolReceiver->stop();
769 mDataProtocolReceiver->wait();
770
771 // Stop the audio processes
772 //mAudioInterface->stopProcess();
773 closeAudio();
774
775 cout << "JackTrip Processes STOPPED!" << endl;
776 cout << gPrintSeparator << endl;
777
778 // Emit the jack stopped signal
779 if (sJackStopped) {
780 emit signalError("The Jack Server was shut down!");
781 } else if (errorMessage.isEmpty()) {
782 emit signalProcessesStopped();
783 } else {
784 emit signalError(errorMessage);
785 }
786 }
787
788
789 //*******************************************************************************
790 void JackTrip::waitThreads()
791 {
792 mDataProtocolSender->wait();
793 mDataProtocolReceiver->wait();
794 }
795
796
797 //*******************************************************************************
798 void JackTrip::clientStart()
799 {
800 // For the Client mode, the peer (or server) address has to be specified by the user
801 if ( mPeerAddress.isEmpty() ) {
802 throw std::invalid_argument("Peer Address has to be set if you run in CLIENT mode");
803 }
804 else {
805 mDataProtocolSender->setPeerAddress( mPeerAddress.toLatin1().data() );
806 mDataProtocolReceiver->setPeerAddress( mPeerAddress.toLatin1().data() );
807 cout << "Peer Address set to: " << mPeerAddress.toStdString() << std::endl;
808 cout << gPrintSeparator << endl;
809 completeConnection();
810 }
811 }
812
813
814 //*******************************************************************************
815 int JackTrip::serverStart(bool timeout, int udpTimeout) // udpTimeout unused
816 {
817 // Set the peer address
818 if ( !mPeerAddress.isEmpty() ) {
819 if (gVerboseFlag) std::cout << "WARNING: SERVER mode: Peer Address was set but will be deleted." << endl;
820 //throw std::invalid_argument("Peer Address has to be set if you run in CLIENT mode");
821 mPeerAddress.clear();
822 //return;
823 }
824
825 // Get the client address when it connects
826 if (gVerboseFlag) std::cout << "JackTrip:serverStart before mUdpSockTemp.bind(Any)" << std::endl;
827 // Bind the socket
828 if ( !mUdpSockTemp.bind(QHostAddress::Any, mReceiverBindPort,
829 QUdpSocket::DefaultForPlatform) )
830 {
831 std::cerr << "in JackTrip: Could not bind UDP socket. It may be already binded." << endl;
832 throw std::runtime_error("Could not bind UDP socket. It may be already binded.");
833 }
834 connect(&mUdpSockTemp, &QUdpSocket::readyRead, this, &JackTrip::receivedDataUDP);
835
836 // Start timer and then wait for a signal to read datagrams.
837 mElapsedTime = 0;
838 if (timeout) {
839 mEndTime = udpTimeout;
840 }
841 mTimeoutTimer.setInterval(mSleepTime);
842 connect(&mTimeoutTimer, &QTimer::timeout, this, &JackTrip::udpTimerTick);
843 mTimeoutTimer.start();
844
845 if (gVerboseFlag) std::cout << "JackTrip:serverStart before !UdpSockTemp.hasPendingDatagrams()" << std::endl;
846 cout << "Waiting for Connection From a Client..." << endl;
638847 return 0;
848 // Continued in the receivedDataUDP slot.
849
850 // char buf[1];
851 // // set client address
852 // UdpSockTemp.readDatagram(buf, 1, &peerHostAddress, &peer_port);
853 // UdpSockTemp.close(); // close the socket
639854 }
640855
641856
655870
656871 // Create Socket Objects
657872 // --------------------
658 QTcpSocket tcpClient;
659873 QHostAddress serverHostAddress;
660874 if (!serverHostAddress.setAddress(mPeerAddress)) {
661875 QHostInfo info = QHostInfo::fromName(mPeerAddress);
667881
668882 // Connect Socket to Server and wait for response
669883 // ----------------------------------------------
670 tcpClient.connectToHost(serverHostAddress, mTcpServerPort);
884 connect(&mTcpClient, &QTcpSocket::readyRead, this, &JackTrip::receivedDataTCP);
885 connect(&mTcpClient, &QTcpSocket::connected, this, &JackTrip::receivedConnectionTCP);
886 mElapsedTime = 0;
887 mEndTime = 5000; //Timeout after 5 seconds.
888 mTimeoutTimer.setInterval(mSleepTime);
889 connect(&mTimeoutTimer, &QTimer::timeout, this, &JackTrip::tcpTimerTick);
890 mTimeoutTimer.start();
891 mTcpClient.connectToHost(serverHostAddress, mTcpServerPort);
892
671893 if (gVerboseFlag) cout << "Connecting to TCP Server at " << serverHostAddress.toString().toLatin1().constData() << " port " << mTcpServerPort << "..." << endl;
672 if (!tcpClient.waitForConnected()) {
673 std::cerr << "TCP Socket ERROR at " << mTcpServerPort << ": " << tcpClient.errorString().toStdString() << endl;
674 //std::exit(1);
675 return -1;
676 }
677 if (gVerboseFlag) cout << "TCP Socket Connected to Server!" << endl;
678 emit signalTcpClientConnected();
679
680 // Send Client Port Number to Server
681 // ---------------------------------
682 char port_buf[sizeof(mReceiverBindPort)];
683 std::memcpy(port_buf, &mReceiverBindPort, sizeof(mReceiverBindPort));
684
685 tcpClient.write(port_buf, sizeof(mReceiverBindPort));
686 while ( tcpClient.bytesToWrite() > 0 ) {
687 tcpClient.waitForBytesWritten(-1);
688 }
689 if (gVerboseFlag) cout << "Port " << mReceiverBindPort << " sent to Server" << endl;
690
691 // Read the size of the package
692 // ----------------------------
693 if (gVerboseFlag) cout << "Reading UDP port from Server..." << endl;
694 while (tcpClient.bytesAvailable() < (int)sizeof(uint16_t)) {
695 if (!tcpClient.waitForReadyRead()) {
696 std::cerr << "TCP Socket ERROR: " << tcpClient.errorString().toStdString() << endl;
697 //std::exit(1);
698 return -1;
699 }
700 }
701 if (gVerboseFlag) cout << "Ready To Read From Socket!" << endl;
702
703 // Read UDP Port Number from Server
704 // --------------------------------
705 uint32_t udp_port;
706 int size = sizeof(udp_port);
707 //char port_buf[size];
708 tcpClient.read(port_buf, size);
709 std::memcpy(&udp_port, port_buf, size);
710 //cout << "Received UDP Port Number: " << udp_port << endl;
711
712 // Close the TCP Socket
713 // --------------------
714 tcpClient.close(); // Close the socket
715 //cout << "TCP Socket Closed!" << endl;
716 if (gVerboseFlag) cout << "Connection Successful!" << endl;
717
718 // Set with the received UDP port
719 // ------------------------------
720 setPeerPorts(udp_port);
721 mDataProtocolReceiver->setPeerAddress( mPeerAddress.toLatin1().data() );
722 mDataProtocolSender->setPeerAddress( mPeerAddress.toLatin1().data() );
723 mDataProtocolSender->setPeerPort(udp_port);
724 mDataProtocolReceiver->setPeerPort(udp_port);
725 cout << "Server Address set to: " << mPeerAddress.toStdString() << " Port: " << udp_port << std::endl;
726 cout << gPrintSeparator << endl;
727894 return 0;
895 // Continued in the receivedConnectionTCP slot.
728896
729897 /*
730898 else {
8921060 std::memcpy(audio_packet, audio_part, getTotalAudioPacketSizeInBytes());
8931061 }
8941062
895
8961063 //*******************************************************************************
8971064 void JackTrip::checkPeerSettings(int8_t* full_packet)
8981065 {
4343 #include <QObject>
4444 #include <QString>
4545 #include <QUdpSocket>
46 #include <QTcpSocket>
47 #include <QTimer>
48 #include <QSharedPointer>
4649
4750 #include "DataProtocol.h"
4851 #include "AudioInterface.h"
5356
5457 #include "PacketHeader.h"
5558 #include "RingBuffer.h"
56
57 #include <signal.h>
59 #include "AudioTester.h"
60
61 //#include <signal.h>
5862 /** \brief Main class to creates a SERVER (to listen) or a CLIENT (to connect
5963 * to a listening server) to send audio streams in the network.
6064 *
6367 * Classes that uses JackTrip methods need to register with it.
6468 */
6569
66 class JackTrip : public QThread
70 class JackTrip : public QObject
6771 {
6872 Q_OBJECT;
6973
7983
8084 /// \brief Enum for the JackTrip mode
8185 enum jacktripModeT {
82 SERVER, ///< Run in Server Mode
83 CLIENT, ///< Run in Client Mode
86 SERVER, ///< Run in P2P Server Mode
87 CLIENT, ///< Run in P2P Client Mode
8488 CLIENTTOPINGSERVER, ///< Client of the Ping Server Mode
8589 SERVERPINGSERVER ///< Server of the MultiThreaded JackTrip
8690 };
110114 CLIENTECHO, ///< Client Echo (client self-to-self)
111115 CLIENTFOFI, ///< Client Fan Out to Clients and Fan In from Clients (but not self-to-self)
112116 RESERVEDMATRIX, ///< Reserved for custom patch matrix (for TUB ensemble)
113 FULLMIX ///< Client Fan Out to Clients and Fan In from Clients (including self-to-self)
117 FULLMIX, ///< Client Fan Out to Clients and Fan In from Clients (including self-to-self)
118 NOAUTO ///< No automatic patching
114119 };
115120 //---------------------------------------------------------
116121
132137 int BufferQueueLength = gDefaultQueueLength,
133138 unsigned int redundancy = gDefaultRedundancy,
134139 AudioInterface::audioBitResolutionT AudioBitResolution =
135 AudioInterface::BIT16,
140 AudioInterface::BIT16,
136141 DataProtocol::packetHeaderTypeT PacketHeaderType =
137 DataProtocol::DEFAULT,
142 DataProtocol::DEFAULT,
138143 underrunModeT UnderRunMode = WAVETABLE,
139144 int receiver_bind_port = gDefaultPort,
140145 int sender_bind_port = gDefaultPort,
144149
145150 /// \brief The class destructor
146151 virtual ~JackTrip();
152
153 static void sigIntHandler(__attribute__((unused)) int unused)
154 { std::cout << std::endl << "Shutting Down..." << std::endl; sSigInt = true; }
155 static bool sSigInt;
156 static bool sJackStopped;
147157
148158 /// \brief Starting point for the thread
149 virtual void run() {
159 /*virtual void run() {
150160 if (gVerboseFlag) std::cout << "Settings:startJackTrip before mJackTrip->run" << std::endl;
151 }
161 }*/
152162
153163 /// \brief Set the Peer Address for jacktripModeT::CLIENT mode only
154 virtual void setPeerAddress(const char* PeerHostOrIP);
164 virtual void setPeerAddress(QString PeerHostOrIP);
155165
156166 /** \brief Append a process plugin. Processes will be appended in order
157167 * \param plugin Pointer to ProcessPlugin Class
158168 */
159169 //void appendProcessPlugin(const std::tr1::shared_ptr<ProcessPlugin> plugin);
160 virtual void appendProcessPlugin(ProcessPlugin* plugin);
170 virtual void appendProcessPluginToNetwork(ProcessPlugin* plugin);
171 virtual void appendProcessPluginFromNetwork(ProcessPlugin* plugin);
161172
162173 /// \brief Start the processing threads
163174 virtual void startProcess(
165176 int ID
166177 #endif // endwhere
167178 );
179 virtual void completeConnection();
168180
169181 /// \brief Stop the processing threads
170 virtual void stop();
182 virtual void stop(QString errorMessage = "");
171183
172184 /// \brief Wait for all the threads to finish. This functions is used when JackTrip is
173185 /// run as a thread
198210 /// \brief Sets (override) Buffer Queue Length Mode after construction
199211 virtual void setBufferQueueLength(int BufferQueueLength)
200212 { mBufferQueueLength = BufferQueueLength; }
213 virtual void setBufferStrategy(int BufferStrategy)
214 { mBufferStrategy = BufferStrategy; }
201215 /// \brief Sets (override) Audio Bit Resolution after construction
202216 virtual void setAudioBitResolution(AudioInterface::audioBitResolutionT AudioBitResolution)
203217 { mAudioBitResolution = AudioBitResolution; }
204218 /// \brief Sets (override) Underrun Mode
205219 virtual void setUnderRunMode(underrunModeT UnderRunMode)
206220 { mUnderRunMode = UnderRunMode; }
221 /// \brief Sets whether to quit on timeout.
222 virtual void setStopOnTimeout(bool stopOnTimeout)
223 { mStopOnTimeout = stopOnTimeout; }
207224 /// \brief Sets port numbers for the local and peer machine.
208225 /// Receive port is <tt>port</tt>
209226 virtual void setAllPorts(int port)
228245 /// \brief Set Client Name to something different that the default (JackTrip)
229246 virtual void setClientName(QString clientName)
230247 { mJackClientName = clientName; }
248 virtual void setRemoteClientName(QString remoteClientName)
249 { mRemoteClientName = remoteClientName; }
231250 /// \brief Set the number of audio channels
232251 virtual void setNumChannels(int num_chans)
233252 { mNumChans = num_chans; }
253
254 virtual void setIOStatTimeout(int timeout) { mIOStatTimeout = timeout; }
255 virtual void setIOStatStream(QSharedPointer<std::ofstream> statStream) { mIOStatStream = statStream; }
234256
235257 /// Set to connect or not default audio ports (only implemented in Jack)
236258 virtual void setConnectDefaultAudioPorts(bool connect)
273295 { mAudiointerfaceMode = audiointerface_mode; }
274296 virtual void setAudioInterface(AudioInterface* const AudioInterface)
275297 { mAudioInterface = AudioInterface; }
276
298 virtual void setLoopBack(bool b)
299 { mLoopBack = b; }
300 virtual void setAudioTesterP(AudioTester* atp) { mAudioTesterP = atp; }
277301
278302 void setSampleRate(uint32_t sample_rate)
279303 { mSampleRate = sample_rate; }
304328
305329 bool tcpConnectionError()
306330 { return mTcpConnectionError; }
331
307332 //@}
308333 //------------------------------------------------------------------------------------
309334
317342 virtual int getPacketSizeInBytes();
318343 void parseAudioPacket(int8_t* full_packet, int8_t* audio_packet);
319344 virtual void sendNetworkPacket(const int8_t* ptrToSlot)
320 { mSendRingBuffer->insertSlotNonBlocking(ptrToSlot); }
345 { mSendRingBuffer->insertSlotNonBlocking(ptrToSlot, 0, 0); }
346 virtual void receiveBroadcastPacket(int8_t* ptrToReadSlot)
347 { mReceiveRingBuffer->readBroadcastSlot(ptrToReadSlot); }
321348 virtual void receiveNetworkPacket(int8_t* ptrToReadSlot)
322349 { mReceiveRingBuffer->readSlotNonBlocking(ptrToReadSlot); }
323350 virtual void readAudioBuffer(int8_t* ptrToReadSlot)
324351 { mSendRingBuffer->readSlotBlocking(ptrToReadSlot); }
325 virtual void writeAudioBuffer(const int8_t* ptrToSlot)
326 { mReceiveRingBuffer->insertSlotNonBlocking(ptrToSlot); }
352 virtual bool writeAudioBuffer(const int8_t* ptrToSlot, int len, int lostLen)
353 { return mReceiveRingBuffer->insertSlotNonBlocking(ptrToSlot, len, lostLen); }
327354 uint32_t getBufferSizeInSamples() const
328355 { return mAudioBufferSize; /*return mAudioInterface->getBufferSizeInSamples();*/ }
329356 uint32_t getDeviceID() const
392419 void printTextTest() {std::cout << "=== JackTrip PRINT ===" << std::endl;}
393420 void printTextTest2() {std::cout << "=== JackTrip PRINT2 ===" << std::endl;}
394421
395 void startIOStatTimer(int timeout_sec, const std::ostream& log_stream);
422 void setNetIssuesSimulation(double loss, double jitter, double delay_rel)
423 {
424 mSimulatedLossRate = loss;
425 mSimulatedJitterRate = jitter;
426 mSimulatedDelayRel = delay_rel;
427 }
428 void setBroadcast(int broadcast_queue) {mBroadcastQueueLength = broadcast_queue;}
429 void setUseRtUdpPriority(bool use) {mUseRtUdpPriority = use;}
396430
397431 public slots:
398432 /// \brief Slot to stop all the processes and threads
399433 virtual void slotStopProcesses()
400 {
401 std::cout << "Stopping JackTrip..." << std::endl;
402 mStopped = true;
403 this->stop();
404 }
434 { this->stop(); }
435 virtual void slotStopProcessesDueToError(const QString &errorMessage)
436 { this->stop(errorMessage); }
405437
406438 /** \brief This slot emits in turn the signal signalNoUdpPacketsForSeconds
407439 * when UDP has waited for more than 30 seconds.
413445 int wait_time = 10000; // msec
414446 if ( !(wait_msec%wait_time) ) {
415447 std::cerr << "UDP WAITED MORE THAN 10 seconds." << std::endl;
448 if (mStopOnTimeout) {
449 stop("No network data received for 10 seconds");
450 }
416451 emit signalNoUdpPacketsForSeconds();
417452 }
418453 }
454 void slotUdpWaitingTooLong()
455 { emit signalUdpWaitingTooLong(); }
419456 void slotPrintTest()
420457 { std::cout << "=== TESTING ===" << std::endl; }
421458 void slotReceivedConnectionFromPeer()
422 { mReceivedConnection = true; }
459 { mReceivedConnection = true; emit signalReceivedConnectionFromPeer(); }
423460 void onStatTimer();
424
461
462 private slots:
463 void receivedConnectionTCP();
464 void receivedDataTCP();
465 void receivedDataUDP();
466 void udpTimerTick();
467 void tcpTimerTick();
425468
426469 signals:
427
428 void signalUdpTimeOut();
470 //void signalUdpTimeOut();
429471 /// \brief Signal emitted when all the processes and threads are stopped
430472 void signalProcessesStopped();
431473 /// \brief Signal emitted when no UDP Packets have been received for a while
432474 void signalNoUdpPacketsForSeconds();
433475 void signalTcpClientConnected();
434
476 void signalError(const QString &errorMessage);
477 void signalReceivedConnectionFromPeer();
478 void signalUdpWaitingTooLong();
435479
436480 public:
437481
474518 int mNumNetRevChans; ///< Number of Network Audio Channels (net comb filters)
475519 #endif // endwhere
476520 int mBufferQueueLength; ///< Audio Buffer from network queue length
521 int mBufferStrategy;
522 int mBroadcastQueueLength;
477523 uint32_t mSampleRate; ///< Sample Rate
478524 uint32_t mDeviceID; ///< RTAudio DeviceID
479525 uint32_t mAudioBufferSize; ///< Audio buffer size to process on each callback
480526 AudioInterface::audioBitResolutionT mAudioBitResolution; ///< Audio Bit Resolutions
527 bool mLoopBack;
481528 QString mPeerAddress; ///< Peer Address to use in jacktripModeT::CLIENT Mode
482529
483530 /// Pointer to Abstract Type DataProtocol that sends packets
487534 AudioInterface* mAudioInterface; ///< Interface to Jack Client
488535 PacketHeader* mPacketHeader; ///< Pointer to Packet Header
489536 underrunModeT mUnderRunMode; ///< underrunModeT Mode
537 bool mStopOnTimeout; ///< Stop on 10 second timeout
490538
491539 /// Pointer for the Send RingBuffer
492540 RingBuffer* mSendRingBuffer;
501549
502550 unsigned int mRedundancy; ///< Redundancy factor in network data
503551 QString mJackClientName; ///< JackAudio Client Name
552 QString mRemoteClientName; ///< Remote JackAudio Client Name for hub client mode
504553
505554 JackTrip::connectionModeT mConnectionMode; ///< Connection Mode
506555 JackTrip::hubConnectionModeT mHubConnectionModeT; ///< Hub Server Jack Audio Patch Connection Mode
507556
508 QVector<ProcessPlugin*> mProcessPlugins; ///< Vector of ProcesPlugin<EM>s</EM>
557 QVector<ProcessPlugin*> mProcessPluginsFromNetwork; ///< Vector of ProcessPlugin<EM>s</EM>
558 QVector<ProcessPlugin*> mProcessPluginsToNetwork; ///< Vector of ProcessPlugin<EM>s</EM>
559
560 QTimer mTimeoutTimer;
561 int mSleepTime;
562 int mElapsedTime;
563 int mEndTime;
564 QTcpSocket mTcpClient;
565 QUdpSocket mUdpSockTemp;
509566
510567 volatile bool mReceivedConnection; ///< Bool of received connection from peer
511568 volatile bool mTcpConnectionError;
512569 volatile bool mStopped;
570 volatile bool mHasShutdown;
513571
514572 bool mConnectDefaultAudioPorts; ///< Connect or not default audio ports
573 QSharedPointer<std::ofstream> mIOStatStream;
574 int mIOStatTimeout;
515575 std::ostream mIOStatLogStream;
576 double mSimulatedLossRate;
577 double mSimulatedJitterRate;
578 double mSimulatedDelayRel;
579 bool mUseRtUdpPriority;
580
581 AudioTester* mAudioTesterP;
516582 };
517583
518584 #endif
5656 }
5757
5858 NetKS netks;
59 jacktrip.appendProcessPlugin(&netks);
59 jacktrip.appendProcessPluginFromNetwork(&netks);
6060 //netks.play();
6161
6262
6363 //QThread::sleep(1);
64 jacktrip.start();
64 //jacktrip.start();
6565 //netks.play();
66 jacktrip.wait();
66 //jacktrip.wait();
6767
6868
6969 cout << "******** AFTER JACKTRIPTHREAD START **************" << endl;
4444 #include "JackTripWorker.h"
4545 #include "JackTrip.h"
4646 #include "UdpHubListener.h"
47 #include "NetKS.h"
47 //#include "NetKS.h"
4848 #include "LoopBack.h"
4949 #include "Settings.h"
5050 #ifdef WAIR // wair
5757 using std::cout; using std::endl;
5858
5959 //*******************************************************************************
60 JackTripWorker::JackTripWorker(UdpHubListener* udpmasterlistener, int BufferQueueLength, JackTrip::underrunModeT UnderRunMode) :
61 mUdpHubListener(udpmasterlistener),
60 JackTripWorker::JackTripWorker(UdpHubListener* udphublistener, int BufferQueueLength, JackTrip::underrunModeT UnderRunMode, QString clientName) :
61 mUdpHubListener(udphublistener),
6262 m_connectDefaultAudioPorts(false),
6363 mBufferQueueLength(BufferQueueLength),
6464 mUnderRunMode(UnderRunMode),
65 mClientName(clientName),
6566 mSpawning(false),
6667 mID(0),
67 mNumChans(1)
68 mNumChans(1),
69 mIOStatTimeout(0)
6870 #ifdef WAIR // wair
6971 ,mNumNetRevChans(0),
7072 mWAIR(false)
7375 setAutoDelete(false); // stick around after calling run()
7476 //mNetks = new NetKS;
7577 //mNetks->play();
78 mBufferStrategy = 1;
79 mBroadcastQueue = 0;
80 mSimulatedLossRate = 0.0;
81 mSimulatedJitterRate = 0.0;
82 mSimulatedDelayRel = 0.0;
83 mUseRtUdpPriority = false;
7684 }
7785
7886
127135 // Create and setup JackTrip Object
128136 //JackTrip jacktrip(JackTrip::SERVER, JackTrip::UDP, mNumChans, 2);
129137 if (gVerboseFlag) cout << "---> JackTripWorker: Creating jacktrip objects..." << endl;
130 Settings* settings = mUdpHubListener->getSettings();
131138
132139 #ifdef WAIR // WAIR
133140 // forces BufferQueueLength to 2
161168 switch ( mNumNetRevChans )
162169 {
163170 case 16 : // freeverb
164 mJackTrip->appendProcessPlugin(new dcblock2gain(mNumChans)); // plugin slot 0
171 mJackTrip->appendProcessPluginFromNetwork(new dcblock2gain(mNumChans)); // plugin slot 0
165172 ///////////////
166173 // mJackTrip->appendProcessPlugin(new comb16server(mNumNetChans));
167174 // -S LAIR no AP mJackTrip->appendProcessPlugin(new AP8(mNumChans));
183190
184191 // Set our underrun mode
185192 jacktrip.setUnderRunMode(mUnderRunMode);
193 if (mIOStatTimeout > 0) {
194 jacktrip.setIOStatTimeout(mIOStatTimeout);
195 jacktrip.setIOStatStream(mIOStatStream);
196 }
197
198 if (!mClientName.isEmpty()) {
199 jacktrip.setClientName(mClientName);
200 }
186201
187202 // Connect signals and slots
188203 // -------------------------
194209 // Connection to terminate the local eventloop when jacktrip is done
195210 QObject::connect(&jacktrip, SIGNAL(signalProcessesStopped()),
196211 &event_loop, SLOT(quit()), Qt::QueuedConnection);
212 QObject::connect(&jacktrip, &JackTrip::signalError, &event_loop, &QEventLoop::quit, Qt::QueuedConnection);
197213 QObject::connect(this, SIGNAL(signalRemoveThread()),
198214 &jacktrip, SLOT(slotStopProcesses()), Qt::QueuedConnection);
199215
202218 // I still haven't figure out why
203219 //ClientAddress.toString().toLatin1().constData();
204220 //jacktrip.setPeerAddress(ClientAddress.toString().toLatin1().constData());
205 jacktrip.setPeerAddress(mClientAddress.toLatin1().constData());
221 jacktrip.setPeerAddress(mClientAddress);
206222 jacktrip.setBindPorts(mServerPort);
207223 //jacktrip.setPeerPorts(mClientPort);
224 jacktrip.setBufferStrategy(mBufferStrategy);
225 jacktrip.setNetIssuesSimulation(mSimulatedLossRate,
226 mSimulatedJitterRate, mSimulatedDelayRel);
227 jacktrip.setBroadcast(mBroadcastQueue);
228 jacktrip.setUseRtUdpPriority(mUseRtUdpPriority);
208229
209230 if (gVerboseFlag) cout << "---> JackTripWorker: setJackTripFromClientHeader..." << endl;
210231 int PeerConnectionMode = setJackTripFromClientHeader(jacktrip);
221242 mID
222243 #endif // endwhere
223244 );
224 if (0 != settings->getIOStatTimeout()) {
225 jacktrip.startIOStatTimer(settings->getIOStatTimeout(), settings->getIOStatStream());
226 }
227245 // if (gVerboseFlag) cout << "---> JackTripWorker: start..." << endl;
228246 // jacktrip.start(); // ########### JamTest Only #################
229247
232250
233251 event_loop.exec(); // Excecution will block here until exit() the QEventLoop
234252 //--------------------------------------------------------------------------
235
253
236254 { QMutexLocker locker(&mMutex); mSpawning = true; }
237255
238256 // wait for jacktrip to be done before exiting the Worker Thread
239 jacktrip.wait();
257 //jacktrip.wait();
240258
241259 }
242260 catch ( const std::exception & e )
6969
7070 public:
7171 /// \brief The class constructor
72 JackTripWorker(UdpHubListener* udpmasterlistener, int BufferQueueLength = gDefaultQueueLength, JackTrip::underrunModeT UnderRunMode = JackTrip::WAVETABLE);
72 JackTripWorker(UdpHubListener* udphublistener, int BufferQueueLength = gDefaultQueueLength, JackTrip::underrunModeT UnderRunMode = JackTrip::WAVETABLE, QString clientName = "");
7373 /// \brief The class destructor
7474 virtual ~JackTripWorker();
7575
9696 return mID;
9797 }
9898
99
99 void setBufferStrategy(int BufferStrategy) { mBufferStrategy = BufferStrategy; }
100 void setNetIssuesSimulation(double loss, double jitter, double delay_rel)
101 {
102 mSimulatedLossRate = loss;
103 mSimulatedJitterRate = jitter;
104 mSimulatedDelayRel = delay_rel;
105 }
106 void setBroadcast(int broadcast_queue) {mBroadcastQueue = broadcast_queue;}
107 void setUseRtUdpPriority(bool use) {mUseRtUdpPriority = use;}
108
109 void setIOStatTimeout(int timeout) { mIOStatTimeout = timeout; }
110 void setIOStatStream(QSharedPointer<std::ofstream> statStream) { mIOStatStream = statStream; }
111
100112 private slots:
101113 void slotTest()
102114 { std::cout << "--- JackTripWorker TEST SLOT ---" << std::endl; }
104116
105117 signals:
106118 void signalRemoveThread();
107
108119
109120 private:
110121 int setJackTripFromClientHeader(JackTrip& jacktrip);
118129
119130 /// Client Outgoing Port. By convention, the receving port will be <tt>mClientPort -1</tt>
120131 uint16_t mClientPort;
132
133 int mBufferQueueLength;
134 JackTrip::underrunModeT mUnderRunMode;
135 QString mClientName;
121136
122137 /// Thread spawning internal lock.
123138 /// If true, the prototype is working on creating (spawning) a new thread
124139 volatile bool mSpawning;
125140 QMutex mMutex; ///< Mutex to protect mSpawning
126 JackTrip::underrunModeT mUnderRunMode;
127 int mBufferQueueLength;
128141
129142 int mID; ///< ID thread number
130143 int mNumChans; ///< Number of Channels
144
145 int mBufferStrategy;
146 int mBroadcastQueue;
147 double mSimulatedLossRate;
148 double mSimulatedJitterRate;
149 double mSimulatedDelayRel;
150 bool mUseRtUdpPriority;
151
152 int mIOStatTimeout;
153 QSharedPointer<std::ofstream> mIOStatStream;
131154 #ifdef WAIR // wair
132155 int mNumNetRevChans; ///< Number of Net Channels = net combs
133156 bool mWAIR;
0 //*****************************************************************
1 /*
2 JackTrip: A System for High-Quality Audio Network Performance
3 over the Internet
4
5 Copyright (c) 2020 Juan-Pablo Caceres, Chris Chafe.
6 SoundWIRE group at CCRMA, Stanford University.
7
8 Permission is hereby granted, free of charge, to any person
9 obtaining a copy of this software and associated documentation
10 files (the "Software"), to deal in the Software without
11 restriction, including without limitation the rights to use,
12 copy, modify, merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom the
14 Software is furnished to do so, subject to the following
15 conditions:
16
17 The above copyright notice and this permission notice shall be
18 included in all copies or substantial portions of the Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 OTHER DEALINGS IN THE SOFTWARE.
28 */
29 //*****************************************************************
30
31 /**
32 * \file JitterBuffer.cpp
33 * \author Anton Runov
34 * \date June 2020
35 */
36
37
38 #include "JitterBuffer.h"
39
40 #include <iostream>
41 #include <cstring>
42 #include <cstdlib>
43 #include <stdexcept>
44 #include <cmath>
45
46 using std::cout; using std::endl;
47
48
49 //*******************************************************************************
50 JitterBuffer::JitterBuffer(int buf_samples, int qlen, int sample_rate, int strategy,
51 int bcast_qlen, int channels, int bit_res) :
52 RingBuffer(0, 0)
53 {
54 int total_size = sample_rate * channels * bit_res * 2; // 2 secs of audio
55 int slot_size = buf_samples * channels * bit_res;
56 mSlotSize = slot_size;
57 mInSlotSize = slot_size;
58 if (0 < qlen) {
59 mMaxLatency = qlen * slot_size;
60 mAutoQueue = 0;
61 }
62 else {
63 // AutoQueue
64 mMaxLatency = 3*slot_size;
65 mAutoQueue = 1;
66 }
67 mTotalSize = total_size;
68 mBroadcastLatency = bcast_qlen * mSlotSize;
69 mNumChannels = channels;
70 mAudioBitRes = bit_res;
71 mMinStepSize = channels * bit_res;
72 mFPP = buf_samples;
73 mSampleRate = sample_rate;
74 mActive = false;
75
76 // Defaults for zero strategy
77 mUnderrunIncTolerance = -10 * mSlotSize;
78 mCorrIncTolerance = 100*mMaxLatency; // should be greater than mUnderrunIncTolerance
79 mOverflowDecTolerance = 100*mMaxLatency;
80 mWritePosition = mMaxLatency;
81 mStatUnit = mSlotSize;
82 mLevelDownRate = std::min(256, mFPP) / (5.0*sample_rate) * mSlotSize;
83 mOverflowDropStep = mMaxLatency / 2;
84 mLevelCur = mMaxLatency;
85 mLevel = mLevelCur;
86 mMinLevelThreshold = 1.9 * mSlotSize;
87 mBroadcastPosition = 0;
88 mBroadcastPositionCorr = 0.0;
89 mLastCorrCounter = 0;
90 mLastCorrDirection = 0;
91
92 switch (strategy) {
93 case 1:
94 mOverflowDropStep = mSlotSize;
95 break;
96 case 2:
97 mUnderrunIncTolerance = 1.1 * mSlotSize;
98 mCorrIncTolerance = 1.9 * mSlotSize; // should be greater than mUnderrunIncTolerance
99 mOverflowDecTolerance = 0.1*mSlotSize;
100 mOverflowDropStep = mSlotSize;
101 break;
102 }
103
104 mRingBuffer = new int8_t[mTotalSize];
105 std::memset(mRingBuffer, 0, mTotalSize);
106
107 mAutoQueueCorr = 2*mSlotSize;
108 if (0 > qlen) {
109 mAutoQFactor = 1.0/-qlen;
110 }
111 else {
112 mAutoQFactor = 1.0/500;
113 }
114 mAutoQRate = mSlotSize * 0.5;
115 mAutoQRateMin = mSlotSize * 0.0005;
116 mAutoQRateDecay = 1.0 - std::min(mFPP*1.2e-6, 0.0005);
117 }
118
119 //*******************************************************************************
120 bool JitterBuffer::insertSlotNonBlocking(const int8_t* ptrToSlot, int len, int lostLen)
121 {
122 if (0 == len) {
123 len = mSlotSize;
124 }
125 QMutexLocker locker(&mMutex);
126 mInSlotSize = len;
127 if (!mActive) {
128 mActive = true;
129 }
130 if (mMaxLatency < len + mSlotSize) {
131 mMaxLatency = len + mSlotSize;
132 }
133 if (0 < lostLen) {
134 processPacketLoss(lostLen);
135 }
136 mSkewRaw += mReadsNew - len;
137 mReadsNew = 0;
138 mUnderruns += mUnderrunsNew;
139 mUnderrunsNew = 0;
140 mLevel = mSlotSize*std::ceil(mLevelCur/mSlotSize);
141
142 // Update positions if necessary
143 int32_t available = mWritePosition - mReadPosition;
144
145 int delta = 0;
146 if (available < -10*mMaxLatency) {
147 delta = available;
148 mBufIncUnderrun += -delta;
149 mLevelCur = len;
150 //cout << "reset" << endl;
151 }
152 else if (available + len > mMaxLatency) {
153 delta = mOverflowDropStep;
154 mOverflows += delta;
155 mBufDecOverflow += delta;
156 mLevelCur = mMaxLatency;
157 }
158 else if (0 > available &&
159 mLevelCur < std::max(mInSlotSize + mMinLevelThreshold,
160 mMaxLatency - mUnderrunIncTolerance - 2*mSlotSize*lastCorrFactor())) {
161 delta = -std::min(-available, mSlotSize);
162 mBufIncUnderrun += -delta;
163 }
164 else if (mLevelCur < mMaxLatency - mCorrIncTolerance - 6*mSlotSize*lastCorrFactor()) {
165 delta = -mSlotSize;
166 mUnderruns += -delta;
167 mBufIncCompensate += -delta;
168 }
169
170 if (0 != delta) {
171 mReadPosition += delta;
172 mLastCorrCounter = 0;
173 mLastCorrDirection = 0 < delta ? 1 : -1;
174 }
175 else {
176 ++mLastCorrCounter;
177 }
178
179 int wpos = mWritePosition % mTotalSize;
180 int n = std::min(mTotalSize - wpos, len);
181 std::memcpy(mRingBuffer+wpos, ptrToSlot, n);
182 if (n < len) {
183 //cout << "split write: " << len << "-" << n << endl;
184 std::memcpy(mRingBuffer, ptrToSlot+n, len-n);
185 }
186 mWritePosition += len;
187
188 return true;
189 }
190
191 //*******************************************************************************
192 void JitterBuffer::readSlotNonBlocking(int8_t* ptrToReadSlot)
193 {
194 int len = mSlotSize;
195 QMutexLocker locker(&mMutex);
196 if (!mActive) {
197 std::memset(ptrToReadSlot, 0, len);
198 return;
199 }
200 mReadsNew += len;
201 int32_t available = mWritePosition - mReadPosition;
202 if (available < mLevelCur) {
203 mLevelCur = std::max((double)available, mLevelCur-mLevelDownRate);
204 }
205 else {
206 mLevelCur = available;
207 }
208
209 // auto queue correction
210 if (0 > available + mAutoQueueCorr - mLevelCur) {
211 mAutoQueueCorr += mAutoQRate;
212 }
213 else if (mInSlotSize + mSlotSize < mAutoQueueCorr) {
214 mAutoQueueCorr -= mAutoQRate * mAutoQFactor;
215 }
216 if (mAutoQRate > mAutoQRateMin) {
217 mAutoQRate *= mAutoQRateDecay;
218 }
219 if (0 != mAutoQueue) {
220 int PPS = mSampleRate / mFPP;
221 if (2*PPS == mAutoQueue++ % (4*PPS)) {
222 double k = 1.0 + 1e-5/mAutoQFactor;
223 if (12*PPS > mAutoQueue ||
224 std::abs(mAutoQueueCorr*k - mMaxLatency + mSlotSize/2) > 0.6*mSlotSize) {
225 mMaxLatency = mSlotSize * std::ceil(mAutoQueueCorr*k/mSlotSize);
226 cout << "AutoQueue: " << mMaxLatency / mSlotSize << endl;
227 }
228 }
229 }
230
231 int read_len = qBound(0, available, len);
232 int rpos = mReadPosition % mTotalSize;
233 int n = std::min(mTotalSize - rpos, read_len);
234 std::memcpy(ptrToReadSlot, mRingBuffer+rpos, n);
235 if (n < read_len) {
236 //cout << "split read: " << read_len << "-" << n << endl;
237 std::memcpy(ptrToReadSlot+n, mRingBuffer, read_len-n);
238 }
239 if (read_len < len) {
240 std::memset(ptrToReadSlot+read_len, 0, len-read_len);
241 mUnderrunsNew += len-read_len;
242 }
243 mReadPosition += len;
244 }
245
246 //*******************************************************************************
247 void JitterBuffer::readBroadcastSlot(int8_t* ptrToReadSlot)
248 {
249 int len = mSlotSize;
250 QMutexLocker locker(&mMutex);
251 if (mBroadcastLatency + len > mReadPosition) {
252 std::memset(ptrToReadSlot, 0, len);
253 return;
254 }
255 // latency correction
256 int32_t d = mReadPosition - mBroadcastLatency - mBroadcastPosition - len;
257 if (std::abs(d) > mBroadcastLatency / 2) {
258 mBroadcastPosition = mReadPosition - mBroadcastLatency - len;
259 mBroadcastPositionCorr = 0.0;
260 mBroadcastSkew += d / mMinStepSize;
261 }
262 else {
263 mBroadcastPositionCorr += 0.0003 * d;
264 int delta = mBroadcastPositionCorr / mMinStepSize;
265 if (0 != delta) {
266 mBroadcastPositionCorr -= delta * mMinStepSize;
267 if (2 == mAudioBitRes && (int32_t)(mWritePosition - mBroadcastPosition) > len) {
268 // interpolate
269 len += delta * mMinStepSize;
270 }
271 else {
272 // skip
273 mBroadcastPosition += delta * mMinStepSize;
274 }
275 mBroadcastSkew += delta;
276 }
277 }
278 mBroadcastDelta = d / mMinStepSize;
279 int32_t available = mWritePosition - mBroadcastPosition;
280 int read_len = qBound(0, available, len);
281 if (len == mSlotSize) {
282 int rpos = mBroadcastPosition % mTotalSize;
283 int n = std::min(mTotalSize - rpos, read_len);
284 std::memcpy(ptrToReadSlot, mRingBuffer+rpos, n);
285 if (n < read_len) {
286 //cout << "split read: " << read_len << "-" << n << endl;
287 std::memcpy(ptrToReadSlot+n, mRingBuffer, read_len-n);
288 }
289 if (read_len < len) {
290 std::memset(ptrToReadSlot+read_len, 0, len-read_len);
291 }
292 }
293 else {
294 // interpolation len => mSlotSize
295 double K = 1.0 * len / mSlotSize;
296 for (int c=0; c < mMinStepSize; c+=sizeof(int16_t)) {
297 for (int j=0; j < mSlotSize/mMinStepSize; ++j) {
298 int j1 = std::floor(j*K);
299 double a = j*K - j1;
300 int rpos = (mBroadcastPosition + j1*mMinStepSize + c) % mTotalSize;
301 int16_t v1 = *(int16_t*)(mRingBuffer + rpos);
302 rpos = (rpos + mMinStepSize) % mTotalSize;
303 int16_t v2 = *(int16_t*)(mRingBuffer + rpos);
304 *(int16_t*)(ptrToReadSlot + j*mMinStepSize + c) = std::round((1-a)*v1 + a*v2);
305 }
306 }
307 }
308 mBroadcastPosition += len;
309 }
310
311
312 //*******************************************************************************
313 void JitterBuffer::processPacketLoss(int lostLen)
314 {
315 mSkewRaw -= lostLen;
316
317 int32_t available = mWritePosition - mReadPosition;
318 int delta = std::min(available + mInSlotSize + lostLen - mMaxLatency, lostLen);
319 if (0 < delta) {
320 lostLen -= delta;
321 mBufDecPktLoss += delta;
322 mLevelCur = mMaxLatency;
323 mLastCorrCounter = 0;
324 mLastCorrDirection = 1;
325 }
326 else if (mSlotSize < available + lostLen && (
327 mOverflowDecTolerance > mMaxLatency // for strategies 0,1
328 || (0 < mLastCorrDirection && mLevelCur >
329 mMaxLatency - mOverflowDecTolerance*(1.1 - lastCorrFactor()))
330 )) {
331 delta = std::min(lostLen, mSlotSize);
332 lostLen -= delta;
333 mBufDecPktLoss += delta;
334 mLevelCur -= delta;
335 mLastCorrCounter = 0;
336 mLastCorrDirection = 1;
337 }
338 if (lostLen >= mTotalSize) {
339 std::memset(mRingBuffer, 0, mTotalSize);
340 mUnderruns += std::max(0, lostLen - std::max(0, -available));
341 }
342 else if (0 < lostLen) {
343 int wpos = mWritePosition % mTotalSize;
344 int n = std::min(mTotalSize - wpos, lostLen);
345 std::memset(mRingBuffer+wpos, 0, n);
346 if (n < lostLen) {
347 //cout << "split write: " << lostLen << "-" << n << endl;
348 std::memset(mRingBuffer, 0, lostLen-n);
349 }
350 mUnderruns += std::max(0, lostLen - std::max(0, -available));
351 }
352 mWritePosition += lostLen;
353 }
354
355 //*******************************************************************************
356 bool JitterBuffer::getStats(RingBuffer::IOStat* stat, bool reset)
357 {
358 QMutexLocker locker(&mMutex);
359 if (reset) {
360 mUnderruns = 0;
361 mOverflows = 0;
362 mSkew0 = mLevel;
363 mSkewRaw = 0;
364 mBufDecOverflow = 0;
365 mBufDecPktLoss = 0;
366 mBufIncUnderrun = 0;
367 mBufIncCompensate = 0;
368 mBroadcastSkew = 0;
369 }
370 stat->underruns = mUnderruns / mStatUnit;
371 stat->overflows = mOverflows / mStatUnit;
372 stat->skew = (int32_t)((mSkew0 - mLevel + mBufIncUnderrun + mBufIncCompensate
373 - mBufDecOverflow - mBufDecPktLoss)) / mStatUnit;
374 stat->skew_raw = mSkewRaw / mStatUnit;
375 stat->level = mLevel / mStatUnit;
376
377 stat->buf_dec_overflows = mBufDecOverflow / mStatUnit;
378 stat->buf_dec_pktloss = mBufDecPktLoss / mStatUnit;
379 stat->buf_inc_underrun = mBufIncUnderrun / mStatUnit;
380 stat->buf_inc_compensate = mBufIncCompensate / mStatUnit;
381 stat->broadcast_skew = mBroadcastSkew;
382 stat->broadcast_delta = mBroadcastDelta;
383
384 stat->autoq_corr = mAutoQueueCorr / mStatUnit * 10;
385 stat->autoq_rate = mAutoQRate / mStatUnit * 1000;
386 return true;
387 }
388
0 //*****************************************************************
1 /*
2 JackTrip: A System for High-Quality Audio Network Performance
3 over the Internet
4
5 Copyright (c) 2020 Juan-Pablo Caceres, Chris Chafe.
6 SoundWIRE group at CCRMA, Stanford University.
7
8 Permission is hereby granted, free of charge, to any person
9 obtaining a copy of this software and associated documentation
10 files (the "Software"), to deal in the Software without
11 restriction, including without limitation the rights to use,
12 copy, modify, merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom the
14 Software is furnished to do so, subject to the following
15 conditions:
16
17 The above copyright notice and this permission notice shall be
18 included in all copies or substantial portions of the Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 OTHER DEALINGS IN THE SOFTWARE.
28 */
29 //*****************************************************************
30
31 /**
32 * \file JitterBuffer.h
33 * \author Anton Runov
34 * \date June 2020
35 */
36
37 #ifndef __JITTERBUFFER_H__
38 #define __JITTERBUFFER_H__
39
40 #include "RingBuffer.h"
41
42 class JitterBuffer : public RingBuffer
43 {
44 public:
45 JitterBuffer(int buf_samples, int qlen, int sample_rate, int strategy,
46 int bcast_qlen, int channels, int bit_res);
47 virtual ~JitterBuffer() {}
48
49 virtual bool insertSlotNonBlocking(const int8_t* ptrToSlot, int len, int lostLen);
50 virtual void readSlotNonBlocking(int8_t* ptrToReadSlot);
51 virtual void readBroadcastSlot(int8_t* ptrToReadSlot);
52
53 virtual bool getStats(IOStat* stat, bool reset);
54
55 protected:
56 void processPacketLoss(int lostLen);
57
58 protected:
59 int mMaxLatency;
60 int mNumChannels;
61 int mAudioBitRes;
62 int mMinStepSize;
63 int mFPP;
64 int mSampleRate;
65 int mInSlotSize;
66 bool mActive;
67 uint32_t mBroadcastLatency;
68 uint32_t mBroadcastPosition;
69 double mBroadcastPositionCorr;
70
71 double mUnderrunIncTolerance;
72 double mCorrIncTolerance;
73 double mOverflowDecTolerance;
74 int mOverflowDropStep;
75 uint32_t mLastCorrCounter;
76 int mLastCorrDirection;
77 double mMinLevelThreshold;
78 double lastCorrFactor() const {return 500.0 / std::max(500U, mLastCorrCounter);}
79
80 int mAutoQueue;
81 double mAutoQueueCorr;
82 double mAutoQFactor;
83 double mAutoQRate;
84 double mAutoQRateMin;
85 double mAutoQRateDecay;
86 };
87
88
89 #endif //__JITTERBUFFER_H__
0 //*****************************************************************
1 /*
2 JackTrip: A System for High-Quality Audio Network Performance
3 over the Internet
4
5 Copyright (c) 2020 Julius Smith, Juan-Pablo Caceres, Chris Chafe.
6 SoundWIRE group at CCRMA, Stanford University.
7
8 Permission is hereby granted, free of charge, to any person
9 obtaining a copy of this software and associated documentation
10 files (the "Software"), to deal in the Software without
11 restriction, including without limitation the rights to use,
12 copy, modify, merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom the
14 Software is furnished to do so, subject to the following
15 conditions:
16
17 The above copyright notice and this permission notice shall be
18 included in all copies or substantial portions of the Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 OTHER DEALINGS IN THE SOFTWARE.
28 */
29 //*****************************************************************
30
31 /**
32 * \file Limiter.cpp
33 * \author Julius Smith, based on LoopBack.h
34 * \date May-Nov 2020
35 * \license MIT
36 */
37
38 #include "Limiter.h"
39 #include "jacktrip_types.h"
40
41 #include <iostream>
42
43 //*******************************************************************************
44 void Limiter::compute(int nframes, float** inputs, float** outputs)
45 {
46 if (not inited) {
47 std::cerr << "*** Limiter " << this << ": init never called! Doing it now.\n";
48 if (fSamplingFreq <= 0) {
49 fSamplingFreq = 48000;
50 std::cout << "Limiter " << this << ": *** HAD TO GUESS the sampling rate (chose 48000 Hz) ***\n";
51 }
52 init(fSamplingFreq);
53 }
54 #ifdef SINE_TEST
55 float sineTestOut[nframes];
56 float* faustSigs[1] { sineTestOut };
57 #endif
58 for ( int i = 0; i < mNumChannels; i++ ) {
59 if (warningAmp > 0.0) {
60 checkAmplitudes(nframes, inputs[i]); // we presently do one check across all channels
61 }
62 limiterP[i]->compute(nframes, &inputs[i], &outputs[i]);
63 #ifdef SINE_TEST
64 limiterTestP[i]->compute(nframes, faustSigs, faustSigs);
65 for ( int n = 0; n < nframes; n++ ) {
66 outputs[i][n] = outputs[i][n] + sineTestOut[n];
67 }
68 #endif
69 }
70 }
0 //*****************************************************************
1 /*
2 JackTrip: A System for High-Quality Audio Network Performance
3 over the Internet
4
5 Copyright (c) 2020 Julius Smith, Juan-Pablo Caceres, Chris Chafe.
6 SoundWIRE group at CCRMA, Stanford University.
7
8 Permission is hereby granted, free of charge, to any person
9 obtaining a copy of this software and associated documentation
10 files (the "Software"), to deal in the Software without
11 restriction, including without limitation the rights to use,
12 copy, modify, merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom the
14 Software is furnished to do so, subject to the following
15 conditions:
16
17 The above copyright notice and this permission notice shall be
18 included in all copies or substantial portions of the Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 OTHER DEALINGS IN THE SOFTWARE.
28 */
29 //*****************************************************************
30
31 /**
32 * \file Limiter.h
33 * \author Julius Smith, based on LoopBack.h
34 * \date May-Nov 2020
35 * \license MIT
36 */
37
38 /** \brief Applies limiter_lad_mono from the faustlibraries distribution, compressors.lib
39 *
40 */
41 #ifndef __LIMITER_H__
42 #define __LIMITER_H__
43
44 //#define SINE_TEST
45
46 #ifdef SINE_TEST
47 #include "limitertest.h"
48 #endif
49
50 #include "ProcessPlugin.h"
51 #include "limiterdsp.h"
52 #include <vector>
53 #include "assert.h"
54
55 /** \brief The Limiter class confines the output dynamic range to a
56 * "dynamic range lane" determined by the assumed number of clients.
57 */
58 class Limiter : public ProcessPlugin
59 {
60 public:
61 /// \brief The class constructor sets the number of channels to limit
62 Limiter(int numchans, int numclients, bool verboseFlag = false) // xtor
63 : mNumChannels(numchans), mNumClients(numclients)
64 , warningAmp(0.0), warnCount(0), peakMagnitude(0.0), nextWarning(1)
65 {
66 setVerbose(verboseFlag);
67 for ( int i = 0; i < mNumChannels; i++ ) {
68 limiterP.push_back(new limiterdsp);
69 limiterUIP.push_back(new APIUI); // #included in limiterdsp.h
70 limiterP[i]->buildUserInterface(limiterUIP[i]);
71 #ifdef SINE_TEST
72 limiterTestP.push_back(new limitertest);
73 limiterTestUIP.push_back(new APIUI); // #included in limitertest.h
74 limiterTestP[i]->buildUserInterface(limiterTestUIP[i]);
75 #endif
76 }
77 // std::cout << "Limiter: constructed for "
78 // << mNumChannels << " channels and "
79 // << mNumClients << " assumed clients\n";
80 }
81
82 /// \brief The class destructor
83 virtual ~Limiter() {
84 for ( int i = 0; i < mNumChannels; i++ ) {
85 delete limiterP[i];
86 delete limiterUIP[i];
87 }
88 limiterP.clear();
89 limiterUIP.clear();
90 }
91
92 void init(int samplingRate) override {
93 ProcessPlugin::init(samplingRate);
94 if (samplingRate != fSamplingFreq) {
95 std::cerr << "Sampling rate not set by superclass!\n";
96 std::exit(1); }
97 fs = float(fSamplingFreq);
98 for ( int i = 0; i < mNumChannels; i++ ) {
99 limiterP[i]->init(fs); // compression filter parameters depend on sampling rate
100 int ndx = limiterUIP[i]->getParamIndex("NumClientsAssumed");
101 limiterUIP[i]->setParamValue(ndx, mNumClients);
102 #ifdef SINE_TEST
103 limiterTestP[i]->init(fs); // oscillator parameters depend on sampling rate
104 ndx = limiterTestUIP[i]->getParamIndex("Amp");
105 limiterTestUIP[i]->setParamValue(ndx, 0.2);
106 ndx = limiterTestUIP[i]->getParamIndex("Freq");
107 float sineFreq = 110.0 * pow(1.5,double(i)) * (mNumClients>1?1.25:1.0); // Maj 7 chord for stereo in & out
108 limiterTestUIP[i]->setParamValue(ndx, sineFreq);
109 #endif
110 }
111 inited = true;
112 }
113 int getNumInputs() override { return(mNumChannels); }
114 int getNumOutputs() override { return(mNumChannels); }
115 void compute(int nframes, float** inputs, float** outputs) override;
116
117 void setWarningAmplitude(double wa) { // setting to 0 turns off warnings
118 warningAmp = std::max(0.0,std::min(1.0,wa));
119 }
120
121 private:
122
123 void checkAmplitudes(int nframes, float* buf) {
124 const int maxWarningInterval { 10000 }; // this could become an option
125 assert(warningAmp > 0.0);
126 assert(mNumClients > 0);
127 for (int i=0; i<nframes; i++) {
128 double tmp_sample = double(buf[i]);
129 double limiterAmp = fabs(tmp_sample)/sqrt(double(mNumClients)); // KEEP IN SYNC with gain in ../faust-src/limiterdsp.dsp
130 if (limiterAmp >= warningAmp) {
131 warnCount++;
132 peakMagnitude = std::max(peakMagnitude,limiterAmp);
133 if (warnCount==nextWarning) {
134 double peakMagnitudeDB = 20.0 * std::log10(peakMagnitude);
135 double warningAmpDB = 20.0 * std::log10(warningAmp);
136 if (warnCount==1) {
137 if (warningAmp == 1.0) {
138 std::cerr << "*** Limiter.cpp: Audio HARD-CLIPPED!\n";
139 fprintf(stderr, "\tReduce your audio input level(s) by %0.1f dB to avoid this.\n", peakMagnitudeDB);
140 } else {
141 fprintf(stderr,
142 "*** Limiter.cpp: Amplitude levels must stay below %0.1f dBFS to avoid compression.\n",
143 warningAmpDB);
144 fprintf(stderr, "\tReduce input level(s) by %0.1f dB to achieve this.\n",
145 peakMagnitudeDB-warningAmpDB);
146 }
147 } else {
148 fprintf(stderr, "\tReduce audio input level(s) by %0.1f dB to avoid limiter compression distortion.\n",
149 peakMagnitudeDB-warningAmpDB);
150 }
151 peakMagnitude = 0.0; // reset for next group measurement
152 if (nextWarning < maxWarningInterval) { // don't let it stop reporting for too long
153 nextWarning *= 10;
154 } else {
155 warnCount=0;
156 }
157 } // warnCount==nextWarning
158 } // above warningAmp
159 } // loop over frames
160 } // checkAmplitudes()
161
162 private:
163 float fs;
164 int mNumChannels;
165 int mNumClients;
166 std::vector<limiterdsp*> limiterP;
167 std::vector<APIUI*> limiterUIP;
168 #ifdef SINE_TEST
169 std::vector<limitertest*> limiterTestP;
170 std::vector<APIUI*> limiterTestUIP;
171 #endif
172 double warningAmp;
173 uint32_t warnCount;
174 double peakMagnitude;
175 uint32_t nextWarning;
176 };
177
178 #endif
132132 // Check Buffer Size
133133 if ( peer_header->BufferSize != mHeader.BufferSize )
134134 {
135 std::cerr << "ERROR: Peer Buffer Size is : " << peer_header->BufferSize << endl;
136 std::cerr << " Local Buffer Size is : " << mHeader.BufferSize << endl;
137 std::cerr << "Make sure both machines use same buffer size" << endl;
138 std::cerr << gPrintSeparator << endl;
139 error = true;
135 std::cerr << "WARNING: Peer Buffer Size is : " << peer_header->BufferSize << endl;
136 std::cerr << " Local Buffer Size is : " << mHeader.BufferSize << endl;
137 //std::cerr << "Make sure both machines use same buffer size" << endl;
138 //std::cerr << gPrintSeparator << endl;
139 //error = true;
140140 }
141141
142142 // Check Sampling Rate
164164
165165
166166 signals:
167 void signalError(const char* error_message);
167 void signalError(const QString &error_message);
168168
169169
170170 private:
6464
6565 //virtual void buildUserInterface(UI* interface) = 0;
6666
67 virtual char* getName() {
68 char* pluginName { const_cast<char*>(typeid(*this).name()) }; // get name of DERIVED class
69 while (isdigit(*pluginName)) { pluginName++; }
70 return pluginName;
71 }
72
6773 /** \brief Do proper Initialization of members and class instances. By default this
6874 * initializes the Sampling Frequency. If a class instance depends on the
6975 * sampling frequency, it should be initialize here.
7076 */
71 virtual void init(int samplingRate) { fSamplingFreq = samplingRate; };
77 virtual void init(int samplingRate) {
78 fSamplingFreq = samplingRate;
79 if (verbose) {
80 char* derivedClassName = getName();
81 printf("%s: init(%d)\n",derivedClassName,samplingRate);
82 }
83 }
84 virtual bool getInited() { return inited; }
85 virtual void setVerbose(bool v) { verbose = v; }
7286
7387 /// \brief Compute process
7488 virtual void compute(int nframes, float** inputs, float** outputs) = 0;
7589
7690 protected:
7791 int fSamplingFreq; ///< Faust Data member, Sampling Rate
92 bool inited = false;
93 bool verbose = false;
7894 };
7995
8096 #endif
0 //*****************************************************************
1 /*
2 JackTrip: A System for High-Quality Audio Network Performance
3 over the Internet
4
5 Copyright (c) 2020 Julius Smith, Juan-Pablo Caceres, Chris Chafe.
6 SoundWIRE group at CCRMA, Stanford University.
7
8 Permission is hereby granted, free of charge, to any person
9 obtaining a copy of this software and associated documentation
10 files (the "Software"), to deal in the Software without
11 restriction, including without limitation the rights to use,
12 copy, modify, merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom the
14 Software is furnished to do so, subject to the following
15 conditions:
16
17 The above copyright notice and this permission notice shall be
18 included in all copies or substantial portions of the Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 OTHER DEALINGS IN THE SOFTWARE.
28 */
29 //*****************************************************************
30
31 /**
32 * \file Reverb.cpp
33 * \author Julius Smith, based on Limiter.h
34 * \date August 2020
35 */
36
37
38 #include "Reverb.h"
39 #include "jacktrip_types.h"
40
41 #include <iostream>
42
43 //*******************************************************************************
44 void Reverb::compute(int nframes, float** inputs, float** outputs)
45 {
46 if (not inited) {
47 std::cerr << "*** Reverb " << this << ": init never called! Doing it now.\n";
48 if (fSamplingFreq <= 0) {
49 fSamplingFreq = 48000;
50 std::cout << "Reverb " << this << ": *** HAD TO GUESS the sampling rate (chose 48000 Hz) ***\n";
51 }
52 init(fSamplingFreq);
53 }
54 if (mReverbLevel <= 1.0) {
55 if (mNumInChannels == 1) {
56 freeverbMonoP->compute(nframes, inputs, outputs);
57 } else {
58 assert(mNumInChannels == 2);
59 freeverbStereoP->compute(nframes, inputs, outputs);
60 }
61 } else {
62 if (mNumInChannels == 1) {
63 zitarevMonoP->compute(nframes, inputs, outputs);
64 } else {
65 assert(mNumInChannels == 2);
66 zitarevStereoP->compute(nframes, inputs, outputs);
67 }
68 }
69 }
0 //*****************************************************************
1 /*
2 JackTrip: A System for High-Quality Audio Network Performance
3 over the Internet
4
5 Copyright (c) 2020 Julius Smith, Juan-Pablo Caceres, Chris Chafe.
6 SoundWIRE group at CCRMA, Stanford University.
7
8 Permission is hereby granted, free of charge, to any person
9 obtaining a copy of this software and associated documentation
10 files (the "Software"), to deal in the Software without
11 restriction, including without limitation the rights to use,
12 copy, modify, merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom the
14 Software is furnished to do so, subject to the following
15 conditions:
16
17 The above copyright notice and this permission notice shall be
18 included in all copies or substantial portions of the Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 OTHER DEALINGS IN THE SOFTWARE.
28 */
29 //*****************************************************************
30
31 /**
32 * \file Reverb.h
33 * \author Julius Smith, based on Limiter.h
34 * \date August 2020
35 */
36
37
38 /** \brief Applies freeverb or zitarev from the faustlibraries distribution: reverbs.lib
39 *
40 */
41 #ifndef __REVERB_H__
42 #define __REVERB_H__
43
44 //#define SINE_TEST
45
46 #include "ProcessPlugin.h"
47 #include "freeverbdsp.h" // stereo in and out
48 #include "freeverbmonodsp.h" // mono in and out (there is no mono to stereo case in jacktrip as yet)
49 #include "zitarevdsp.h" // stereo in and out
50 #include "zitarevmonodsp.h" // mono in and out
51
52 /** \brief A Reverb is an echo-based delay effect,
53 * providing a virtual acoustic listening space.
54 */
55 class Reverb : public ProcessPlugin
56 {
57 public:
58 /// \brief The class constructor sets the number of channels to limit
59 Reverb(int numInChans, int numOutChans, float reverbLevel = 1.0, bool verboseFlag = false) // xtor
60 : mNumInChannels(numInChans), mNumOutChannels(numOutChans), mReverbLevel(reverbLevel)
61 {
62 setVerbose(verboseFlag);
63 if ( mNumInChannels < 1 ) {
64 std::cerr << "*** Reverb.h: must have at least one input audio channels\n";
65 mNumInChannels = 1;
66 }
67 if ( mNumInChannels > 2 ) {
68 std::cerr << "*** Reverb.h: limiting number of audio output channels to 2\n";
69 mNumInChannels = 2;
70 }
71 #if 0
72 std::cout << "Reverb: constructed for "
73 << mNumInChannels << " input channels and "
74 << mNumOutChannels << " output channels with reverb level = "
75 << mReverbLevel << "\n";
76 #endif
77
78 if (mReverbLevel <= 1.0) { // freeverb:
79 freeverbStereoP = new freeverbdsp; // stereo input and output
80 freeverbMonoP = new freeverbmonodsp; // mono input, stereo output
81 freeverbStereoUIP = new APIUI; // #included in *dsp.h
82 freeverbMonoUIP = new APIUI;
83 freeverbStereoP->buildUserInterface(freeverbStereoUIP);
84 freeverbMonoP->buildUserInterface(freeverbMonoUIP);
85 // std::cout << "Using freeverb\n";
86 } else {
87 zitarevStereoP = new zitarevdsp; // stereo input and output
88 zitarevMonoP = new zitarevmonodsp; // mono input, stereo output
89 zitarevStereoUIP = new APIUI;
90 zitarevMonoUIP = new APIUI;
91 zitarevStereoP->buildUserInterface(zitarevStereoUIP);
92 zitarevMonoP->buildUserInterface(zitarevMonoUIP);
93 // std::cout << "Using zitarev\n";
94 }
95 }
96
97 /// \brief The class destructor
98 virtual ~Reverb() {
99 if (mReverbLevel <= 1.0) { // freeverb:
100 delete freeverbStereoP;
101 delete freeverbMonoP;
102 delete freeverbStereoUIP;
103 delete freeverbMonoUIP;
104 } else {
105 delete zitarevStereoP;
106 delete zitarevMonoP;
107 delete zitarevStereoUIP;
108 delete zitarevMonoUIP;
109 }
110 }
111
112 void init(int samplingRate) override {
113 ProcessPlugin::init(samplingRate);
114 // std::cout << "Reverb: init(" << samplingRate << ")\n";
115 if (samplingRate != fSamplingFreq) {
116 std::cerr << "Sampling rate not set by superclass!\n";
117 std::exit(1); }
118 fs = float(fSamplingFreq);
119 if (mReverbLevel <= 1.0) { // freeverb:
120 freeverbStereoP->init(fs); // compression filter parameters depend on sampling rate
121 freeverbMonoP->init(fs); // compression filter parameters depend on sampling rate
122 int ndx = freeverbStereoUIP->getParamIndex("Wet");
123 freeverbStereoUIP->setParamValue(ndx, mReverbLevel);
124 freeverbMonoUIP->setParamValue(ndx, mReverbLevel);
125 } else { // zitarev:
126 zitarevStereoP->init(fs); // compression filter parameters depend on sampling rate
127 zitarevMonoP->init(fs); // compression filter parameters depend on sampling rate
128 int ndx = zitarevStereoUIP->getParamIndex("Wet");
129 float zitaLevel = mReverbLevel-1.0f; // range within zitarev is 0 to 1 (our version only)
130 zitarevStereoUIP->setParamValue(ndx, zitaLevel);
131 zitarevMonoUIP->setParamValue(ndx, zitaLevel);
132 }
133 inited = true;
134 }
135 int getNumInputs() override { return(mNumInChannels); }
136 int getNumOutputs() override { return(mNumOutChannels); }
137 void compute(int nframes, float** inputs, float** outputs) override;
138
139 private:
140 float fs;
141 int mNumInChannels;
142 int mNumOutChannels;
143
144 float mReverbLevel;
145
146 freeverbdsp* freeverbStereoP;
147 freeverbmonodsp* freeverbMonoP;
148 APIUI* freeverbStereoUIP;
149 APIUI* freeverbMonoUIP;
150
151 zitarevdsp* zitarevStereoP;
152 zitarevmonodsp* zitarevMonoP;
153 APIUI* zitarevStereoUIP;
154 APIUI* zitarevMonoUIP;
155 };
156
157 #endif
4141 #include <cstring>
4242 #include <cstdlib>
4343 #include <stdexcept>
44 #include <cmath>
45 #include "JackTrip.h"
4446
4547 using std::cout; using std::endl;
4648
5355 mReadPosition(0),
5456 mWritePosition(0),
5557 mFullSlots(0),
56 mRingBuffer(new int8_t[mTotalSize]),
57 mLastReadSlot(new int8_t[mSlotSize])
58 {
59 //QMutexLocker locker(&mMutex); // lock the mutex
60
61 // Verify if there's enough space to for the buffers
62 if ( (mRingBuffer == NULL) || (mLastReadSlot == NULL) ) {
63 //std::cerr << "ERROR: RingBuffer out of memory!" << endl;
64 //std::cerr << "Exiting program..." << endl;
65 //std::exit(1);
66 throw std::length_error("RingBuffer out of memory!");
67 }
68
69 // Set the buffers to zeros
70 /*
71 for (int i=0; i<mTotalSize; i++) {
72 mRingBuffer[i] = 0; // Initialize all elements to zero.
73 }
74 */
75 std::memset(mRingBuffer, 0, mTotalSize); // set buffer to 0
76 /*
77 for (int i=0; i<mSlotSize; i++) {
78 mLastReadSlot[i] = 0; // Initialize all elements to zero.
79 }
80 */
81 std::memset(mLastReadSlot, 0, mSlotSize); // set buffer to 0
82
58 mRingBuffer(NULL),
59 mLastReadSlot(NULL)
60 {
61 if (0 < mTotalSize) {
62 mRingBuffer = new int8_t[mTotalSize];
63 mLastReadSlot = new int8_t[mSlotSize];
64 //QMutexLocker locker(&mMutex); // lock the mutex
65
66 // Verify if there's enough space to for the buffers
67 if ( (mRingBuffer == NULL) || (mLastReadSlot == NULL) ) {
68 //std::cerr << "ERROR: RingBuffer out of memory!" << endl;
69 //std::cerr << "Exiting program..." << endl;
70 //std::exit(1);
71 throw std::length_error("RingBuffer out of memory!");
72 }
73
74 // Set the buffers to zeros
75 /*
76 for (int i=0; i<mTotalSize; i++) {
77 mRingBuffer[i] = 0; // Initialize all elements to zero.
78 }
79 */
80 std::memset(mRingBuffer, 0, mTotalSize); // set buffer to 0
81 /*
82 for (int i=0; i<mSlotSize; i++) {
83 mLastReadSlot[i] = 0; // Initialize all elements to zero.
84 }
85 */
86 std::memset(mLastReadSlot, 0, mSlotSize); // set buffer to 0
87 mWritePosition = ( (NumSlots/2) * SlotSize ) % mTotalSize;
88 }
8389
8490 // Advance write position to half of the RingBuffer
85 mWritePosition = ( (NumSlots/2) * SlotSize ) % mTotalSize;
8691 // Udpate Full Slots accordingly
8792 mFullSlots = (NumSlots/2);
93 mLevelDownRate = 0.01;
94 mStatUnit = 1;
8895 mUnderruns = 0;
8996 mOverflows = 0;
97 mSkew0 = 0;
98 mSkewRaw = 0;
99 mLevelCur = mFullSlots;
100 mLevel = mLevelCur;
101 mBufDecOverflow = 0;
102 mBufDecPktLoss = 0;
103 mBufIncUnderrun = 0;
104 mBufIncCompensate = 0;
105 mBroadcastSkew = 0;
106 mBroadcastDelta = 0;
90107 }
91108
92109
104121 void RingBuffer::insertSlotBlocking(const int8_t* ptrToSlot)
105122 {
106123 QMutexLocker locker(&mMutex); // lock the mutex
124 updateReadStats();
107125
108126 // Check if there is space available to write a slot
109127 // If the Ringbuffer is full, it waits for the bufferIsNotFull condition
126144 void RingBuffer::readSlotBlocking(int8_t* ptrToReadSlot)
127145 {
128146 QMutexLocker locker(&mMutex); // lock the mutex
147 ++mReadsNew;
129148
130149 // Check if there are slots available to read
131150 // If the Ringbuffer is empty, it waits for the bufferIsNotEmpty condition
132151 while (mFullSlots == 0) {
133152 //std::cerr << "READ UNDER-RUN BLOCKING before" << endl;
134 mBufferIsNotEmpty.wait(&mMutex);
153 mBufferIsNotEmpty.wait(&mMutex, 200);
154 if (JackTrip::sJackStopped) {
155 return;
156 }
135157 }
136158
137159 // Copy mSlotSize bytes to ReadSlot
147169
148170
149171 //*******************************************************************************
150 void RingBuffer::insertSlotNonBlocking(const int8_t* ptrToSlot)
151 {
172 bool RingBuffer::insertSlotNonBlocking(const int8_t* ptrToSlot, int len, int lostLen)
173 {
174 if (len != mSlotSize && 0 != len) {
175 // RingBuffer does not suppport mixed buf sizes
176 return false;
177 }
152178 QMutexLocker locker(&mMutex); // lock the mutex
179 if (0 < lostLen) {
180 int lostCount = lostLen / mSlotSize;
181 mBufDecPktLoss += lostCount;
182 mSkewRaw -= lostCount;
183 mLevelCur -= lostCount;
184 }
185 updateReadStats();
153186
154187 // Check if there is space available to write a slot
155188 // If the Ringbuffer is full, it returns without writing anything
159192 if (mFullSlots == mNumSlots) {
160193 //std::cout << "OUPUT OVERFLOW NON BLOCKING = " << mNumSlots << std::endl;
161194 overflowReset();
162 return;
195 return true;
163196 }
164197
165198 // Copy mSlotSize bytes to mRingBuffer
169202 mFullSlots++; //update full slots
170203 // Wake threads waitng for bufferIsNotFull condition
171204 mBufferIsNotEmpty.wakeAll();
205 return true;
172206 }
173207
174208
176210 void RingBuffer::readSlotNonBlocking(int8_t* ptrToReadSlot)
177211 {
178212 QMutexLocker locker(&mMutex); // lock the mutex
179
213 ++mReadsNew;
214 if (mFullSlots < mLevelCur) {
215 mLevelCur = std::max((double)mFullSlots, mLevelCur-mLevelDownRate);
216 }
217 else {
218 mLevelCur = mFullSlots;
219 }
180220
181221 // Check if there are slots available to read
182222 // If the Ringbuffer is empty, it returns a buffer of zeros and rests the buffer
183 if (mFullSlots == 0) {
223 if (mFullSlots <= 0) {
184224 // Returns a buffer of zeros if there's nothing to read
185225 //std::cerr << "READ UNDER-RUN NON BLOCKING = " << mNumSlots << endl;
186226 //std::memset(ptrToReadSlot, 0, mSlotSize);
202242
203243
204244 //*******************************************************************************
245 // Not supported in RingBuffer
246 void RingBuffer::readBroadcastSlot(int8_t* ptrToReadSlot)
247 {
248 std::memset(ptrToReadSlot, 0, mSlotSize);
249 }
250
251
252 //*******************************************************************************
205253 void RingBuffer::setUnderrunReadSlot(int8_t* ptrToReadSlot)
206254 {
207255 std::memset(ptrToReadSlot, 0, mSlotSize);
227275 //mFullSlots += mNumSlots/2;
228276 // There's nothing new to read, so we clear the whole buffer (Set the entire buffer to 0)
229277 std::memset(mRingBuffer, 0, mTotalSize);
230 ++mUnderruns;
278 ++mUnderrunsNew;
231279 }
232280
233281
237285 {
238286 // Advance the read pointer 1/2 the ring buffer
239287 //mReadPosition = ( mWritePosition + ( (mNumSlots/2) * mSlotSize ) ) % mTotalSize;
240 mReadPosition = ( mReadPosition + ( (mNumSlots/2) * mSlotSize ) ) % mTotalSize;
241 mFullSlots -= mNumSlots/2;
242 mOverflows += mNumSlots/2 + 1;
288 int d = mNumSlots / 2;
289 mReadPosition = ( mReadPosition + ( d * mSlotSize ) ) % mTotalSize;
290 mFullSlots -= d;
291 mOverflows += d + 1;
292 mBufDecOverflow += d + 1;
293 mLevelCur -= d;
243294 }
244295
245296
255306 //*******************************************************************************
256307 bool RingBuffer::getStats(RingBuffer::IOStat* stat, bool reset)
257308 {
309 QMutexLocker locker(&mMutex);
258310 if (reset) {
259311 mUnderruns = 0;
260312 mOverflows = 0;
261 }
262 stat->underruns = mUnderruns;
263 stat->overflows = mOverflows;
313 mSkew0 = mLevel;
314 mSkewRaw = 0;
315 mBufDecOverflow = 0;
316 mBufDecPktLoss = 0;
317 mBufIncUnderrun = 0;
318 mBufIncCompensate = 0;
319 mBroadcastSkew = 0;
320 }
321 stat->underruns = mUnderruns / mStatUnit;
322 stat->overflows = mOverflows / mStatUnit;
323 stat->skew = (int32_t)((mSkew0 - mLevel + mBufIncUnderrun + mBufIncCompensate
324 - mBufDecOverflow - mBufDecPktLoss)) / mStatUnit;
325 stat->skew_raw = mSkewRaw / mStatUnit;
326 stat->level = mLevel / mStatUnit;
327
328 stat->buf_dec_overflows = mBufDecOverflow / mStatUnit;
329 stat->buf_dec_pktloss = mBufDecPktLoss / mStatUnit;
330 stat->buf_inc_underrun = mBufIncUnderrun / mStatUnit;
331 stat->buf_inc_compensate = mBufIncCompensate / mStatUnit;
332 stat->broadcast_skew = mBroadcastSkew;
333 stat->broadcast_delta = mBroadcastDelta;
334
335 stat->autoq_corr = 0;
336 stat->autoq_rate = 0;
264337 return true;
265338 }
339
340 //*******************************************************************************
341 void RingBuffer::updateReadStats()
342 {
343 --mSkewRaw;
344 mSkewRaw += mReadsNew;
345 mReadsNew = 0;
346 mUnderruns += mUnderrunsNew;
347 mBufIncUnderrun += mUnderrunsNew;
348 mUnderrunsNew = 0;
349 mLevel = std::ceil(mLevelCur);
350 }
9494 /** \brief Same as insertSlotBlocking but non-blocking (asynchronous)
9595 * \param ptrToSlot Pointer to slot to insert into the RingBuffer
9696 */
97 void insertSlotNonBlocking(const int8_t* ptrToSlot);
97 virtual bool insertSlotNonBlocking(const int8_t* ptrToSlot, int len, int lostLen);
9898
9999 /** \brief Same as readSlotBlocking but non-blocking (asynchronous)
100100 * \param ptrToReadSlot Pointer to read slot from the RingBuffer
101101 */
102 void readSlotNonBlocking(int8_t* ptrToReadSlot);
102 virtual void readSlotNonBlocking(int8_t* ptrToReadSlot);
103 virtual void readBroadcastSlot(int8_t* ptrToReadSlot);
103104
104105 struct IOStat {
105106 uint32_t underruns;
106107 uint32_t overflows;
108 int32_t skew;
109 int32_t skew_raw;
110 int32_t level;
111 uint32_t buf_dec_overflows;
112 uint32_t buf_dec_pktloss;
113 uint32_t buf_inc_underrun;
114 uint32_t buf_inc_compensate;
115 int32_t broadcast_skew;
116 int32_t broadcast_delta;
117
118 int32_t autoq_corr;
119 int32_t autoq_rate;
107120 };
108121 virtual bool getStats(IOStat* stat, bool reset);
109122
123136 */
124137 virtual void setMemoryInReadSlotWithLastReadSlot(int8_t* ptrToReadSlot);
125138
126 private:
127
128139 /// \brief Resets the ring buffer for reads under-runs non-blocking
129140 void underrunReset();
130141 /// \brief Resets the ring buffer for writes over-flows non-blocking
131142 void overflowReset();
132143 /// \brief Helper method to debug, prints member variables to terminal
133144 void debugDump() const;
145 void updateReadStats();
134146
135 const int mSlotSize; ///< The size of one slot in byes
136 const int mNumSlots; ///< Number of Slots
137 const int mTotalSize; ///< Total size of the mRingBuffer = mSlotSize*mNumSlotss
138 int mReadPosition; ///< Read Positions in the RingBuffer (Tail)
139 int mWritePosition; ///< Write Position in the RingBuffer (Head)
147 /*const*/ int mSlotSize; ///< The size of one slot in byes
148 /*const*/ int mNumSlots; ///< Number of Slots
149 /*const*/ int mTotalSize; ///< Total size of the mRingBuffer = mSlotSize*mNumSlotss
150 uint32_t mReadPosition; ///< Read Positions in the RingBuffer (Tail)
151 uint32_t mWritePosition; ///< Write Position in the RingBuffer (Head)
140152 int mFullSlots; ///< Number of used (full) slots, in slot-size
141153 int8_t* mRingBuffer; ///< 8-bit array of data (1-byte)
142154 int8_t* mLastReadSlot; ///< Last slot read
145157 QMutex mMutex; ///< Mutex to protect read and write operations
146158 QWaitCondition mBufferIsNotFull; ///< Buffer not full condition to monitor threads
147159 QWaitCondition mBufferIsNotEmpty; ///< Buffer not empty condition to monitor threads
148 std::atomic<uint32_t> mUnderruns;
149 std::atomic<uint32_t> mOverflows;
160
161 // IO stat
162 int mStatUnit;
163 uint32_t mUnderruns;
164 uint32_t mOverflows;
165 int32_t mSkewRaw;
166 double mLevelCur;
167 double mLevelDownRate;
168 int32_t mLevel;
169
170 uint32_t mBufDecOverflow;
171 uint32_t mBufDecPktLoss;
172 uint32_t mBufIncUnderrun;
173 uint32_t mBufIncCompensate;
174
175 // temp counters for reads
176 uint32_t mReadsNew;
177 uint32_t mUnderrunsNew;
178 int32_t mSkew0;
179
180 // broadcast counters
181 int32_t mBroadcastSkew;
182 int32_t mBroadcastDelta;
150183 };
151184
152185 #endif
3636
3737 #include "Settings.h"
3838 #include "LoopBack.h"
39 #include "NetKS.h"
39 //#include "NetKS.h"
40 #include "Effects.h"
4041
4142 #ifdef WAIR // wair
4243 #include "ap8x2.dsp.h"
4344 #include "Stk16.dsp.h"
4445 #endif // endwhere
4546
46 #include "UdpHubListener.h"
47 #include "JackTripWorker.h"
47 //#include "JackTripWorker.h"
4848 #include "jacktrip_globals.h"
4949
5050 #include <iostream>
5151 #include <getopt.h> // for command line parsing
5252 #include <cstdlib>
53
54 #include "ThreadPoolTest.h"
53 #include <assert.h>
54 #include <ctype.h>
55
56 //#include "ThreadPoolTest.h"
5557
5658 using std::cout; using std::endl;
5759
5860 int gVerboseFlag = 0;
5961
62 enum JTLongOptIDS {
63 OPT_BUFSTRATEGY = 1001,
64 OPT_SIMLOSS,
65 OPT_SIMJITTER,
66 OPT_BROADCAST,
67 OPT_RTUDPPRIORITY,
68 };
6069
6170 //*******************************************************************************
6271 Settings::Settings() :
63 mJackTrip(NULL),
6472 mJackTripMode(JackTrip::SERVER),
6573 mDataProtocol(JackTrip::UDP),
6674 mNumChans(2),
6775 mBufferQueueLength(gDefaultQueueLength),
6876 mAudioBitResolution(AudioInterface::BIT16),
6977 mBindPortNum(gDefaultPort), mPeerPortNum(gDefaultPort),
70 mServerUdpPortNum(NULL),
71 mClientName(NULL),
72 mUnderrrunZero(false),
78 mServerUdpPortNum(0),
79 mUnderrunMode(JackTrip::WAVETABLE),
80 mStopOnTimeout(false),
81 mBufferStrategy(1),
7382 mLoopBack(false),
7483 #ifdef WAIR // WAIR
7584 mNumNetRevChans(0),
8695 mChanfeDefaultBS(false),
8796 mHubConnectionMode(JackTrip::SERVERTOCLIENT),
8897 mConnectDefaultAudioPorts(true),
89 mIOStatTimeout(0)
98 mIOStatTimeout(0),
99 mEffects(false), // outgoing limiter OFF by default
100 mSimulatedLossRate(0.0),
101 mSimulatedJitterRate(0.0),
102 mSimulatedDelayRel(0.0),
103 mBroadcastQueue(0),
104 mUseRtUdpPriority(false)
90105 {}
91106
92107 //*******************************************************************************
93 Settings::~Settings()
94 {
95 stopJackTrip();
96 delete mJackTrip;
97 }
108 Settings::~Settings() = default;
98109
99110 //*******************************************************************************
100111 void Settings::parseInput(int argc, char** argv)
101112 {
113 // Always use decimal point for floating point numbers
114 setlocale( LC_NUMERIC, "C" );
102115 // If no command arguments are given, print instructions
103116 if(argc == 1) {
104117 printUsage();
111124 //----------------------------------------------------------------------------
112125 static struct option longopts[] = {
113126 // These options don't set a flag.
114 { "numchannels", required_argument, NULL, 'n' }, // Number of input and output channels
127 { "numchannels", required_argument, NULL, 'n' }, // Number of input and output channels
115128 #ifdef WAIR // WAIR
116 { "wair", no_argument, NULL, 'w' }, // Run in LAIR mode, sets numnetrevchannels
117 { "addcombfilterlength", required_argument, NULL, 'N' }, // added comb filter length
118 { "combfilterfeedback", required_argument, NULL, 'H' }, // comb filter feedback
129 { "wair", no_argument, NULL, 'w' }, // Run in LAIR mode, sets numnetrevchannels
130 { "addcombfilterlength", required_argument, NULL, 'N' }, // added comb filter length
131 { "combfilterfeedback", required_argument, NULL, 'H' }, // comb filter feedback
119132 #endif // endwhere
120 { "server", no_argument, NULL, 's' }, // Run in server mode
121 { "client", required_argument, NULL, 'c' }, // Run in client mode, set server IP address
122 { "localaddress", required_argument, NULL, 'L' }, // set local address e.g., 127.0.0.2 for second instance on same host
123 { "jacktripserver", no_argument, NULL, 'S' }, // Run in JamLink mode
124 { "pingtoserver", required_argument, NULL, 'C' }, // Run in ping to server mode, set server IP address
125 { "portoffset", required_argument, NULL, 'o' }, // Port Offset from 4464
126 { "bindport", required_argument, NULL, 'B' }, // Port Offset from 4464
127 { "peerport", required_argument, NULL, 'P' }, // Port Offset from 4464
128 { "udpbaseport", required_argument, NULL, 'U' }, // Server udp base port (defaults to 61002)
129 { "queue", required_argument, NULL, 'q' }, // Queue Length
130 { "redundancy", required_argument, NULL, 'r' }, // Redundancy
131 { "bitres", required_argument, NULL, 'b' }, // Audio Bit Resolution
132 { "zerounderrun", no_argument, NULL, 'z' }, // Use Underrun to Zeros Mode
133 { "loopback", no_argument, NULL, 'l' }, // Run in loopback mode
134 { "jamlink", no_argument, NULL, 'j' }, // Run in JamLink mode
135 { "emptyheader", no_argument, NULL, 'e' }, // Run in JamLink mode
136 { "clientname", required_argument, NULL, 'J' }, // Run in JamLink mode
137 { "rtaudio", no_argument, NULL, 'R' }, // Run in JamLink mode
138 { "srate", required_argument, NULL, 'T' }, // Set Sample Rate
139 { "deviceid", required_argument, NULL, 'd' }, // Set RTAudio device id to use
140 { "bufsize", required_argument, NULL, 'F' }, // Set buffer Size
141 { "nojackportsconnect" , no_argument, NULL, 'D'}, // Don't connect default Audio Ports
142 { "version", no_argument, NULL, 'v' }, // Version Number
143 { "verbose", no_argument, NULL, 'V' }, // Verbose mode
144 { "hubpatch", required_argument, NULL, 'p' }, // Set hubConnectionMode for auto patch in Jack
145 { "iostat", required_argument, NULL, 'I' }, // Set IO stat timeout
146 { "iostatlog", required_argument, NULL, 'G' }, // Set IO stat log file
147 { "help", no_argument, NULL, 'h' }, // Print Help
148 { NULL, 0, NULL, 0 }
149 };
133 { "server", no_argument, NULL, 's' }, // Run in P2P server mode
134 { "client", required_argument, NULL, 'c' }, // Run in P2P client mode, set server IP address
135 { "localaddress", required_argument, NULL, 'L' }, // set local address e.g., 127.0.0.2 for second instance on same host
136 { "jacktripserver", no_argument, NULL, 'S' }, // Run in JamLink mode
137 { "pingtoserver", required_argument, NULL, 'C' }, // Run in ping to server mode, set server IP address
138 { "portoffset", required_argument, NULL, 'o' }, // Port Offset from 4464
139 { "bindport", required_argument, NULL, 'B' }, // Port Offset from 4464
140 { "peerport", required_argument, NULL, 'P' }, // Port Offset from 4464
141 { "udpbaseport", required_argument, NULL, 'U' }, // Server udp base port (defaults to 61002)
142 { "queue", required_argument, NULL, 'q' }, // Queue Length
143 { "redundancy", required_argument, NULL, 'r' }, // Redundancy
144 { "bitres", required_argument, NULL, 'b' }, // Audio Bit Resolution
145 { "zerounderrun", no_argument, NULL, 'z' }, // Use Underrun to Zeros Mode
146 { "timeout", no_argument, NULL, 't' }, // Quit after 10 second network timeout
147 { "loopback", no_argument, NULL, 'l' }, // Run in loopback mode
148 { "jamlink", no_argument, NULL, 'j' }, // Run in JamLink mode
149 { "emptyheader", no_argument, NULL, 'e' }, // Run in JamLink mode
150 { "clientname", required_argument, NULL, 'J' }, // Run in JamLink mode
151 { "remotename", required_argument, NULL, 'K' }, // Client name on hub server
152 { "rtaudio", no_argument, NULL, 'R' }, // Run in JamLink mode
153 { "srate", required_argument, NULL, 'T' }, // Set Sample Rate
154 { "deviceid", required_argument, NULL, 'd' }, // Set RTAudio device id to use
155 { "bufsize", required_argument, NULL, 'F' }, // Set buffer Size
156 { "nojackportsconnect" , no_argument, NULL, 'D'}, // Don't connect default Audio Ports
157 { "version", no_argument, NULL, 'v' }, // Version Number
158 { "verbose", no_argument, NULL, 'V' }, // Verbose mode
159 { "hubpatch", required_argument, NULL, 'p' }, // Set hubConnectionMode for auto patch in Jack
160 { "iostat", required_argument, NULL, 'I' }, // Set IO stat timeout
161 { "iostatlog", required_argument, NULL, 'G' }, // Set IO stat log file
162 { "effects", required_argument, NULL, 'f' }, // Turn on outgoing compressor and incoming reverb, reverbLevel arg
163 { "overflowlimiting", required_argument, NULL, 'O' }, // Turn On limiter, cases 'i', 'o', 'io'
164 { "assumednumclients", required_argument, NULL, 'a' }, // assumed number of clients (sound sources) (otherwise 2)
165 { "bufstrategy", required_argument, NULL, OPT_BUFSTRATEGY }, // Set bufstrategy
166 { "simloss", required_argument, NULL, OPT_SIMLOSS },
167 { "simjitter", required_argument, NULL, OPT_SIMJITTER },
168 { "broadcast", required_argument, NULL, OPT_BROADCAST },
169 { "udprt", no_argument, NULL, OPT_RTUDPPRIORITY },
170 { "help", no_argument, NULL, 'h' }, // Print Help
171 { "examine-audio-delay", required_argument, NULL, 'x' }, // test mode - measure audio round-trip latency statistics
172 { NULL, 0, NULL, 0 }
173 };
150174
151175 // Parse Command Line Arguments
152176 //----------------------------------------------------------------------------
153177 /// \todo Specify mandatory arguments
154178 int ch;
155 while ( (ch = getopt_long(argc, argv,
156 "n:N:H:sc:SC:o:B:P:U:q:r:b:zlwjeJ:RTd:F:p:DvVh", longopts, NULL)) != -1 )
179 while ((ch = getopt_long(argc, argv,
180 "n:N:H:sc:SC:o:B:P:U:q:r:b:ztlwjeJ:K:RTd:F:p:DvVhI:G:f:O:a:x:", longopts, NULL)) != -1)
157181 switch (ch) {
158182
159183 case 'n': // Number of input and output channels
178202 mClientRoomSize = atof(optarg); // cmd line comb feedback adjustment
179203 break;
180204 #endif // endwhere
181 case 's': // Run in server mode
205 case 's': // Run in P2P server mode
182206 //-------------------------------------------------------
183207 mJackTripMode = JackTrip::SERVER;
184208 break;
185 case 'S': // Run in jacktripserver mode
209 case 'S': // Run in Hub server mode
186210 //-------------------------------------------------------
187211 mJackTripServer = true;
188212 break;
189 case 'c': // Client mode
213 case 'c': // P2P client mode
190214 //-------------------------------------------------------
191215 mJackTripMode = JackTrip::CLIENT;
192216 mPeerAddress = optarg;
219243 break;
220244 case 'b':
221245 //-------------------------------------------------------
222 if ( atoi(optarg) == 8 ) {
223 mAudioBitResolution = AudioInterface::BIT8; }
224 else if ( atoi(optarg) == 16 ) {
225 mAudioBitResolution = AudioInterface::BIT16; }
226 else if ( atoi(optarg) == 24 ) {
227 mAudioBitResolution = AudioInterface::BIT24; }
228 else if ( atoi(optarg) == 32 ) {
229 mAudioBitResolution = AudioInterface::BIT32; }
230 else {
231 std::cerr << "--bitres ERROR: Wrong bit resolution: "
246 if (atoi(optarg) == 8) {
247 mAudioBitResolution = AudioInterface::BIT8;
248 } else if (atoi(optarg) == 16) {
249 mAudioBitResolution = AudioInterface::BIT16;
250 } else if (atoi(optarg) == 24) {
251 mAudioBitResolution = AudioInterface::BIT24;
252 } else if (atoi(optarg) == 32) {
253 mAudioBitResolution = AudioInterface::BIT32;
254 } else {
255 printUsage();
256 std::cerr << "--bitres ERROR: Bit resolution: "
232257 << atoi(optarg) << " is not supported." << endl;
258 std::exit(1);
259 }
260 break;
261 case 'q':
262 //-------------------------------------------------------
263 if (0 == strncmp(optarg, "auto", 4)) {
264 mBufferQueueLength = -atoi(optarg+4);
265 if (0 == mBufferQueueLength) {
266 mBufferQueueLength = -500;
267 }
268 }
269 else if ( atoi(optarg) <= 0 ) {
233270 printUsage();
234 std::exit(1); }
235 break;
236 case 'q':
237 //-------------------------------------------------------
238 if ( atoi(optarg) <= 0 ) {
239271 std::cerr << "--queue ERROR: The queue has to be equal or greater than 2" << endl;
240 printUsage();
241272 std::exit(1); }
242273 else {
243274 mBufferQueueLength = atoi(optarg);
246277 case 'r':
247278 //-------------------------------------------------------
248279 if ( atoi(optarg) <= 0 ) {
249 std::cerr << "--redundancy ERROR: The reduncancy has to be a positive integer" << endl;
250280 printUsage();
281 std::cerr << "--redundancy ERROR: The redundancy has to be a positive integer" << endl;
251282 std::exit(1); }
252283 else {
253284 mRedundancy = atoi(optarg);
255286 break;
256287 case 'z': // underrun to zero
257288 //-------------------------------------------------------
258 mUnderrrunZero = true;
289 mUnderrunMode = JackTrip::ZEROS;
290 break;
291 case 't': // quit on timeout
292 mStopOnTimeout = true;
259293 break;
260294 case 'l': // loopback
261295 //-------------------------------------------------------
272306 case 'J': // Set client Name
273307 //-------------------------------------------------------
274308 mClientName = optarg;
309 break;
310 case 'K': // Set Remote client Name
311 //-------------------------------------------------------
312 mRemoteClientName = optarg;
275313 break;
276314 case 'R': // RtAudio
277315 //-------------------------------------------------------
308346 //-------------------------------------------------------
309347 gVerboseFlag = true;
310348 if (gVerboseFlag) std::cout << "Verbose mode" << std::endl;
349 mEffects.setVerboseFlag(gVerboseFlag);
311350 break;
312351 case 'p':
313352 //-------------------------------------------------------
314 if ( atoi(optarg) == 0 ) {
315 mHubConnectionMode = JackTrip::SERVERTOCLIENT; }
316 else if ( atoi(optarg) == 1 ) {
317 mHubConnectionMode = JackTrip::CLIENTECHO; }
318 else if ( atoi(optarg) == 2 ) {
319 mHubConnectionMode = JackTrip::CLIENTFOFI; }
320 else if ( atoi(optarg) == 3 ) {
321 mHubConnectionMode = JackTrip::RESERVEDMATRIX; }
322 else if ( atoi(optarg) == 4 ) {
323 mHubConnectionMode = JackTrip::FULLMIX; }
324 else {
353 if ( atoi(optarg) == 0 ) {
354 mHubConnectionMode = JackTrip::SERVERTOCLIENT;
355 } else if ( atoi(optarg) == 1 ) {
356 mHubConnectionMode = JackTrip::CLIENTECHO;
357 } else if ( atoi(optarg) == 2 ) {
358 mHubConnectionMode = JackTrip::CLIENTFOFI;
359 } else if ( atoi(optarg) == 3 ) {
360 mHubConnectionMode = JackTrip::RESERVEDMATRIX;
361 } else if ( atoi(optarg) == 4 ) {
362 mHubConnectionMode = JackTrip::FULLMIX;
363 } else if ( atoi(optarg) == 5 ) {
364 mHubConnectionMode = JackTrip::NOAUTO;
365 } else {
366 printUsage();
325367 std::cerr << "-p ERROR: Wrong HubConnectionMode: "
326368 << atoi(optarg) << " is not supported." << endl;
327 printUsage();
328 std::exit(1); }
369 std::exit(1);
370 }
329371 break;
330372 case 'I': // IO Stat timeout
331373 //-------------------------------------------------------
332374 mIOStatTimeout = atoi(optarg);
333375 if (0 > mIOStatTimeout) {
376 printUsage();
334377 std::cerr << "--iostat ERROR: negative timeout." << endl;
378 std::exit(1);
379 }
380 break;
381 case 'G': // IO Stat log file
382 //-------------------------------------------------------
383 mIOStatStream.reset(new std::ofstream(optarg));
384 if (!mIOStatStream->is_open()) {
385 printUsage();
386 std::cerr << "--iostatlog FAILED to open " << optarg
387 << " for writing." << endl;
388 std::exit(1);
389 }
390 break;
391 case OPT_BUFSTRATEGY: // Buf strategy
392 mBufferStrategy = atoi(optarg);
393 if (-1 > mBufferStrategy || 2 < mBufferStrategy) {
394 std::cerr << "Unsupported buffer strategy " << optarg << endl;
335395 printUsage();
336396 std::exit(1);
337397 }
338398 break;
339 case 'G': // IO Stat log file
340 //-------------------------------------------------------
341 mIOStatStream.open(optarg);
342 if (!mIOStatStream.is_open()) {
343 std::cerr << "--iostatlog FAILED to open " << optarg
344 << " for writing." << endl;
345 printUsage();
346 std::exit(1);
347 }
399 case OPT_SIMLOSS: // Simulate packet loss
400 mSimulatedLossRate = atof(optarg);
401 break;
402 case OPT_SIMJITTER: // Simulate jitter
403 char* endp;
404 mSimulatedJitterRate = strtod(optarg, &endp);
405 if (0 == *endp) {
406 mSimulatedDelayRel = 1.0;
407 }
408 else {
409 mSimulatedDelayRel = atof(endp+1);
410 }
411 break;
412 case OPT_BROADCAST: // Broadcast output
413 mBroadcastQueue = atoi(optarg);
414 break;
415 case OPT_RTUDPPRIORITY: // Use RT priority for UDPDataProtocol thread
416 mUseRtUdpPriority = true;
348417 break;
349418 case 'h':
350419 //-------------------------------------------------------
351420 printUsage();
352421 std::exit(0);
353422 break;
354 default:
355 //-------------------------------------------------------
423 case 'O': { // Overflow limiter (i, o, or io)
424 //-------------------------------------------------------
425 char cmd[] { "--overflowlimiting (-O)" };
426 if (gVerboseFlag) {
427 printf("%s argument = %s\n",cmd,optarg);
428 }
429 int returnCode = mEffects.parseLimiterOptArg(cmd,optarg);
430 if (returnCode > 1) {
431 mEffects.printHelp(cmd,ch);
432 std::cerr << cmd << " required argument `" << optarg << "' is malformed\n";
433 std::exit(1);
434 } else if (returnCode == 1) {
435 std::exit(0); // benign but not continuing such as "help"
436 }
437 break; }
438 case 'a': { // assumed number of clients (applies to outgoing limiter)
439 //-------------------------------------------------------
440 char cmd[] { "--assumednumclients (-a)" };
441 if (gVerboseFlag) {
442 printf("%s argument = %s\n",cmd,optarg);
443 }
444 int returnCode = mEffects.parseAssumedNumClientsOptArg(cmd,optarg);
445 if (returnCode > 1) {
446 mEffects.printHelp(cmd,ch);
447 std::cerr << cmd << " required argument `" << optarg << "' is malformed\n";
448 std::exit(1);
449 } else if (returnCode == 1) {
450 std::exit(0); // help printed
451 }
452 break; }
453 case 'f': { // --effects (-f) effectsSpecArg
454 //-------------------------------------------------------
455 char cmd[] { "--effects (-f)" };
456 int returnCode = mEffects.parseEffectsOptArg(cmd,optarg);
457 if (returnCode > 1) {
458 mEffects.printHelp(cmd,ch);
459 std::cerr << cmd << " required argument `" << optarg << "' is malformed\n";
460 std::exit(1);
461 } else if (returnCode == 1) {
462 std::exit(0); // something benign but non-continuing like "help"
463 }
464 break; }
465 case 'x': { // examine connection (test mode)
466 //-------------------------------------------------------
467 char cmd[] { "--examine-audio-delay (-x)" };
468 if (tolower(optarg[0])=='h') {
469 mAudioTester.printHelp(cmd,ch);
470 std::exit(0);
471 }
472 mAudioTester.setEnabled(true);
473 if (optarg == 0 || optarg[0] == '-' || optarg[0] == 0) { // happens when no -f argument specified
356474 printUsage();
357 std::exit(0);
358 break;
475 std::cerr << cmd << " ERROR: Print-interval argument REQUIRED (set to 0.0 to see every delay)\n";
476 std::exit(1);
477 }
478 mAudioTester.setPrintIntervalSec(atof(optarg));
479 break; }
480 case ':': {
481 printUsage();
482 printf("*** Missing option argument *** see above for usage\n\n");
483 break; }
484 case '?': {
485 printUsage();
486 printf("*** Unknown, missing, or ambiguous option argument *** see above for usage\n\n");
487 std::exit(1);
488 break; }
489 default: {
490 //-------------------------------------------------------
491 printUsage();
492 printf("*** Unrecognized option -%c *** see above for usage\n",ch);
493 std::exit(1);
494 break; }
359495 }
360496
361497 // Warn user if undefined options where entered
362498 //----------------------------------------------------------------------------
363499 if (optind < argc) {
500 if (strcmp(argv[optind],"help")!=0) {
364501 cout << gPrintSeparator << endl;
365 cout << "WARINING: The following entered options have no effect." << endl;
366 cout << " They will be ignored!" << endl;
367 cout << " Type 'jacktrip' to see options." << endl;
502 cout << "*** Unexpected command-line argument(s): ";
368503 for( ; optind < argc; optind++) {
369 cout << "argument: " << argv[optind] << endl;
504 cout << argv[optind] << " ";
370505 }
371 cout << gPrintSeparator << endl;
506 cout << endl << gPrintSeparator << endl;
507 }
508 printUsage();
509 std::exit(1);
510 }
511
512 assert(mNumChans>0);
513 mAudioTester.setSendChannel(mNumChans-1); // use last channel for latency testing
514 // Originally, testing only in the last channel was adopted
515 // because channel 0 ("left") was a clap track on CCRMA loopback
516 // servers. Now, however, we also do it in order to easily keep
517 // effects in all but the last channel, enabling silent testing
518 // in the last channel in parallel with normal operation of the others.
519
520 // Exit if options are incompatible
521 //----------------------------------------------------------------------------
522 bool haveSomeServerMode = not ((mJackTripMode == JackTrip::CLIENT) || (mJackTripMode == JackTrip::CLIENTTOPINGSERVER));
523 if (mEffects.getHaveEffect() && haveSomeServerMode) {
524 std::cerr << "*** --effects (-f) ERROR: Effects not yet supported server modes (-S and -s).\n\n";
525 std::exit(1);
526 }
527 if (mEffects.getHaveLimiter() && haveSomeServerMode) {
528 if (mEffects.getLimit() != Effects::LIMITER_MODE::LIMITER_OUTGOING) { // default case
529 std::cerr << "*** --overflowlimiting (-O) ERROR: Limiters not yet supported server modes (-S and -s).\n\n";
530 }
531 mEffects.setNoLimiters();
532 // don't exit since an outgoing limiter should be the default (could exit for incoming case):
533 // std::exit(1);
534 }
535 if (mAudioTester.getEnabled() && haveSomeServerMode) {
536 std::cerr << "*** --examine-audio-delay (-x) ERROR: Audio latency measurement not supported in server modes (-S and -s)\n\n";
537 std::exit(1);
538 }
539 if (mAudioTester.getEnabled()
540 && (mAudioBitResolution != AudioInterface::BIT16)
541 && (mAudioBitResolution != AudioInterface::BIT32) ) { // BIT32 not tested but should be ok
542 // BIT24 should work also, but there's a comment saying it's broken right now, so exclude it
543 std::cerr << "*** --examine-audio-delay (-x) ERROR: Only --bitres (-b) 16 and 32 presently supported for audio latency measurement.\n\n";
544 std::exit(1);
372545 }
373546 }
374
375547
376548 //*******************************************************************************
377549 void Settings::printUsage()
383555 cout << "SoundWIRE group at CCRMA, Stanford University" << endl;
384556 cout << "VERSION: " << gVersion << endl;
385557 cout << "" << endl;
386 cout << "Usage: jacktrip [-s|-c host] [options]" << endl;
558 cout << "Usage: jacktrip [-s|-c|-S|-C hostIPAddressOrURL] [options]" << endl;
387559 cout << "" << endl;
388560 cout << "Options: " << endl;
389 cout << "REQUIRED ARGUMENTS: " << endl;
390 cout << " -s, --server Run in Server Mode" << endl;
391 cout << " -c, --client <peer_hostname_or_IP_num> Run in Client Mode" << endl;
561 cout << "REQUIRED ARGUMENTS: One of:" << endl;
562 cout << " -s, --server Run in P2P Server Mode" << endl;
563 cout << " -c, --client <peer_hostname_or_IP_num> Run in P2P Client Mode" << endl;
392564 cout << " -S, --jacktripserver Run in Hub Server Mode" << endl;
393565 cout << " -C, --pingtoserver <peer_name_or_IP> Run in Hub Client Mode" << endl;
394566 cout << endl;
399571 cout << " -w, --wair Run in WAIR Mode" << endl;
400572 cout << " -N, --addcombfilterlength # comb length adjustment for WAIR (default "
401573 << gDefaultAddCombFilterLength << ")" << endl;
402 cout << " -H, --combfilterfeedback # comb feedback adjustment for WAIR (default "
574 cout << " -H, --combfilterfeedback # (roomSize) comb feedback adjustment for WAIR (default "
403575 << gDefaultCombFilterFeedback << ")" << endl;
404576 #endif // endwhere
405577 cout << " -q, --queue # (2 or more) Queue Buffer Length, in Packet Size (default: "
410582 cout << " -B, --bindport # Set only the bind port number (default: " << gDefaultPort << ")" << endl;
411583 cout << " -P, --peerport # Set only the peer port number (default: " << gDefaultPort << ")" << endl;
412584 cout << " -U, --udpbaseport Set only the server udp base port number (default: 61002)" << endl;
413 cout << " -b, --bitres # (8, 16, 24, 32) Audio Bit Rate Resolutions (default: 16)" << endl;
414 cout << " -p, --hubpatch # (0, 1, 2, 3, 4) Hub auto audio patch, only has effect if running HUB SERVER mode, 0=server-to-clients, 1=client loopback, 2=clients can hear all clients except themselves, 3=reserved for TUB, 4=full mix (default: 0), i.e. clients auto-connect and hear all clients including themselves" << endl;
585 cout << " -b, --bitres # (8, 16, 24, 32) Audio Bit Rate Resolutions (default: 16, 32 uses floating-point)" << endl;
586 cout << " -p, --hubpatch # (0, 1, 2, 3, 4, 5) Hub auto audio patch, only has effect if running HUB SERVER mode, 0=server-to-clients, 1=client loopback, 2=client fan out/in but not loopback, 3=reserved for TUB, 4=full mix, 5=no auto patching (default: 0)" << endl;
415587 cout << " -z, --zerounderrun Set buffer to zeros when underrun occurs (default: wavetable)" << endl;
588 cout << " -t, --timeout Quit after 10 seconds of no network activity" << endl;
416589 cout << " -l, --loopback Run in Loop-Back Mode" << endl;
417590 cout << " -j, --jamlink Run in JamLink Mode (Connect to a JamLink Box)" << endl;
418 cout << " --clientname Change default client name (default: JackTrip)" << endl;
419 cout << " --localaddress Change default local host IP address (default: 127.0.0.1)" << endl;
420 cout << " --nojackportsconnect Don't connect default audio ports in jack, including not doing hub auto audio patch in HUB SERVER mode." << endl;
591 cout << " -J, --clientname Change default client name (default: JackTrip)" << endl;
592 cout << " -K, --remotename Change default remote client name when connecting to a hub server (the default is derived from this computer's external facing IP address)" << endl;
593 cout << " -L, --localaddress Change default local host IP address (default: 127.0.0.1)" << endl;
594 cout << " -D, --nojackportsconnect Don't connect default audio ports in jack" << endl;
595 cout << " --bufstrategy # (0, 1, 2) Use alternative jitter buffer" << endl;
596 cout << " --broadcast <broadcast_queue> Turn on broadcast output ports with extra queue (requires new jitter buffer)" << endl;
597 cout << " --udprt Use RT thread priority for network I/O" << endl;
598 cout << endl;
599 cout << "OPTIONAL SIGNAL PROCESSING: " << endl;
600 cout << " -f, --effects # | paramString | help Turn on incoming and/or outgoing compressor and/or reverb in Client - see `-f help' for details" << endl;
601 cout << " -O, --overflowlimiting i|o[w]|io[w]|n|help" << endl;
602 cout << " Use audio limiter(s) in Client, i=incoming from network, o=outgoing to network, io=both, n=no limiters, w=warn if limiting (default=n). Say -O help for more." << endl;
603 cout << " -a, --assumednumclients help|# (1,2,...) Assumed number of Clients (sources) mixing at Hub Server (otherwise 2 assumed by -O)" << endl;
421604 cout << endl;
422605 cout << "ARGUMENTS TO USE JACKTRIP WITHOUT JACK:" << endl;
423 cout << " --rtaudio Use system's default sound system instead of Jack" << endl;
424 cout << " --srate # Set the sampling rate, works on --rtaudio mode only (default: 48000)" << endl;
425 cout << " --bufsize # Set the buffer size, works on --rtaudio mode only (default: 128)" << endl;
426 cout << " --deviceid # The rtaudio device id --rtaudio mode only (default: 0)" << endl;
606 cout << " -R, --rtaudio Use system's default sound system instead of Jack" << endl;
607 cout << " -T, --srate # Set the sampling rate, works on --rtaudio mode only (default: 48000)" << endl;
608 cout << " -F, --bufsize # Set the buffer size, works on --rtaudio mode only (default: 128)" << endl;
609 cout << " -d, --deviceid # The rtaudio device id --rtaudio mode only (default: 0)" << endl;
427610 cout << endl;
428611 cout << "ARGUMENTS TO DISPLAY IO STATISTICS:" << endl;
429612 cout << " -I, --iostat <time_in_secs> Turn on IO stat reporting with specified interval (in seconds)" << endl;
430613 cout << " -G, --iostatlog <log_file> Save stat log into a file (default: print in stdout)" << endl;
614 cout << " -x, --examine-audio-delay <print_interval_in_secs> | help\n";
615 cout << " Print round-trip audio delay statistics. See `-x help' for details." << endl;
616 cout << endl;
617 cout << "ARGUMENTS TO SIMULATE NETWORK ISSUES:" << endl;
618 cout << " --simloss <rate> Simulate packet loss" << endl;
619 cout << " --simjitter <rate>,<d> Simulate jitter, d is max delay in packets" << endl;
431620 cout << endl;
432621 cout << "HELP ARGUMENTS: " << endl;
433622 cout << " -v, --version Prints Version Number" << endl;
438627
439628
440629 //*******************************************************************************
441 void Settings::startJackTrip()
630 UdpHubListener *Settings::getConfiguredHubServer()
442631 {
443
444632 if ((mBindPortNum < gBindPortLow) || (mBindPortNum > gBindPortHigh))
445633 std::cout << "BindPort: "<< mBindPortNum << " outside range" << std::endl;
446634
447 /// \todo Change this, just here to test
448 if ( mJackTripServer ) {
449 if (gVerboseFlag) std::cout << "JackTrip HUB SERVER TCP Bind Port: " << mBindPortNum << std::endl;
450 UdpHubListener* udpmaster = new UdpHubListener(mBindPortNum,mServerUdpPortNum);
451 udpmaster->setSettings(this);
635 if (gVerboseFlag) std::cout << "JackTrip HUB SERVER TCP Bind Port: " << mBindPortNum << std::endl;
636 UdpHubListener *udpHub = new UdpHubListener(mBindPortNum, mServerUdpPortNum);
637 //udpHub->setSettings(this);
452638 #ifdef WAIR // WAIR
453 udpmaster->setWAIR(mWAIR);
639 udpHub->setWAIR(mWAIR);
454640 #endif // endwhere
455 udpmaster->setHubPatch(mHubConnectionMode);
456 udpmaster->setConnectDefaultAudioPorts(mConnectDefaultAudioPorts);
457 if (gVerboseFlag) std::cout << "Settings:startJackTrip before udpmaster->start" << std::endl;
458 // Set buffers to zero when underrun
459 if ( mUnderrrunZero ) {
460 cout << "Setting buffers to zero when underrun..." << endl;
461 cout << gPrintSeparator << std::endl;
462 udpmaster->setUnderRunMode(JackTrip::ZEROS);
641 udpHub->setHubPatch(mHubConnectionMode);
642 if (mHubConnectionMode == JackTrip::NOAUTO) {
643 udpHub->setConnectDefaultAudioPorts(false);
644 } else {
645 udpHub->setConnectDefaultAudioPorts(mConnectDefaultAudioPorts);
646 }
647 // Set buffers to zero when underrun
648 if ( mUnderrunMode == JackTrip::ZEROS ) {
649 cout << "Setting buffers to zero when underrun..." << endl;
650 cout << gPrintSeparator << std::endl;
651 udpHub->setUnderRunMode(mUnderrunMode);
652 }
653 udpHub->setBufferQueueLength(mBufferQueueLength);
654
655 udpHub->setBufferStrategy(mBufferStrategy);
656 udpHub->setNetIssuesSimulation(mSimulatedLossRate,
657 mSimulatedJitterRate, mSimulatedDelayRel);
658 udpHub->setBroadcast(mBroadcastQueue);
659 udpHub->setUseRtUdpPriority(mUseRtUdpPriority);
660
661 if (mIOStatTimeout > 0) {
662 udpHub->setIOStatTimeout(mIOStatTimeout);
663 udpHub->setIOStatStream(mIOStatStream);
664 }
665 return udpHub;
666 }
667
668 JackTrip *Settings::getConfiguredJackTrip()
669 {
670 #ifdef WAIR // WAIR
671 if (gVerboseFlag) std::cout << "Settings:startJackTrip mNumNetRevChans = " << mNumNetRevChans << std::endl;
672 #endif // endwhere
673 if (gVerboseFlag) std::cout << "Settings:startJackTrip before new JackTrip" << std::endl;
674 JackTrip *jackTrip = new JackTrip(mJackTripMode, mDataProtocol, mNumChans,
675 #ifdef WAIR // wair
676 mNumNetRevChans,
677 #endif // endwhere
678 mBufferQueueLength, mRedundancy, mAudioBitResolution,
679 /*DataProtocol::packetHeaderTypeT PacketHeaderType = */DataProtocol::DEFAULT,
680 /*underrunModeT UnderRunMode = */ mUnderrunMode,
681 /* int receiver_bind_port = */ mBindPortNum,
682 /*int sender_bind_port = */ mBindPortNum,
683 /*int receiver_peer_port = */ mPeerPortNum,
684 /* int sender_peer_port = */ mPeerPortNum,
685 mPeerPortNum
686 );
687 // Set connect or not default audio ports. Only work for jack
688 jackTrip->setConnectDefaultAudioPorts(mConnectDefaultAudioPorts);
689
690 // Change client name if different from default
691 if (!mClientName.isEmpty()) {
692 jackTrip->setClientName(mClientName);
693 }
694
695 if (!mRemoteClientName.isEmpty() && (mJackTripMode == JackTrip::CLIENTTOPINGSERVER)) {
696 jackTrip->setRemoteClientName(mRemoteClientName);
697 }
698
699 // Set buffers to zero when underrun (Actual setting is handled in constructor.)
700 if (mUnderrunMode == JackTrip::ZEROS) {
701 cout << "Setting buffers to zero when underrun..." << endl;
702 cout << gPrintSeparator << std::endl;
703 }
704
705 jackTrip->setStopOnTimeout(mStopOnTimeout);
706
707 // Set peer address in server mode
708 if (mJackTripMode == JackTrip::CLIENT || mJackTripMode == JackTrip::CLIENTTOPINGSERVER) {
709 jackTrip->setPeerAddress(mPeerAddress); }
710
711 // if(mLocalAddress!=QString()) // default
712 // mJackTrip->setLocalAddress(QHostAddress(mLocalAddress.toLatin1().data()));
713 // else
714 // mJackTrip->setLocalAddress(QHostAddress::Any);
715
716 // Set Ports - Done in constructor now.
717 //cout << "SETTING ALL PORTS" << endl;
718 /*if (gVerboseFlag) std::cout << "Settings:startJackTrip before mJackTrip->setBindPorts" << std::endl;
719 jackTrip->setBindPorts(mBindPortNum);
720 if (gVerboseFlag) std::cout << "Settings:startJackTrip before mJackTrip->setPeerPorts" << std::endl;
721 jackTrip->setPeerPorts(mPeerPortNum);*/
722
723 // Set in JamLink Mode
724 if ( mJamLink ) {
725 cout << "Running in JamLink Mode..." << endl;
726 cout << gPrintSeparator << std::endl;
727 jackTrip->setPacketHeaderType(DataProtocol::JAMLINK);
728 }
729
730 // Set in EmptyHeader Mode
731 if (mEmptyHeader) {
732 cout << "Running in EmptyHeader Mode..." << endl;
733 cout << gPrintSeparator << std::endl;
734 jackTrip->setPacketHeaderType(DataProtocol::EMPTY);
735 }
736
737 // Set RtAudio
738 #ifdef __RT_AUDIO__
739 if (!mUseJack) {
740 mJackTrip->setAudiointerfaceMode(JackTrip::RTAUDIO);
741 }
742 #endif
743
744 // Chanfe default Sampling Rate
745 if (mChanfeDefaultSR) {
746 jackTrip->setSampleRate(mSampleRate);
747 }
748
749 // Chanfe defualt device ID
750 if (mChanfeDefaultID) {
751 jackTrip->setDeviceID(mDeviceID);
752 }
753
754 // Chanfe default Buffer Size
755 if (mChanfeDefaultBS) {
756 jackTrip->setAudioBufferSizeInSamples(mAudioBufferSize);
757 }
758 jackTrip->setBufferStrategy(mBufferStrategy);
759 jackTrip->setNetIssuesSimulation(mSimulatedLossRate,
760 mSimulatedJitterRate, mSimulatedDelayRel);
761 jackTrip->setBroadcast(mBroadcastQueue);
762 jackTrip->setUseRtUdpPriority(mUseRtUdpPriority);
763
764 // Add Plugins
765 if (mLoopBack) {
766 cout << "Running in Loop-Back Mode..." << endl;
767 cout << gPrintSeparator << std::endl;
768 //std::tr1::shared_ptr<LoopBack> loopback(new LoopBack(mNumChans));
769 //mJackTrip->appendProcessPlugin(loopback.get());
770
771 #if 0 // previous technique:
772 LoopBack* loopback = new LoopBack(mNumChans);
773 jackTrip->appendProcessPlugin(loopback);
774 #else // simpler method ( see AudioInterface.cpp callback() ):
775 jackTrip->setLoopBack(true);
776 #endif
777
778 // ----- Test Karplus Strong -----------------------------------
779 //std::tr1::shared_ptr<NetKS> loopback(new NetKS());
780 //mJackTrip->appendProcessPlugin(loopback);
781 //loopback->play();
782 //NetKS* netks = new NetKS;
783 //mJackTrip->appendProcessPlugin(netks);
784 //netks->play();
785 // -------------------------------------------------------------
786 }
787
788 if (mIOStatTimeout > 0) {
789 jackTrip->setIOStatTimeout(mIOStatTimeout);
790 jackTrip->setIOStatStream(mIOStatStream);
791 }
792
793 jackTrip->setAudioTesterP(&mAudioTester);
794
795 // Allocate audio effects in client, if any:
796 int nReservedChans = mAudioTester.getEnabled() ? 1 : 0; // no fx allowed on tester channel
797 std::vector<ProcessPlugin*> outgoingEffects = mEffects.allocateOutgoingEffects(mNumChans-nReservedChans);
798 for (auto p : outgoingEffects) {
799 jackTrip->appendProcessPluginToNetwork( p );
800 }
801 std::vector<ProcessPlugin*> incomingEffects = mEffects.allocateIncomingEffects(mNumChans-nReservedChans);
802 for (auto p : incomingEffects) {
803 jackTrip->appendProcessPluginFromNetwork( p );
804 }
805
806 #ifdef WAIR // WAIR
807 if ( mWAIR ) {
808 cout << "Running in WAIR Mode..." << endl;
809 cout << gPrintSeparator << std::endl;
810 switch ( mNumNetRevChans )
811 {
812 case 16 :
813 {
814 jackTrip->appendProcessPluginFromNetwork(new ap8x2(mNumChans)); // plugin slot 0
815 /////////////////////////////////////////////////////////
816 Stk16* plugin = new Stk16(mNumNetRevChans);
817 plugin->Stk16::initCombClient(mClientAddCombLen, mClientRoomSize);
818 jackTrip->appendProcessPluginFromNetwork(plugin); // plugin slot 1
463819 }
464 udpmaster->setBufferQueueLength(mBufferQueueLength);
465 udpmaster->start();
466
467 //---Thread Pool Test--------------------------------------------
468 /*
469 cout << "BEFORE START" << endl;
470 ThreadPoolTest* thtest = new ThreadPoolTest();
471 // QThreadPool takes ownership and deletes 'hello' automatically
472 QThreadPool::globalInstance()->start(thtest);
473
474 cout << "AFTER START" << endl;
475 sleep(2);
476 thtest->stop();
477 QThreadPool::globalInstance()->waitForDone();
478 */
479 //---------------------------------------------------------------
480 }
481
482 else {
483
484 //JackTrip jacktrip(mJackTripMode, mDataProtocol, mNumChans,
485 // mBufferQueueLength, mAudioBitResolution);
486 #ifdef WAIR // WAIR
487 if (gVerboseFlag) std::cout << "Settings:startJackTrip mNumNetRevChans = " << mNumNetRevChans << std::endl;
820 break;
821 default:
822 throw std::invalid_argument("Settings: mNumNetRevChans doesn't correspond to Faust plugin");
823 break;
824 }
825 break;
826 default:
827 throw std::invalid_argument("Settings: mNumNetRevChans doesn't correspond to Faust plugin");
828 break;
829 }
830 }
488831 #endif // endwhere
489 if (gVerboseFlag) std::cout << "Settings:startJackTrip before new JackTrip" << std::endl;
490 mJackTrip = new JackTrip(mJackTripMode, mDataProtocol, mNumChans,
491 #ifdef WAIR // wair
492 mNumNetRevChans,
493 #endif // endwhere
494 mBufferQueueLength, mRedundancy, mAudioBitResolution,
495 /*DataProtocol::packetHeaderTypeT PacketHeaderType = */DataProtocol::DEFAULT,
496 /*underrunModeT UnderRunMode = */ mUnderRunMode,
497 /* int receiver_bind_port = */ gDefaultPort,
498 /*int sender_bind_port = */ gDefaultPort,
499 /*int receiver_peer_port = */ gDefaultPort,
500 /* int sender_peer_port = */ gDefaultPort,
501 mPeerPortNum
502 );
503
504 // Set connect or not default audio ports. Only work for jack
505 mJackTrip->setConnectDefaultAudioPorts(mConnectDefaultAudioPorts);
506
507 // Connect Signals and Slots
508 QObject::connect(mJackTrip, SIGNAL( signalProcessesStopped() ),
509 this, SLOT( slotExitProgram() ));
510
511 // Change client name if different from default
512 if (mClientName != NULL) {
513 mJackTrip->setClientName(mClientName);
514 }
515
516 // Set buffers to zero when underrun
517 if ( mUnderrrunZero ) {
518 cout << "Setting buffers to zero when underrun..." << endl;
519 cout << gPrintSeparator << std::endl;
520 mJackTrip->setUnderRunMode(JackTrip::ZEROS);
521 } else {
522 cout << "Setting buffers to wavetable when underrun..." << endl;
523 cout << gPrintSeparator << std::endl;
524 mJackTrip->setUnderRunMode(JackTrip::WAVETABLE);
525 }
526
527 // Set peer address in server mode
528 if ( mJackTripMode == JackTrip::CLIENT || mJackTripMode == JackTrip::CLIENTTOPINGSERVER ) {
529 mJackTrip->setPeerAddress(mPeerAddress.toLatin1().data()); }
530
531 // if(mLocalAddress!=QString()) // default
532 // mJackTrip->setLocalAddress(QHostAddress(mLocalAddress.toLatin1().data()));
533 // else
534 // mJackTrip->setLocalAddress(QHostAddress::Any);
535
536 // Set Ports
537 //cout << "SETTING ALL PORTS" << endl;
538 if (gVerboseFlag) std::cout << "Settings:startJackTrip before mJackTrip->setBindPorts" << std::endl;
539 mJackTrip->setBindPorts(mBindPortNum);
540 if (gVerboseFlag) std::cout << "Settings:startJackTrip before mJackTrip->setPeerPorts" << std::endl;
541 mJackTrip->setPeerPorts(mPeerPortNum);
542
543 // Set in JamLink Mode
544 if ( mJamLink ) {
545 cout << "Running in JamLink Mode..." << endl;
546 cout << gPrintSeparator << std::endl;
547 mJackTrip->setPacketHeaderType(DataProtocol::JAMLINK);
548 }
549
550 // Set in EmptyHeader Mode
551 if ( mEmptyHeader ) {
552 cout << "Running in EmptyHeader Mode..." << endl;
553 cout << gPrintSeparator << std::endl;
554 mJackTrip->setPacketHeaderType(DataProtocol::EMPTY);
555 }
556
557 // Set RtAudio
558 #ifdef __RT_AUDIO__
559 if (!mUseJack) {
560 mJackTrip->setAudiointerfaceMode(JackTrip::RTAUDIO);
561 }
562 #endif
563
564 // Chanfe default Sampling Rate
565 if (mChanfeDefaultSR) {
566 mJackTrip->setSampleRate(mSampleRate);
567 }
568
569 // Chanfe defualt device ID
570 if (mChanfeDefaultID) {
571 mJackTrip->setDeviceID(mDeviceID);
572 }
573
574 // Chanfe default Buffer Size
575 if (mChanfeDefaultBS) {
576 mJackTrip->setAudioBufferSizeInSamples(mAudioBufferSize);
577 }
578
579 // Add Plugins
580 if ( mLoopBack ) {
581 cout << "Running in Loop-Back Mode..." << endl;
582 cout << gPrintSeparator << std::endl;
583 //std::tr1::shared_ptr<LoopBack> loopback(new LoopBack(mNumChans));
584 //mJackTrip->appendProcessPlugin(loopback.get());
585
586 LoopBack* loopback = new LoopBack(mNumChans);
587 mJackTrip->appendProcessPlugin(loopback);
588
589 // ----- Test Karplus Strong -----------------------------------
590 //std::tr1::shared_ptr<NetKS> loopback(new NetKS());
591 //mJackTrip->appendProcessPlugin(loopback);
592 //loopback->play();
593 //NetKS* netks = new NetKS;
594 //mJackTrip->appendProcessPlugin(netks);
595 //netks->play();
596 // -------------------------------------------------------------
597 }
598
599 #ifdef WAIR // WAIR
600 if ( mWAIR ) {
601 cout << "Running in WAIR Mode..." << endl;
602 cout << gPrintSeparator << std::endl;
603 switch ( mNumNetRevChans )
604 {
605 case 16 :
606 {
607 mJackTrip->appendProcessPlugin(new ap8x2(mNumChans)); // plugin slot 0
608 /////////////////////////////////////////////////////////
609 Stk16* plugin = new Stk16(mNumNetRevChans);
610 plugin->Stk16::initCombClient(mClientAddCombLen, mClientRoomSize);
611 mJackTrip->appendProcessPlugin(plugin); // plugin slot 1
612 }
613 break;
614 default:
615 throw std::invalid_argument("Settings: mNumNetRevChans doesn't correspond to Faust plugin");
616 break;
617 }
618 }
619 #endif // endwhere
620
621 // Start JackTrip
622 if (gVerboseFlag) std::cout << "Settings:startJackTrip before mJackTrip->startProcess" << std::endl;
623 mJackTrip->startProcess(
624 #ifdef WAIRTOHUB // WAIR
625 0 // for WAIR compatibility, ID in jack client name
626 #endif // endwhere
627 );
628 if (0 < getIOStatTimeout()) {
629 mJackTrip->startIOStatTimer(getIOStatTimeout(), getIOStatStream());
630 }
631 // if (gVerboseFlag) std::cout << "Settings:startJackTrip before mJackTrip->start" << std::endl;
632 // this is a noop
633 // mJackTrip->start();
634
635 /*
636 sleep(10);
637 cout << "Stoping JackTrip..." << endl;
638 mJackTrip->stop();
639 */
640 }
832
833 return jackTrip;
641834 }
642
643
644 //*******************************************************************************
645 void Settings::stopJackTrip()
646 {
647 mJackTrip->stop();
648 }
4040
4141 #include <cstdlib>
4242 #include <fstream>
43 #include <vector>
4344
4445 #include "DataProtocol.h"
4546
4849 #endif //__NO_JACK__
4950
5051 #include "JackTrip.h"
52 #include "UdpHubListener.h"
53
54 #include "Effects.h"
55 #include "AudioTester.h"
5156
5257 /** \brief Class to set usage options and parse settings from input
5358 */
54 class Settings : public QThread
59 class Settings : public QObject
5560 {
5661 Q_OBJECT;
5762
6267 /// \brief Parses command line input
6368 void parseInput(int argc, char** argv);
6469
65 void startJackTrip();
66 void stopJackTrip();
70 UdpHubListener *getConfiguredHubServer();
71 JackTrip *getConfiguredJackTrip();
6772
6873 /// \brief Prints usage help
6974 void printUsage();
7075
7176 bool getLoopBack() { return mLoopBack; }
72 int getIOStatTimeout() const {return mIOStatTimeout;}
73 const std::ostream& getIOStatStream() const
74 {
75 return mIOStatStream.is_open() ? (std::ostream&)mIOStatStream : std::cout;
76 }
77
78
79 public slots:
80 void slotExitProgram()
81 {
82 std::cerr << "Exiting JackTrip..." << std::endl;
83 std::exit(1);
84 }
77 bool isHubServer() { return mJackTripServer; }
8578
8679 private:
87 JackTrip* mJackTrip; ///< JackTrip class
8880 JackTrip::jacktripModeT mJackTripMode; ///< JackTrip::jacktripModeT
8981 JackTrip::dataProtocolT mDataProtocol; ///< Data Protocol
9082 int mNumChans; ///< Number of Channels (inputs = outputs)
9486 int mBindPortNum; ///< Bind Port Number
9587 int mPeerPortNum; ///< Peer Port Number
9688 int mServerUdpPortNum;
97 char* mClientName; ///< JackClient Name
98 bool mUnderrrunZero; ///< Use Underrun to Zero mode
99 JackTrip::underrunModeT mUnderRunMode;
89 QString mClientName; ///< JackClient Name
90 QString mRemoteClientName;
91 JackTrip::underrunModeT mUnderrunMode; ///< Underrun mode
92 bool mStopOnTimeout; /// < Stop jacktrip after 10 second network timeout
93 int mBufferStrategy;
10094
10195 #ifdef WAIR // wair
10296 int mNumNetRevChans; ///< Number of Network Audio Channels (net comb filters)
121115 unsigned int mHubConnectionMode;
122116 bool mConnectDefaultAudioPorts; ///< Connect or not jack audio ports
123117 int mIOStatTimeout;
124 std::ofstream mIOStatStream;
118 QSharedPointer<std::ofstream> mIOStatStream;
119 Effects mEffects;
120 double mSimulatedLossRate;
121 double mSimulatedJitterRate;
122 double mSimulatedDelayRel;
123 int mBroadcastQueue;
124 bool mUseRtUdpPriority;
125 AudioTester mAudioTester;
125126 };
126127
127128 #endif
5252 #endif
5353 #if defined (__LINUX__) || (__MAC_OSX__)
5454 #include <sys/socket.h> // for POSIX Sockets
55 #include <unistd.h>
56 #include <sys/fcntl.h>
5557 #endif
5658
5759 using std::cout; using std::endl;
7173 mBindPort(bind_port), mPeerPort(peer_port),
7274 mRunMode(runmode),
7375 mAudioPacket(NULL), mFullPacket(NULL),
74 mUdpRedundancyFactor(udp_redundancy_factor)
76 mUdpRedundancyFactor(udp_redundancy_factor),
77 mControlPacketSize(63),
78 mStopSignalSent(false)
7579 {
7680 mStopped = false;
7781 mIPv6 = false;
8488 QObject::connect(this, SIGNAL(signalWaitingTooLong(int)),
8589 jacktrip, SLOT(slotUdpWaitingTooLongClientGoneProbably(int)), Qt::QueuedConnection);
8690 }
91 mSimulatedLossRate = 0.0;
92 mSimulatedJitterRate = 0.0;
93 mSimulatedJitterMaxDelay = 0.0;
8794 }
8895
8996
9299 {
93100 delete[] mAudioPacket;
94101 delete[] mFullPacket;
102 if (mRunMode == RECEIVER) {
103 #ifdef __WIN_32__
104 closesocket(mSocket);
105 #else
106 ::close(mSocket);
107 #endif
108 }
95109 wait();
96110 }
97111
120134 if ( mPeerAddress.protocol() == QAbstractSocket::IPv6Protocol ) {
121135 mIPv6 = true;
122136 } else if ( mPeerAddress.protocol() != QAbstractSocket::IPv4Protocol ) {
123 QString error_message = "Incorrect presentation format address\n '";
137 QString error_message = "Incorrect presentation format address\n'";
124138 error_message.append(peerHostOrIP);
125139 error_message.append("' is not a valid IP address or Host Name");
126140 //std::cerr << "ERROR: Incorrect presentation format address" << endl;
162176 if (socket == -1) {
163177 #endif
164178 try {
165 if (gVerboseFlag) std::cout << " UdpDataProtocol:run" << mRunMode << " before bindSocket(UdpSocket)" << std::endl;
179 if (gVerboseFlag) std::cout << " UdpDataProtocol:run" << mRunMode << " before bindSocket" << std::endl;
166180 socket = bindSocket(); // Bind Socket
167181 } catch ( const std::exception & e ) {
168182 emit signalError( e.what() );
315329
316330
317331 //*******************************************************************************
318 int UdpDataProtocol::receivePacket(QUdpSocket& UdpSocket, char* buf, const size_t n)
332 int UdpDataProtocol::receivePacket(char* buf, const size_t n)
319333 {
320334 // Block until There's something to read
321 while ( (UdpSocket.pendingDatagramSize() < n) && !mStopped ) { QThread::usleep(100); }
322 int n_bytes = UdpSocket.readDatagram(buf, n);
335 while ( !datagramAvailable() && !mStopped ) {
336 QThread::usleep(100);
337 }
338 int n_bytes = ::recv(mSocket, buf, n, 0);
339 if (n_bytes == mControlPacketSize) {
340 //Control signal (currently just check for exit packet);
341 bool exit = true;
342 for (int i = 0; i < mControlPacketSize; i++) {
343 if (buf[i] != char(0xff)) {
344 exit = false;
345 i = mControlPacketSize;
346 }
347 }
348 if (exit && !mStopSignalSent) {
349 mStopSignalSent = true;
350 emit signalCeaseTransmission("Peer Stopped");
351 std::cout << "Peer Stopped" <<std::endl;
352 }
353 return 0;
354 }
323355 return n_bytes;
324356 }
325357
357389
358390
359391 //*******************************************************************************
360 void UdpDataProtocol::getPeerAddressFromFirstPacket(QUdpSocket& UdpSocket,
361 QHostAddress& peerHostAddress,
392 void UdpDataProtocol::getPeerAddressFromFirstPacket(QHostAddress& peerHostAddress,
362393 uint16_t& port)
363394 {
364 while ( !UdpSocket.hasPendingDatagrams() ) {
395 while ( !datagramAvailable() ) {
365396 msleep(100);
366397 }
367398 char buf[1];
368 UdpSocket.readDatagram(buf, 1, &peerHostAddress, &port);
399
400 struct sockaddr_storage addr;
401 std::memset(&addr, 0, sizeof(addr));
402 socklen_t sa_len = sizeof(addr);
403 ::recvfrom(mSocket, buf, 1, 0, (struct sockaddr*) &addr, &sa_len);
404 peerHostAddress.setAddress((struct sockaddr*) &addr);
405 if (mIPv6) {
406 port = ((struct sockaddr_in6*) &addr)->sin6_port;
407 } else {
408 port = ((struct sockaddr_in*) &addr)->sin_port;
409 }
369410 }
370411
371412
387428 // mJackTrip, SLOT(slotStopProcesses()),
388429 // Qt::QueuedConnection);
389430
390 //Wrap our socket in a QUdpSocket object if we're the receiver, for convenience.
391 //If we're the sender, we'll just write directly to our socket.
392 QUdpSocket UdpSocket;
393431 if (mRunMode == RECEIVER) {
394 if (mIPv6) {
395 UdpSocket.setSocketDescriptor(mSocket, QUdpSocket::BoundState,
396 QUdpSocket::ReadOnly);
397 } else {
398 UdpSocket.setSocketDescriptor(mSocket, QUdpSocket::ConnectedState,
399 QUdpSocket::ReadOnly);
400 }
401432 cout << "UDP Socket Receiving in Port: " << mBindPort << endl;
402433 cout << gPrintSeparator << endl;
434 //Make sure our socket is in non-blocking mode.
435 #ifdef __WIN_32__
436 u_long nonblock = 1;
437 ioctlsocket(mSocket, FIONBIO, &nonblock);
438 #else
439 int flags = ::fcntl(mSocket, F_GETFL, 0);
440 ::fcntl(mSocket, F_SETFL, flags | O_NONBLOCK);
441 #endif
403442 }
404443
405444 if (gVerboseFlag) std::cout << " UdpDataProtocol:run" << mRunMode << " before Setup Audio Packet buffer, Full Packet buffer, Redundancy Variables" << std::endl;
408447 //cout << "audio_packet_size: " << audio_packet_size << endl;
409448 mAudioPacket = new int8_t[audio_packet_size];
410449 std::memset(mAudioPacket, 0, audio_packet_size); // set buffer to 0
450 mBuffer.resize(audio_packet_size, 0);
451 mChans = mJackTrip->getNumChannels();
452 mSmplSize = mJackTrip->getAudioBitResolution() / 8;
411453
412454 // Setup Full Packet buffer
413455 int full_packet_size = mJackTrip->getPacketSizeInBytes();
424466 // (Algorithm explained at the end of this file)
425467 // ---------------------------------------------
426468 int full_redundant_packet_size = full_packet_size * mUdpRedundancyFactor;
427 int8_t* full_redundant_packet;
428 full_redundant_packet = new int8_t[full_redundant_packet_size];
429 std::memset(full_redundant_packet, 0, full_redundant_packet_size); // Initialize to 0
469 int8_t* full_redundant_packet = NULL;
430470
431471 // Set realtime priority (function in jacktrip_globals.h)
432472 if (gVerboseFlag) std::cout << " UdpDataProtocol:run" << mRunMode << " before setRealtimeProcessPriority()" << std::endl;
433473 //std::cout << "Experimental version -- not using setRealtimeProcessPriority()" << std::endl;
434 //setRealtimeProcessPriority();
474 // Anton Runov: making setRealtimeProcessPriority optional
475 if (mUseRtPriority) {
476 setRealtimeProcessPriority();
477 }
435478
436479 /////////////////////
437480 // to see thread priorities
506549 if (gVerboseFlag) std::cout << " UdpDataProtocol:run" << mRunMode << " before !UdpSocket.hasPendingDatagrams()" << std::endl;
507550 std::cout << "Waiting for Peer..." << std::endl;
508551 // This blocks waiting for the first packet
509 while ( !UdpSocket.hasPendingDatagrams() ) {
552 while ( !datagramAvailable() ) {
510553 if (mStopped) { return; }
511554 QThread::msleep(100);
512555 if (gVerboseFlag) std::cout << "100ms " << std::flush;
513556 }
514 int first_packet_size = UdpSocket.pendingDatagramSize();
515 // The following line is the same as
516 int8_t* first_packet = new int8_t[first_packet_size];
517 /// \todo fix this to avoid memory leaks
518 // but avoids memory leaks
519 //std::tr1::shared_ptr<int8_t> first_packet(new int8_t[first_packet_size]);
520 receivePacket( UdpSocket, reinterpret_cast<char*>(first_packet), first_packet_size);
557 full_redundant_packet_size = 0x10000; // max UDP datagram size
558 full_redundant_packet = new int8_t[full_redundant_packet_size];
559 full_redundant_packet_size = receivePacket(reinterpret_cast<char*>(full_redundant_packet), full_redundant_packet_size);
521560 // Check that peer has the same audio settings
522561 if (gVerboseFlag) std::cout << std::endl << " UdpDataProtocol:run" << mRunMode << " before mJackTrip->checkPeerSettings()" << std::endl;
523 mJackTrip->checkPeerSettings(first_packet);
562 mJackTrip->checkPeerSettings(full_redundant_packet);
563
564 int peer_chans = mJackTrip->getPeerNumChannels(full_redundant_packet);
565 full_packet_size = mJackTrip->getHeaderSizeInBytes()
566 + mJackTrip->getPeerBufferSize(full_redundant_packet) * peer_chans * mSmplSize;
567 /*
568 cout << "peer sizes: " << mJackTrip->getHeaderSizeInBytes()
569 << " + " << mJackTrip->getPeerBufferSize(full_redundant_packet)
570 << " * " << mJackTrip->getNumChannels() << " * " << (int)mJackTrip->getAudioBitResolution()/8 << endl;
571 cout << "full_packet_size: " << full_packet_size << " / " << mJackTrip->getPacketSizeInBytes() << endl;
572 cout << "full_redundant_packet_size: " << full_redundant_packet_size << endl;
573 // */
574
524575 if (gVerboseFlag) std::cout << "step 7" << std::endl;
525576 if (gVerboseFlag) std::cout << " UdpDataProtocol:run" << mRunMode << " before mJackTrip->parseAudioPacket()" << std::endl;
526 mJackTrip->parseAudioPacket(mFullPacket, mAudioPacket);
527577 std::cout << "Received Connection from Peer!" << std::endl;
528578 emit signalReceivedConnectionFromPeer();
529579
537587 mTotCount = 0;
538588 mLostCount = 0;
539589 mOutOfOrderCount = 0;
590 mLastOutOfOrderCount = 0;
591 mInitialState = true;
540592 mRevivedCount = 0;
541593 mStatCount = 0;
542594
549601 // arrive for a longer time
550602 //timeout = UdpSocket.waitForReadyRead(30);
551603 // timeout = cc unused!
552 waitForReady(UdpSocket, 60000); //60 seconds
604 waitForReady(60000); //60 seconds
553605
554606 // OLD CODE WITHOUT REDUNDANCY----------------------------------------------------
555607 /*
564616 mJackTrip->writeAudioBuffer(mAudioPacket);
565617 */
566618 //----------------------------------------------------------------------------------
567 receivePacketRedundancy(UdpSocket,
568 full_redundant_packet,
619 receivePacketRedundancy(full_redundant_packet,
569620 full_redundant_packet_size,
570621 full_packet_size,
571622 current_seq_num,
575626 break; }
576627
577628 case SENDER : {
578 while ( !mStopped )
629 full_redundant_packet = new int8_t[full_redundant_packet_size];
630 std::memset(full_redundant_packet, 0, full_redundant_packet_size); // Initialize to 0
631 while ( !mStopped && !JackTrip::sSigInt && !JackTrip::sJackStopped )
579632 {
580633 // OLD CODE WITHOUT REDUNDANCY -----------------------------------------------------
581634 /*
591644 full_redundant_packet_size,
592645 full_packet_size);
593646 }
647
648 // Send exit packet (with 1 redundant packet).
649 cout << "sending exit packet" << endl;
650 QByteArray exitPacket = QByteArray(mControlPacketSize, 0xff);
651 sendPacket(exitPacket.constData(), mControlPacketSize);
652 sendPacket(exitPacket.constData(), mControlPacketSize);
653 emit signalCeaseTransmission();
594654 break; }
595655 }
656
657 if (NULL != full_redundant_packet) {
658 delete[] full_redundant_packet;
659 full_redundant_packet = NULL;
660 }
596661 }
597662
598663
599664 //*******************************************************************************
600665 //bool
601 void UdpDataProtocol::waitForReady(QUdpSocket& UdpSocket, int timeout_msec)
666 void UdpDataProtocol::waitForReady(int timeout_msec)
602667 {
603668 int loop_resolution_usec = 100; // usecs to wait on each loop
604669 int emit_resolution_usec = 10000; // 10 milliseconds
605670 int timeout_usec = timeout_msec * 1000;
606671 int elapsed_time_usec = 0; // Ellapsed time in milliseconds
607672
608 while ( ( !(
609 UdpSocket.hasPendingDatagrams() &&
610 (UdpSocket.pendingDatagramSize() > 0)
611 ) && (elapsed_time_usec <= timeout_usec) )
673 while ( !datagramAvailable()
674 && (elapsed_time_usec <= timeout_usec)
612675 && !mStopped ){
613676 // if (mStopped) { return false; }
614677 QThread::usleep(loop_resolution_usec);
634697 int wait_time = 30; // msec
635698 if ( !(wait_msec%wait_time) ) {
636699 std::cerr << "UDP waiting too long (more than " << wait_time << "ms) for " << mPeerAddress.toString().toStdString() << "..." << endl;
637 }
638 }
639
640
641 //*******************************************************************************
642 void UdpDataProtocol::receivePacketRedundancy(QUdpSocket& UdpSocket,
643 int8_t* full_redundant_packet,
700 emit signalUdpWaitingTooLong();
701 }
702 }
703
704
705 //*******************************************************************************
706 void UdpDataProtocol::receivePacketRedundancy(int8_t* full_redundant_packet,
644707 int full_redundant_packet_size,
645708 int full_packet_size,
646709 uint16_t& current_seq_num,
648711 uint16_t& newer_seq_num)
649712 {
650713 // This is blocking until we get a packet...
651 receivePacket( UdpSocket, reinterpret_cast<char*>(full_redundant_packet),
652 full_redundant_packet_size);
714 if (receivePacket( reinterpret_cast<char*>(full_redundant_packet),
715 full_redundant_packet_size) == 0) {
716 return;
717 }
718
719 if (0.0 < mSimulatedLossRate || 0.0 < mSimulatedJitterRate) {
720 double x = mUniformDist(mRndEngine);
721 // Drop packets
722 x -= mSimulatedLossRate;
723 if (0 > x) {
724 return;
725 }
726 // Delay packets
727 x -= mSimulatedJitterRate;
728 if (0 > x) {
729 usleep(mUniformDist(mRndEngine) * mSimulatedJitterMaxDelay * 1e6);
730 }
731 }
653732
654733 // Get Packet Sequence Number
655734 newer_seq_num =
656735 mJackTrip->getPeerSequenceNumber(full_redundant_packet);
657736 current_seq_num = newer_seq_num;
658737
659 if (0 != last_seq_num) {
660 int16_t lost = newer_seq_num - last_seq_num - 1;
661 if (0 > lost) {
738 int16_t lost = 0;
739 if (!mInitialState) {
740 lost = newer_seq_num - last_seq_num - 1;
741 if (0 > lost || 1000 < lost) {
662742 // Out of order packet, should be ignored
663743 ++mOutOfOrderCount;
744 if (5 < ++mLastOutOfOrderCount) {
745 mInitialState = true;
746 mStatCount = 0;
747 mTotCount = 0;
748 }
664749 return;
665750 }
666751 else if (0 != lost) {
668753 }
669754 mTotCount += 1 + lost;
670755 }
756 mLastOutOfOrderCount = 0;
757 mInitialState = false;
671758
672759 //cout << current_seq_num << " ";
673760 int redun_last_index = 0;
686773 mRevivedCount += redun_last_index;
687774 //cout << endl;
688775
776 int peer_chans = mJackTrip->getPeerNumChannels(full_redundant_packet);
777 int N = mJackTrip->getPeerBufferSize(full_redundant_packet);
778 int host_buf_size = N * mChans * mSmplSize;
779 int hdr_size = mJackTrip->getHeaderSizeInBytes();
780 int gap_size = mInitialState ? 0 : (lost - redun_last_index) * host_buf_size;
781
689782 last_seq_num = newer_seq_num; // Save last read packet
690783
784 if ((int)mBuffer.size() < host_buf_size) {
785 mBuffer.resize(host_buf_size, 0);
786 }
691787 // Send to audio all available audio packets, in order
692788 for (int i = redun_last_index; i>=0; i--) {
693 memcpy(mFullPacket,
694 full_redundant_packet + (i*full_packet_size),
695 full_packet_size);
696 mJackTrip->parseAudioPacket(mFullPacket, mAudioPacket);
697 mJackTrip->writeAudioBuffer(mAudioPacket);
789 int8_t* src = full_redundant_packet + (i*full_packet_size) + hdr_size;
790 if (1 != mChans) {
791 // Convert packet's non-interleaved layout to interleaved one used internally
792 int8_t* dst = mBuffer.data();
793 int C = qMin(mChans, peer_chans);
794 for (int n=0; n<N; ++n) {
795 for (int c=0; c<C; ++c) {
796 memcpy(dst + (n*mChans + c)*mSmplSize, src + (n + c*N)*mSmplSize, mSmplSize);
797 }
798 }
799 src = dst;
800 }
801 if (!mJackTrip->writeAudioBuffer(src, host_buf_size, gap_size)) {
802 emit signalError("Local and Peer buffer settings are incompatible");
803 cout << "ERROR: Local and Peer buffer settings are incompatible" << endl;
804 mStopped = true;
805 break;
806 }
807 gap_size = 0;
698808 }
699809 }
700810
715825 }
716826
717827 //*******************************************************************************
828 void UdpDataProtocol::setIssueSimulation(double loss, double jitter, double max_delay)
829 {
830 mSimulatedLossRate = loss;
831 mSimulatedJitterRate = jitter;
832 mSimulatedJitterMaxDelay = max_delay;
833
834 std::random_device r;
835 mRndEngine = std::default_random_engine(r());
836 mUniformDist = std::uniform_real_distribution<double>(0.0, 1.0);
837
838 cout << "Simulating network issues: "
839 "loss_rate=" << loss << ", jitter_rate=" << jitter << ", jitter_max_delay=" << max_delay << endl;
840 }
841
842 //*******************************************************************************
718843 void UdpDataProtocol::sendPacketRedundancy(int8_t* full_redundant_packet,
719844 int full_redundant_packet_size,
720845 int full_packet_size)
721846 {
722847 mJackTrip->readAudioBuffer( mAudioPacket );
723 mJackTrip->putHeaderInPacket(mFullPacket, mAudioPacket);
848 int8_t* src = mAudioPacket;
849 if (1 != mChans) {
850 // Convert internal interleaved layout to non-interleaved
851 int N = getAudioPacketSizeInBites() / mChans / mSmplSize;
852 int8_t* dst = mBuffer.data();
853 for (int n=0; n<N; ++n) {
854 for (int c=0; c<mChans; ++c) {
855 memcpy(dst + (n + c*N)*mSmplSize, src + (n*mChans + c)*mSmplSize, mSmplSize);
856 }
857 }
858 src = dst;
859 }
860 mJackTrip->putHeaderInPacket(mFullPacket, src);
724861
725862 // Move older packets to end of array of redundant packets
726863 std::memmove(full_redundant_packet+full_packet_size,
783920 If it has more than one packet that it hasn't yet received, it sends it to the soundcard
784921 one by one.
785922 */
923
924 bool UdpDataProtocol::datagramAvailable()
925 {
926 //Currently using a simplified version of the way QUdpSocket checks for datagrams.
927 //TODO: Consider changing to use poll() or select().
928 char c;
929 #if defined (__WIN_32__)
930 //Need to use the winsock version of the function for MSG_PEEK
931 WSABUF buffer;
932 buffer.buf = &c;
933 buffer.len = sizeof(c);
934 DWORD n = 0;
935 DWORD flags = MSG_PEEK;
936 int ret = WSARecv(mSocket, &buffer, 1, &n, &flags, NULL, NULL);
937 if (ret == 0) {
938 //True if no error,
939 return true;
940 } else {
941 //or if our error is that our buffer is too small.
942 int err = WSAGetLastError();
943 return (err == WSAEMSGSIZE);
944 }
945 #else
946 ssize_t n;
947 n = ::recv(mSocket, &c, sizeof(c), MSG_PEEK);
948 //We have a datagram if our buffer is too small or if no error.
949 return (n != -1 || errno == EMSGSIZE);
950 #endif
951 }
4040 #include <stdexcept>
4141
4242 #include <QThread>
43 #include <QUdpSocket>
4443 #include <QHostAddress>
4544 #include <QMutex>
45 #include <vector>
46 #include <random>
4647
4748 #include "DataProtocol.h"
4849 #include "jacktrip_types.h"
103104 * \return number of bytes read, -1 on error
104105 */
105106 //virtual int receivePacket(char* buf, const size_t n);
106 virtual int receivePacket(QUdpSocket& UdpSocket, char* buf, const size_t n);
107 virtual int receivePacket(char* buf, const size_t n);
107108
108109 /** \brief Sends a packet
109110 *
120121 * \param peerHostAddress QHostAddress to store the peer address
121122 * \param port Receiving port
122123 */
123 virtual void getPeerAddressFromFirstPacket(QUdpSocket& UdpSocket,
124 QHostAddress& peerHostAddress,
124 virtual void getPeerAddressFromFirstPacket(QHostAddress& peerHostAddress,
125125 uint16_t& port);
126126
127127 /** \brief Sets the bind port number
142142 virtual void run();
143143
144144 virtual bool getStats(PktStat* stat);
145 virtual void setIssueSimulation(double loss, double jitter, double max_delay);
145146
146147 private slots:
147148 void printUdpWaitedTooLong(int wait_msec);
148
149
149150
150151 signals:
151152
152153 /// \brief Signals when waiting every 10 milliseconds, with the total wait on wait_msec
153154 /// \param wait_msec Total wait in milliseconds
154155 void signalWaitingTooLong(int wait_msec);
155
156 void signalUdpWaitingTooLong();
156157
157158 //private:
158159 protected:
166167 #endif
167168
168169 /** \brief This function blocks until data is available for reading in the
169 * QUdpSocket. The function will timeout after timeout_msec microseconds.
170 * socket. The function will timeout after timeout_msec microseconds.
170171 *
171172 * This function is intended to replace QAbstractSocket::waitForReadyRead which has
172173 * some problems with multithreading.
174175 * \return returns true if there is data available for reading;
175176 * otherwise it returns false (if an error occurred or the operation timed out)
176177 */
177 void waitForReady(QUdpSocket& UdpSocket, int timeout_msec);
178 void waitForReady(int timeout_msec);
178179
179180 /** \brief Redundancy algorythm at the receiving end
180181 */
181 virtual void receivePacketRedundancy(QUdpSocket& UdpSocket,
182 int8_t* full_redundant_packet,
182 virtual void receivePacketRedundancy(int8_t* full_redundant_packet,
183183 int full_redundant_packet_size,
184184 int full_packet_size,
185185 uint16_t& current_seq_num,
192192 int full_redundant_packet_size,
193193 int full_packet_size);
194194
195
196195 private:
197
196 bool datagramAvailable();
197
198198 int mBindPort; ///< Local Port number to Bind
199199 int mPeerPort; ///< Peer Port number
200200 const runModeT mRunMode; ///< Run mode, either SENDER or RECEIVER
211211
212212 int8_t* mAudioPacket; ///< Buffer to store Audio Packets
213213 int8_t* mFullPacket; ///< Buffer to store Full Packet (audio+header)
214 std::vector<int8_t> mBuffer;
215 int mChans;
216 int mSmplSize;
217 int mLastOutOfOrderCount;
218 bool mInitialState;
214219
215220 unsigned int mUdpRedundancyFactor; ///< Factor of redundancy
216221 static QMutex sUdpMutex; ///< Mutex to make thread safe the binding process
220225 std::atomic<uint32_t> mOutOfOrderCount;
221226 std::atomic<uint32_t> mRevivedCount;
222227 uint32_t mStatCount;
228
229 uint8_t mControlPacketSize;
230 bool mStopSignalSent;
231
232 // packet loss/jitter simulation
233 double mSimulatedLossRate;
234 double mSimulatedJitterRate;
235 double mSimulatedJitterMaxDelay;
236 std::default_random_engine mRndEngine;
237 std::uniform_real_distribution<double> mUniformDist;
223238 };
224239
225240 #endif // __UDPDATAPROTOCOL_H__
5050
5151 using std::cout; using std::endl;
5252
53 bool UdpHubListener::sSigInt = false;
5354
5455 //*******************************************************************************
5556 UdpHubListener::UdpHubListener(int server_port, int server_udp_port) :
5657 //mJTWorker(NULL),
58 mTcpServer(this),
5759 mServerPort(server_port),
5860 mServerUdpPort(server_udp_port),//final udp base port number
5961 mStopped(false),
6163 mWAIR(false),
6264 #endif // endwhere
6365 mTotalRunningThreads(0),
64 m_connectDefaultAudioPorts(false)
65 {
66 // Register JackTripWorker with the master listener
66 mHubPatchDescriptions({"server-to-clients", "client loopback", "client fan out/in but not loopback",
67 "reserved for TUB", "full mix", "no auto patching"}),
68 m_connectDefaultAudioPorts(false),
69 mIOStatTimeout(0)
70 {
71 // Register JackTripWorker with the hub listener
6772 //mJTWorker = new JackTripWorker(this);
6873 mJTWorkers = new QVector<JackTripWorker*>;
6974 for (int i = 0; i<gMaxThreads; i++) {
8792
8893 // SoundWIRE ports open are UDP 61002-62000
8994 // (server_port - gDefaultPort) apply TCP offset to UDP too
90 if (mServerUdpPort != NULL){
95 if (mServerUdpPort != 0){
9196 mBasePort = mServerUdpPort;
9297 } else {
9398 mBasePort = 61002 + (server_port - gDefaultPort);
97102
98103 mUnderRunMode = JackTrip::WAVETABLE;
99104 mBufferQueueLength = gDefaultQueueLength;
105
106 mBufferStrategy = 1;
107 mBroadcastQueue = 0;
108 mSimulatedLossRate = 0.0;
109 mSimulatedJitterRate = 0.0;
110 mSimulatedDelayRel = 0.0;
111
112 mUseRtUdpPriority = false;
100113 }
101114
102115
118131 // the client is already on the thread pool, it means that a new connection is
119132 // requested (the old was desconnected). So we have to remove that thread from
120133 // the pool and then connect again.
121 void UdpHubListener::run()
134 void UdpHubListener::start()
122135 {
123136 mStopped = false;
124137
125 QHostAddress PeerAddress; // Object to store peer address
126 uint16_t peer_udp_port; // Peer listening port
127 int server_udp_port; // Server assigned udp port
128
129 // Create and bind the TCP server
138 // Bind the TCP server
130139 // ------------------------------
131 QTcpServer TcpServer;
132 if ( !TcpServer.listen(QHostAddress::Any, mServerPort) ) {
133 std::cerr << "TCP Socket Server ERROR on Port " << mServerPort << ": " << TcpServer.errorString().toStdString() << endl;
134 std::exit(1);
135 }
136
137 const int tcpTimeout = 5*1000;
138
139
140 cout << "JackTrip HUB SERVER: TCP Server Listening in Port = " << TcpServer.serverPort() << endl;
141 while ( !mStopped )
140 QObject::connect(&mTcpServer, &QTcpServer::newConnection, this, &UdpHubListener::receivedNewConnection);
141 if ( !mTcpServer.listen(QHostAddress::Any, mServerPort) ) {
142 QString error_message = QString("TCP Socket Server on Port %1 ERROR: %2").arg(mServerPort).arg(mTcpServer.errorString());
143 std::cerr << error_message.toStdString() << endl;
144 emit signalError(error_message);
145 return;
146 }
147
148 cout << "JackTrip HUB SERVER: Waiting for client connections..." << endl;
149 cout << "JackTrip HUB SERVER: Hub auto audio patch setting = " << mHubPatch
150 << " (" << mHubPatchDescriptions.at(mHubPatch).toStdString() << ")" << endl;
151 cout << "=======================================================" << endl;
152
153 // Start our monitoring timer
154 mStopCheckTimer.setInterval(200);
155 connect(&mStopCheckTimer, &QTimer::timeout, this, &UdpHubListener::stopCheck);
156 mStopCheckTimer.start();
157 }
158
159 void UdpHubListener::receivedNewConnection()
160 {
161 QTcpSocket *clientSocket = mTcpServer.nextPendingConnection();
162 connect(clientSocket, &QAbstractSocket::readyRead, this, [=]{
163 receivedClientInfo(clientSocket);
164 });
165 cout << "JackTrip HUB SERVER: Client Connection Received!" << endl;
166 }
167
168 void UdpHubListener::receivedClientInfo(QTcpSocket *clientConnection)
169 {
170 QHostAddress PeerAddress = clientConnection->peerAddress();
171 cout << "JackTrip HUB SERVER: Client Connect Received from Address : "
172 << PeerAddress.toString().toStdString() << endl;
173
174 // Get UDP port from client
175 // ------------------------
176 QString clientName = QString();
177 cout << "JackTrip HUB SERVER: Reading UDP port from Client..." << endl;
178 if (clientConnection->bytesAvailable() < (qint64)sizeof(uint16_t)) {
179 // We don't have enough data. Wait for the next readyRead notification.
180 return;
181 }
182 uint16_t peer_udp_port= readClientUdpPort(clientConnection, clientName);
183
184 cout << "JackTrip HUB SERVER: Client UDP Port is = " << peer_udp_port << endl;
185 if ( peer_udp_port == 0 || peer_udp_port < gBindPortLow || peer_udp_port > gBindPortHigh ) {
186 cout << "JackTrip HUB SERVER: Exiting " << endl;
187 clientConnection->close();
188 clientConnection->deleteLater();
189 return;
190 }
191
192 // Check is client is new or not
193 // -----------------------------
194 // Check if Address is not already in the thread pool
195 // check by comparing address strings (To handle IPv4 and IPv6.)
196 int id = isNewAddress(PeerAddress.toString(), peer_udp_port);
197 // If the address is not new, we need to remove the client from the pool
198 // before re-starting the connection
199
200 if (id == -1) {
201 int id_remove;
202 id_remove = getPoolID(PeerAddress.toString(), peer_udp_port);
203 // stop the thread
204 mJTWorkers->at(id_remove)->stopThread();
205 // block until the thread has been removed from the pool
206 while ( isNewAddress(PeerAddress.toString(), peer_udp_port) == -1 ) {
207 cout << "JackTrip HUB SERVER: Removing JackTripWorker from pool..." << endl;
208 QThread::msleep(10);
209 }
210 // Get a new ID for this client
211 //id = isNewAddress(PeerAddress.toIPv4Address(), peer_udp_port);
212 id = getPoolID(PeerAddress.toString(), peer_udp_port);
213 }
214 // Assign server port and send it to Client
215 int server_udp_port = mBasePort+id;
216 cout << "JackTrip HUB SERVER: Sending Final UDP Port to Client: " << server_udp_port << endl;
217
218 if ( sendUdpPort(clientConnection, server_udp_port) == 0 ) {
219 clientConnection->close();
220 clientConnection->deleteLater();
221 releaseThread(id);
222 return;
223 }
224
225 // Close and mark socket for deletion
226 // ----------------------------------
227 clientConnection->close();
228 clientConnection->deleteLater();
229 cout << "JackTrip HUB SERVER: Client TCP Connection Closed!" << endl;
230
231 // Spawn Thread to Pool
232 // --------------------
233 // Register JackTripWorker with the hub listener
234 delete mJTWorkers->at(id); // just in case the Worker was previously created
235 mJTWorkers->replace(id, new JackTripWorker(this, mBufferQueueLength, mUnderRunMode, clientName));
236 if (mIOStatTimeout > 0) {
237 mJTWorkers->at(id)->setIOStatTimeout(mIOStatTimeout);
238 mJTWorkers->at(id)->setIOStatStream(mIOStatStream);
239 }
240 mJTWorkers->at(id)->setBufferStrategy(mBufferStrategy);
241 mJTWorkers->at(id)->setNetIssuesSimulation(mSimulatedLossRate,
242 mSimulatedJitterRate, mSimulatedDelayRel);
243 mJTWorkers->at(id)->setBroadcast(mBroadcastQueue);
244 mJTWorkers->at(id)->setUseRtUdpPriority(mUseRtUdpPriority);
245 // redirect port and spawn listener
246 cout << "JackTrip HUB SERVER: Spawning JackTripWorker..." << endl;
142247 {
143 cout << "JackTrip HUB SERVER: Waiting for client connections..." << endl;
144 if(m_connectDefaultAudioPorts)
145 {
146 cout << "JackTrip HUB SERVER: Hub auto audio patch setting = " << mHubPatch << endl;
147 } else {
148 cout << "JackTrip HUB SERVER: Hub auto audio patch disabled " << endl;
149 }
150 cout << "=======================================================" << endl;
151 while ( !TcpServer.hasPendingConnections() && !TcpServer.waitForNewConnection(1000) )
152 { if (mStopped) { return; } } // block until a new connection is received
153 cout << "JackTrip HUB SERVER: Client Connection Received!" << endl;
154
155 // Control loop to be able to exit if UDPs or TCPs error ocurr
156 for (int dum = 0; dum<1; dum++) {
157 QTcpSocket *clientConnection = TcpServer.nextPendingConnection();
158 if ( !clientConnection->waitForConnected(tcpTimeout) ) {
159 std::cerr << clientConnection->errorString().toStdString() << endl;
160 break;
161 }
162 PeerAddress = clientConnection->peerAddress();
163 cout << "JackTrip HUB SERVER: Client Connect Received from Address : "
164 << PeerAddress.toString().toStdString() << endl;
165
166 // Get UDP port from client
167 // ------------------------
168 peer_udp_port = readClientUdpPort(clientConnection);
169 if ( peer_udp_port == 0 ) {
170 cout << "JackTrip HUB SERVER: Client UDP Port is = " << peer_udp_port << endl;
171 cout << "JackTrip HUB SERVER: Exiting " << endl;
172 break;
173 }
174 if ( peer_udp_port < gBindPortLow ) {
175 cout << "JackTrip HUB SERVER: Client UDP Port is = " << peer_udp_port << endl;
176 cout << "JackTrip HUB SERVER: Exiting " << endl;
177 break;
178 }
179 if ( peer_udp_port > gBindPortHigh ) {
180 cout << "JackTrip HUB SERVER: Client UDP Port is = " << peer_udp_port << endl;
181 cout << "JackTrip HUB SERVER: Exiting " << endl;
182 break;
183 }
184 cout << "JackTrip HUB SERVER: Client UDP Port is = " << peer_udp_port << endl;
185
186 // Check is client is new or not
187 // -----------------------------
188 // Check if Address is not already in the thread pool
189 // check by comparing address strings (To handle IPv4 and IPv6.)
190 int id = isNewAddress(PeerAddress.toString(), peer_udp_port);
191 // If the address is not new, we need to remove the client from the pool
192 // before re-starting the connection
193
194 if (id == -1) {
195 int id_remove;
196 id_remove = getPoolID(PeerAddress.toString(), peer_udp_port);
197 // stop the thread
198 mJTWorkers->at(id_remove)->stopThread();
199 // block until the thread has been removed from the pool
200 while ( isNewAddress(PeerAddress.toString(), peer_udp_port) == -1 ) {
201 cout << "JackTrip HUB SERVER: Removing JackTripWorker from pool..." << endl;
202 QThread::msleep(10);
203 }
204 // Get a new ID for this client
205 //id = isNewAddress(PeerAddress.toIPv4Address(), peer_udp_port);
206 id = getPoolID(PeerAddress.toString(), peer_udp_port);
207 }
208 // Assign server port and send it to Client
209 server_udp_port = mBasePort+id;
210 cout << "JackTrip HUB SERVER: Sending Final UDP Port to Client: " << server_udp_port << endl;
211
212 if ( sendUdpPort(clientConnection, server_udp_port) == 0 ) {
213 clientConnection->close();
214 delete clientConnection;
215 releaseThread(id);
216 break;
217 }
218
219 // Close and Delete the socket
220 // ---------------------------
221 clientConnection->close();
222 delete clientConnection;
223 cout << "JackTrip HUB SERVER: Client TCP Connection Closed!" << endl;
224
225 // Spawn Thread to Pool
226 // --------------------
227 // Register JackTripWorker with the master listener
228 delete mJTWorkers->at(id); // just in case the Worker was previously created
229 mJTWorkers->replace(id, new JackTripWorker(this, mBufferQueueLength, mUnderRunMode));
230 // redirect port and spawn listener
231 cout << "JackTrip HUB SERVER: Spawning JackTripWorker..." << endl;
232 {
233 QMutexLocker lock(&mMutex);
234 mJTWorkers->at(id)->setJackTrip(id,
235 mActiveAddress[id].address,
236 server_udp_port,
237 mActiveAddress[id].port,
238 1,
239 m_connectDefaultAudioPorts
240 ); /// \todo temp default to 1 channel
241
242 // qDebug() << "mPeerAddress" << id << mActiveAddress[id].address << mActiveAddress[id].port;
243 }
244 //send one thread to the pool
245 cout << "JackTrip HUB SERVER: Starting JackTripWorker..." << endl;
246 mThreadPool.start(mJTWorkers->at(id), QThread::TimeCriticalPriority);
247 // wait until one is complete before another spawns
248 while (mJTWorkers->at(id)->isSpawning()) { QThread::msleep(10); }
249 //mTotalRunningThreads++;
250 cout << "JackTrip HUB SERVER: Total Running Threads: " << mTotalRunningThreads << endl;
251 cout << "===============================================================" << endl;
252 QThread::msleep(100);
248 QMutexLocker lock(&mMutex);
249 mJTWorkers->at(id)->setJackTrip(id,
250 mActiveAddress[id].address,
251 server_udp_port,
252 mActiveAddress[id].port,
253 1,
254 m_connectDefaultAudioPorts
255 ); /// \todo temp default to 1 channel
256
257 //qDebug() << "mPeerAddress" << id << mActiveAddress[id].address << mActiveAddress[id].port;
258 }
259 //send one thread to the pool
260 cout << "JackTrip HUB SERVER: Starting JackTripWorker..." << endl;
261 mThreadPool.start(mJTWorkers->at(id), QThread::TimeCriticalPriority);
262 // wait until one is complete before another spawns
263 while (mJTWorkers->at(id)->isSpawning()) { QThread::msleep(10); }
264 //mTotalRunningThreads++;
265 cout << "JackTrip HUB SERVER: Total Running Threads: " << mTotalRunningThreads << endl;
266 cout << "===============================================================" << endl;
267 QThread::msleep(100);
253268 #ifdef WAIR // WAIR
254 if (isWAIR()) connectMesh(true); // invoked with -Sw
269 if (isWAIR()) connectMesh(true); // invoked with -Sw
255270 #endif // endwhere
256271
257 // qDebug() << "mPeerAddress" << mActiveAddress[id].address << mActiveAddress[id].port;
258
259 connectPatch(true);
260 }
261 }
262
263 /*
272 //qDebug() << "mPeerAddress" << mActiveAddress[id].address << mActiveAddress[id].port;
273
274 connectPatch(true);
275 }
276
277 void UdpHubListener::stopCheck()
278 {
279 if (mStopped || sSigInt) {
280 cout << "JackTrip HUB SERVER: Stopped" << endl;
281 mStopCheckTimer.stop();
282 mTcpServer.close();
283 stopAllThreads();
284 emit signalStopped();
285 }
286 }
287
288 /* From Old Runloop code
264289 // Create objects on the stack
265290 QUdpSocket HubUdpSocket;
266291 QHostAddress PeerAddress;
309334 QThread::msleep(100);
310335 }
311336 */
312 }
313
314337
315338 //*******************************************************************************
316339 // Returns 0 on error
317 uint16_t UdpHubListener::readClientUdpPort(QTcpSocket* clientConnection)
318 {
319 // Read the size of the package
320 // ----------------------------
321 //tcpClient.waitForReadyRead();
322 cout << "JackTrip HUB SERVER: Reading UDP port from Client..." << endl;
323 while (clientConnection->bytesAvailable() < (qint64)sizeof(uint16_t)) {
324 if (!clientConnection->waitForReadyRead()) {
325 std::cerr << "TCP Socket ERROR: " << clientConnection->errorString().toStdString() << endl;
326 return 0;
327 }
328 }
329
340 uint16_t UdpHubListener::readClientUdpPort(QTcpSocket* clientConnection, QString &clientName)
341 {
330342 if (gVerboseFlag) cout << "Ready To Read From Client!" << endl;
331343 // Read UDP Port Number from Server
332344 // --------------------------------
333 uint16_t udp_port = 0;
345 uint16_t udp_port;
334346 qint64 size = sizeof(udp_port);
335347 char port_buf[size];
336348 clientConnection->read(port_buf, size);
337349 std::memcpy(&udp_port, port_buf, size);
350
351 if (clientConnection->bytesAvailable() == gMaxRemoteNameLength) {
352 char name_buf[gMaxRemoteNameLength];
353 clientConnection->read(name_buf, gMaxRemoteNameLength);
354 clientName = QString::fromUtf8((const char *)name_buf);
355 }
356
338357 return udp_port;
339358 }
340359
356375 }
357376 }
358377 return 1;
359 cout << "Port sent to Client" << endl;
378 //cout << "Port sent to Client" << endl;
360379 }
361380
362381
488507 #include "JMess.h"
489508 void UdpHubListener::connectPatch(bool spawn)
490509 {
491 if(m_connectDefaultAudioPorts) {
492 cout << ((spawn)?"spawning":"releasing") << " jacktripWorker so change patch" << endl;
493 } else {
494 cout << ((spawn)?"spawning":"releasing") << " jacktripWorker" << endl;
495 }
510 if ((getHubPatch() == JackTrip::NOAUTO) ||
511 (getHubPatch() == JackTrip::SERVERTOCLIENT && !m_connectDefaultAudioPorts)) {
512 cout << ((spawn)?"spawning":"releasing") << " jacktripWorker (auto hub patching disabled)" << endl;
513 return;
514 }
515 cout << ((spawn)?"spawning":"releasing") << " jacktripWorker so change patch" << endl;
496516 JMess tmp;
497517 // default is patch 0, which connects server audio to all clients
498518 // these are the other cases:
505525 // FIXME: need change to gDefaultNumInChannels if more than stereo
506526 }
507527
528 void UdpHubListener::stopAllThreads()
529 {
530 QVectorIterator<JackTripWorker*> iterator(*mJTWorkers);
531 while (iterator.hasNext()) {
532 if (iterator.peekNext() != nullptr) {
533 iterator.next()->stopThread();
534 } else {
535 iterator.next();
536 }
537 }
538 mThreadPool.waitForDone();
539 }
508540 // TODO:
509541 // USE bool QAbstractSocket::isValid () const to check if socket is connect. if not, exit loop
3939
4040 #include <iostream>
4141 #include <stdexcept>
42 #include <fstream>
4243
4344 #include <QThread>
4445 #include <QThreadPool>
6465 * This creates a server that will listen on the well know port (the server port) and will
6566 * spawn JackTrip threads into the Thread pool. Clients request a connection.
6667 */
67 class UdpHubListener : public QThread
68 class UdpHubListener : public QObject
6869 {
6970 Q_OBJECT;
7071
7172 public:
72 UdpHubListener(int server_port = gServerUdpPort, int server_udp_port = NULL);
73 UdpHubListener(int server_port = gServerUdpPort, int server_udp_port = 0);
7374 virtual ~UdpHubListener();
7475
75 /// \brief Implements the Thread Loop. To start the thread, call start()
76 /// ( DO NOT CALL run() )
77 void run();
76 /// \brief Starts the TCP server
77 void start();
7878
7979 /// \brief Stops the execution of the Thread
8080 void stop() { mStopped = true; }
8282 int releaseThread(int id);
8383
8484 void setConnectDefaultAudioPorts(bool connectDefaultAudioPorts) { m_connectDefaultAudioPorts = connectDefaultAudioPorts; }
85
86 void setSettings(Settings* s) {m_settings = s;}
87 Settings* getSettings() const {return m_settings;}
85
86 static void sigIntHandler(__attribute__((unused)) int unused)
87 { std::cout << std::endl << "Shutting Down..." << std::endl; sSigInt = true; }
8888
8989 private slots:
9090 void testReceive()
9191 { std::cout << "========= TEST RECEIVE SLOT ===========" << std::endl; }
92 void receivedNewConnection();
93 void stopCheck();
9294
9395 signals:
9496 void Listening();
9597 void ClientAddressSet();
9698 void signalRemoveThread(int id);
97
99 void signalStopped();
100 void signalError(const QString &errorMessage);
98101
99102 private:
100103 /** \brief Binds a QUdpSocket. It chooses the available (active) interface.
101104 * \param udpsocket a QUdpSocket
102105 * \param port Port number
103106 */
107 void receivedClientInfo(QTcpSocket *clientConnection);
108
104109 static void bindUdpSocket(QUdpSocket& udpsocket, int port);
105110
106 uint16_t readClientUdpPort(QTcpSocket* clientConnection);
111 uint16_t readClientUdpPort(QTcpSocket* clientConnection, QString &clientName);
107112 int sendUdpPort(QTcpSocket* clientConnection, int udp_port);
108113
109114
123128 * is not in the pool yet, returns -1.
124129 */
125130 int getPoolID(QString address, uint16_t port);
131
132 void stopAllThreads();
126133
127134 //QUdpSocket mUdpHubSocket; ///< The UDP socket
128135 //QHostAddress mPeerAddress; ///< The Peer Address
131138 QVector<JackTripWorker*>* mJTWorkers; ///< Vector of JackTripWorker s
132139 QThreadPool mThreadPool; ///< The Thread Pool
133140
141 QTcpServer mTcpServer;
134142 int mServerPort; //< Server known port number
135143 int mServerUdpPort; //< Server udp base port number
136144 int mBasePort;
139147
140148 /// Boolean stop the execution of the thread
141149 volatile bool mStopped;
150 static bool sSigInt;
151 QTimer mStopCheckTimer;
142152 int mTotalRunningThreads; ///< Number of Threads running in the pool
143153 QMutex mMutex;
144154 JackTrip::underrunModeT mUnderRunMode;
145155 int mBufferQueueLength;
146
156
157 QStringList mHubPatchDescriptions;
147158 bool m_connectDefaultAudioPorts;
148 Settings* m_settings;
149
159
160 int mIOStatTimeout;
161 QSharedPointer<std::ofstream> mIOStatStream;
162
163 int mBufferStrategy;
164 int mBroadcastQueue;
165 double mSimulatedLossRate;
166 double mSimulatedJitterRate;
167 double mSimulatedDelayRel;
168 bool mUseRtUdpPriority;
169
150170 #ifdef WAIR // wair
151171 bool mWAIR;
152172 void connectMesh(bool spawn);
163183
164184 void setUnderRunMode(JackTrip::underrunModeT UnderRunMode) { mUnderRunMode = UnderRunMode; }
165185 void setBufferQueueLength(int BufferQueueLength) { mBufferQueueLength = BufferQueueLength; }
186
187 void setIOStatTimeout(int timeout) { mIOStatTimeout = timeout; }
188 void setIOStatStream(QSharedPointer<std::ofstream> statStream) { mIOStatStream = statStream; }
189
190 void setBufferStrategy(int BufferStrategy) { mBufferStrategy = BufferStrategy; }
191 void setNetIssuesSimulation(double loss, double jitter, double delay_rel)
192 {
193 mSimulatedLossRate = loss;
194 mSimulatedJitterRate = jitter;
195 mSimulatedDelayRel = delay_rel;
196 }
197 void setBroadcast(int broadcast_queue) {mBroadcastQueue = broadcast_queue;}
198 void setUseRtUdpPriority(bool use) {mUseRtUdpPriority = use;}
199
166200 };
167201
168202
3636 $QCMD -spec $QSPEC -config nojack ../src/jacktrip.pro
3737 make release
3838 else
39 $QCMD -spec $QSPEC ../src/jacktrip.pro
39 $QCMD -spec $QSPEC ../src/jacktrip.pro $@
4040 make clean
41 $QCMD -spec $QSPEC ../src/jacktrip.pro
41 $QCMD -spec $QSPEC ../src/jacktrip.pro $@
4242 make release
4343 fi
0 /* ------------------------------------------------------------
1 author: "Julius Smith"
2 license: "MIT Style STK-4.2"
3 name: "compressor"
4 version: "0.0"
5 Code generated with Faust 2.28.6 (https://faust.grame.fr)
6 Compilation options: -lang cpp -inpl -scal -ftz 0
7 ------------------------------------------------------------ */
8
9 #ifndef __compressordsp_H__
10 #define __compressordsp_H__
11
12 // NOTE: ANY INCLUDE-GUARD HERE MUST BE DERIVED FROM THE CLASS NAME
13 //
14 // faust2header.cpp - FAUST Architecture File
15 // This is a simple variation of matlabplot.cpp in the Faust distribution
16 // aimed at creating a simple C++ header file (.h) containing a Faust DSP.
17 // See the Makefile for how to use it.
18
19 /************************** BEGIN dsp.h **************************/
20 /************************************************************************
21 FAUST Architecture File
22 Copyright (C) 2003-2017 GRAME, Centre National de Creation Musicale
23 ---------------------------------------------------------------------
24 This Architecture section is free software; you can redistribute it
25 and/or modify it under the terms of the GNU General Public License
26 as published by the Free Software Foundation; either version 3 of
27 the License, or (at your option) any later version.
28
29 This program is distributed in the hope that it will be useful,
30 but WITHOUT ANY WARRANTY; without even the implied warranty of
31 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 GNU General Public License for more details.
33
34 You should have received a copy of the GNU General Public License
35 along with this program; If not, see <http://www.gnu.org/licenses/>.
36
37 EXCEPTION : As a special exception, you may create a larger work
38 that contains this FAUST architecture section and distribute
39 that work under terms of your choice, so long as this FAUST
40 architecture section is not modified.
41 ************************************************************************/
42
43 #ifndef __dsp__
44 #define __dsp__
45
46 #include <string>
47 #include <vector>
48
49 #ifndef FAUSTFLOAT
50 #define FAUSTFLOAT float
51 #endif
52
53 struct UI;
54 struct Meta;
55
56 /**
57 * DSP memory manager.
58 */
59
60 struct dsp_memory_manager {
61
62 virtual ~dsp_memory_manager() {}
63
64 virtual void* allocate(size_t size) = 0;
65 virtual void destroy(void* ptr) = 0;
66
67 };
68
69 /**
70 * Signal processor definition.
71 */
72
73 class dsp {
74
75 public:
76
77 dsp() {}
78 virtual ~dsp() {}
79
80 /* Return instance number of audio inputs */
81 virtual int getNumInputs() = 0;
82
83 /* Return instance number of audio outputs */
84 virtual int getNumOutputs() = 0;
85
86 /**
87 * Trigger the ui_interface parameter with instance specific calls
88 * to 'openTabBox', 'addButton', 'addVerticalSlider'... in order to build the UI.
89 *
90 * @param ui_interface - the user interface builder
91 */
92 virtual void buildUserInterface(UI* ui_interface) = 0;
93
94 /* Returns the sample rate currently used by the instance */
95 virtual int getSampleRate() = 0;
96
97 /**
98 * Global init, calls the following methods:
99 * - static class 'classInit': static tables initialization
100 * - 'instanceInit': constants and instance state initialization
101 *
102 * @param sample_rate - the sampling rate in Hertz
103 */
104 virtual void init(int sample_rate) = 0;
105
106 /**
107 * Init instance state
108 *
109 * @param sample_rate - the sampling rate in Hertz
110 */
111 virtual void instanceInit(int sample_rate) = 0;
112
113 /**
114 * Init instance constant state
115 *
116 * @param sample_rate - the sampling rate in Hertz
117 */
118 virtual void instanceConstants(int sample_rate) = 0;
119
120 /* Init default control parameters values */
121 virtual void instanceResetUserInterface() = 0;
122
123 /* Init instance state (delay lines...) */
124 virtual void instanceClear() = 0;
125
126 /**
127 * Return a clone of the instance.
128 *
129 * @return a copy of the instance on success, otherwise a null pointer.
130 */
131 virtual dsp* clone() = 0;
132
133 /**
134 * Trigger the Meta* parameter with instance specific calls to 'declare' (key, value) metadata.
135 *
136 * @param m - the Meta* meta user
137 */
138 virtual void metadata(Meta* m) = 0;
139
140 /**
141 * DSP instance computation, to be called with successive in/out audio buffers.
142 *
143 * @param count - the number of frames to compute
144 * @param inputs - the input audio buffers as an array of non-interleaved FAUSTFLOAT samples (eiher float, double or quad)
145 * @param outputs - the output audio buffers as an array of non-interleaved FAUSTFLOAT samples (eiher float, double or quad)
146 *
147 */
148 virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) = 0;
149
150 /**
151 * DSP instance computation: alternative method to be used by subclasses.
152 *
153 * @param date_usec - the timestamp in microsec given by audio driver.
154 * @param count - the number of frames to compute
155 * @param inputs - the input audio buffers as an array of non-interleaved FAUSTFLOAT samples (either float, double or quad)
156 * @param outputs - the output audio buffers as an array of non-interleaved FAUSTFLOAT samples (either float, double or quad)
157 *
158 */
159 virtual void compute(double /*date_usec*/, int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { compute(count, inputs, outputs); }
160
161 };
162
163 /**
164 * Generic DSP decorator.
165 */
166
167 class decorator_dsp : public dsp {
168
169 protected:
170
171 dsp* fDSP;
172
173 public:
174
175 decorator_dsp(dsp* dsp = nullptr):fDSP(dsp) {}
176 virtual ~decorator_dsp() { delete fDSP; }
177
178 virtual int getNumInputs() { return fDSP->getNumInputs(); }
179 virtual int getNumOutputs() { return fDSP->getNumOutputs(); }
180 virtual void buildUserInterface(UI* ui_interface) { fDSP->buildUserInterface(ui_interface); }
181 virtual int getSampleRate() { return fDSP->getSampleRate(); }
182 virtual void init(int sample_rate) { fDSP->init(sample_rate); }
183 virtual void instanceInit(int sample_rate) { fDSP->instanceInit(sample_rate); }
184 virtual void instanceConstants(int sample_rate) { fDSP->instanceConstants(sample_rate); }
185 virtual void instanceResetUserInterface() { fDSP->instanceResetUserInterface(); }
186 virtual void instanceClear() { fDSP->instanceClear(); }
187 virtual decorator_dsp* clone() { return new decorator_dsp(fDSP->clone()); }
188 virtual void metadata(Meta* m) { fDSP->metadata(m); }
189 // Beware: subclasses usually have to overload the two 'compute' methods
190 virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { fDSP->compute(count, inputs, outputs); }
191 virtual void compute(double date_usec, int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { fDSP->compute(date_usec, count, inputs, outputs); }
192
193 };
194
195 /**
196 * DSP factory class.
197 */
198
199 class dsp_factory {
200
201 protected:
202
203 // So that to force sub-classes to use deleteDSPFactory(dsp_factory* factory);
204 virtual ~dsp_factory() {}
205
206 public:
207
208 virtual std::string getName() = 0;
209 virtual std::string getSHAKey() = 0;
210 virtual std::string getDSPCode() = 0;
211 virtual std::string getCompileOptions() = 0;
212 virtual std::vector<std::string> getLibraryList() = 0;
213 virtual std::vector<std::string> getIncludePathnames() = 0;
214
215 virtual dsp* createDSPInstance() = 0;
216
217 virtual void setMemoryManager(dsp_memory_manager* manager) = 0;
218 virtual dsp_memory_manager* getMemoryManager() = 0;
219
220 };
221
222 /**
223 * On Intel set FZ (Flush to Zero) and DAZ (Denormals Are Zero)
224 * flags to avoid costly denormals.
225 */
226
227 #ifdef __SSE__
228 #include <xmmintrin.h>
229 #ifdef __SSE2__
230 #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8040)
231 #else
232 #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8000)
233 #endif
234 #else
235 #define AVOIDDENORMALS
236 #endif
237
238 #endif
239 /************************** END dsp.h **************************/
240
241 /************************** BEGIN APIUI.h **************************/
242 /************************************************************************
243 FAUST Architecture File
244 Copyright (C) 2003-2017 GRAME, Centre National de Creation Musicale
245 ---------------------------------------------------------------------
246 This Architecture section is free software; you can redistribute it
247 and/or modify it under the terms of the GNU General Public License
248 as published by the Free Software Foundation; either version 3 of
249 the License, or (at your option) any later version.
250
251 This program is distributed in the hope that it will be useful,
252 but WITHOUT ANY WARRANTY; without even the implied warranty of
253 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
254 GNU General Public License for more details.
255
256 You should have received a copy of the GNU General Public License
257 along with this program; If not, see <http://www.gnu.org/licenses/>.
258
259 EXCEPTION : As a special exception, you may create a larger work
260 that contains this FAUST architecture section and distribute
261 that work under terms of your choice, so long as this FAUST
262 architecture section is not modified.
263 ************************************************************************/
264
265 #ifndef API_UI_H
266 #define API_UI_H
267
268 #include <sstream>
269 #include <string>
270 #include <vector>
271 #include <iostream>
272 #include <map>
273
274 /************************** BEGIN meta.h **************************/
275 /************************************************************************
276 FAUST Architecture File
277 Copyright (C) 2003-2017 GRAME, Centre National de Creation Musicale
278 ---------------------------------------------------------------------
279 This Architecture section is free software; you can redistribute it
280 and/or modify it under the terms of the GNU General Public License
281 as published by the Free Software Foundation; either version 3 of
282 the License, or (at your option) any later version.
283
284 This program is distributed in the hope that it will be useful,
285 but WITHOUT ANY WARRANTY; without even the implied warranty of
286 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
287 GNU General Public License for more details.
288
289 You should have received a copy of the GNU General Public License
290 along with this program; If not, see <http://www.gnu.org/licenses/>.
291
292 EXCEPTION : As a special exception, you may create a larger work
293 that contains this FAUST architecture section and distribute
294 that work under terms of your choice, so long as this FAUST
295 architecture section is not modified.
296 ************************************************************************/
297
298 #ifndef __meta__
299 #define __meta__
300
301 struct Meta
302 {
303 virtual ~Meta() {};
304 virtual void declare(const char* key, const char* value) = 0;
305
306 };
307
308 #endif
309 /************************** END meta.h **************************/
310 /************************** BEGIN UI.h **************************/
311 /************************************************************************
312 FAUST Architecture File
313 Copyright (C) 2003-2020 GRAME, Centre National de Creation Musicale
314 ---------------------------------------------------------------------
315 This Architecture section is free software; you can redistribute it
316 and/or modify it under the terms of the GNU General Public License
317 as published by the Free Software Foundation; either version 3 of
318 the License, or (at your option) any later version.
319
320 This program is distributed in the hope that it will be useful,
321 but WITHOUT ANY WARRANTY; without even the implied warranty of
322 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
323 GNU General Public License for more details.
324
325 You should have received a copy of the GNU General Public License
326 along with this program; If not, see <http://www.gnu.org/licenses/>.
327
328 EXCEPTION : As a special exception, you may create a larger work
329 that contains this FAUST architecture section and distribute
330 that work under terms of your choice, so long as this FAUST
331 architecture section is not modified.
332 ************************************************************************/
333
334 #ifndef __UI_H__
335 #define __UI_H__
336
337 #ifndef FAUSTFLOAT
338 #define FAUSTFLOAT float
339 #endif
340
341 /*******************************************************************************
342 * UI : Faust DSP User Interface
343 * User Interface as expected by the buildUserInterface() method of a DSP.
344 * This abstract class contains only the method that the Faust compiler can
345 * generate to describe a DSP user interface.
346 ******************************************************************************/
347
348 struct Soundfile;
349
350 template <typename REAL>
351 struct UIReal
352 {
353 UIReal() {}
354 virtual ~UIReal() {}
355
356 // -- widget's layouts
357
358 virtual void openTabBox(const char* label) = 0;
359 virtual void openHorizontalBox(const char* label) = 0;
360 virtual void openVerticalBox(const char* label) = 0;
361 virtual void closeBox() = 0;
362
363 // -- active widgets
364
365 virtual void addButton(const char* label, REAL* zone) = 0;
366 virtual void addCheckButton(const char* label, REAL* zone) = 0;
367 virtual void addVerticalSlider(const char* label, REAL* zone, REAL init, REAL min, REAL max, REAL step) = 0;
368 virtual void addHorizontalSlider(const char* label, REAL* zone, REAL init, REAL min, REAL max, REAL step) = 0;
369 virtual void addNumEntry(const char* label, REAL* zone, REAL init, REAL min, REAL max, REAL step) = 0;
370
371 // -- passive widgets
372
373 virtual void addHorizontalBargraph(const char* label, REAL* zone, REAL min, REAL max) = 0;
374 virtual void addVerticalBargraph(const char* label, REAL* zone, REAL min, REAL max) = 0;
375
376 // -- soundfiles
377
378 virtual void addSoundfile(const char* label, const char* filename, Soundfile** sf_zone) = 0;
379
380 // -- metadata declarations
381
382 virtual void declare(REAL* zone, const char* key, const char* val) {}
383 };
384
385 struct UI : public UIReal<FAUSTFLOAT>
386 {
387 UI() {}
388 virtual ~UI() {}
389 };
390
391 #endif
392 /************************** END UI.h **************************/
393 /************************** BEGIN PathBuilder.h **************************/
394 /************************************************************************
395 FAUST Architecture File
396 Copyright (C) 2003-2017 GRAME, Centre National de Creation Musicale
397 ---------------------------------------------------------------------
398 This Architecture section is free software; you can redistribute it
399 and/or modify it under the terms of the GNU General Public License
400 as published by the Free Software Foundation; either version 3 of
401 the License, or (at your option) any later version.
402
403 This program is distributed in the hope that it will be useful,
404 but WITHOUT ANY WARRANTY; without even the implied warranty of
405 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
406 GNU General Public License for more details.
407
408 You should have received a copy of the GNU General Public License
409 along with this program; If not, see <http://www.gnu.org/licenses/>.
410
411 EXCEPTION : As a special exception, you may create a larger work
412 that contains this FAUST architecture section and distribute
413 that work under terms of your choice, so long as this FAUST
414 architecture section is not modified.
415 ************************************************************************/
416
417 #ifndef FAUST_PATHBUILDER_H
418 #define FAUST_PATHBUILDER_H
419
420 #include <vector>
421 #include <string>
422 #include <algorithm>
423
424 /*******************************************************************************
425 * PathBuilder : Faust User Interface
426 * Helper class to build complete hierarchical path for UI items.
427 ******************************************************************************/
428
429 class PathBuilder
430 {
431
432 protected:
433
434 std::vector<std::string> fControlsLevel;
435
436 public:
437
438 PathBuilder() {}
439 virtual ~PathBuilder() {}
440
441 std::string buildPath(const std::string& label)
442 {
443 std::string res = "/";
444 for (size_t i = 0; i < fControlsLevel.size(); i++) {
445 res += fControlsLevel[i];
446 res += "/";
447 }
448 res += label;
449 std::replace(res.begin(), res.end(), ' ', '_');
450 return res;
451 }
452
453 std::string buildLabel(std::string label)
454 {
455 std::replace(label.begin(), label.end(), ' ', '_');
456 return label;
457 }
458
459 void pushLabel(const std::string& label) { fControlsLevel.push_back(label); }
460 void popLabel() { fControlsLevel.pop_back(); }
461
462 };
463
464 #endif // FAUST_PATHBUILDER_H
465 /************************** END PathBuilder.h **************************/
466 /************************** BEGIN ValueConverter.h **************************/
467 /************************************************************************
468 FAUST Architecture File
469 Copyright (C) 2003-2017 GRAME, Centre National de Creation Musicale
470 ---------------------------------------------------------------------
471 This Architecture section is free software; you can redistribute it
472 and/or modify it under the terms of the GNU General Public License
473 as published by the Free Software Foundation; either version 3 of
474 the License, or (at your option) any later version.
475
476 This program is distributed in the hope that it will be useful,
477 but WITHOUT ANY WARRANTY; without even the implied warranty of
478 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
479 GNU General Public License for more details.
480
481 You should have received a copy of the GNU General Public License
482 along with this program; If not, see <http://www.gnu.org/licenses/>.
483
484 EXCEPTION : As a special exception, you may create a larger work
485 that contains this FAUST architecture section and distribute
486 that work under terms of your choice, so long as this FAUST
487 architecture section is not modified.
488 ************************************************************************/
489
490 #ifndef __ValueConverter__
491 #define __ValueConverter__
492
493 /***************************************************************************************
494 ValueConverter.h
495 (GRAME, Copyright 2015-2019)
496
497 Set of conversion objects used to map user interface values (for example a gui slider
498 delivering values between 0 and 1) to faust values (for example a vslider between
499 20 and 20000) using a log scale.
500
501 -- Utilities
502
503 Range(lo,hi) : clip a value x between lo and hi
504 Interpolator(lo,hi,v1,v2) : Maps a value x between lo and hi to a value y between v1 and v2
505 Interpolator3pt(lo,mi,hi,v1,vm,v2) : Map values between lo mid hi to values between v1 vm v2
506
507 -- Value Converters
508
509 ValueConverter::ui2faust(x)
510 ValueConverter::faust2ui(x)
511
512 -- ValueConverters used for sliders depending of the scale
513
514 LinearValueConverter(umin, umax, fmin, fmax)
515 LinearValueConverter2(lo, mi, hi, v1, vm, v2) using 2 segments
516 LogValueConverter(umin, umax, fmin, fmax)
517 ExpValueConverter(umin, umax, fmin, fmax)
518
519 -- ValueConverters used for accelerometers based on 3 points
520
521 AccUpConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 0
522 AccDownConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 1
523 AccUpDownConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 2
524 AccDownUpConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 3
525
526 -- lists of ZoneControl are used to implement accelerometers metadata for each axes
527
528 ZoneControl(zone, valueConverter) : a zone with an accelerometer data converter
529
530 -- ZoneReader are used to implement screencolor metadata
531
532 ZoneReader(zone, valueConverter) : a zone with a data converter
533
534 ****************************************************************************************/
535
536 #include <float.h>
537 #include <algorithm> // std::max
538 #include <cmath>
539 #include <vector>
540 #include <assert.h>
541
542 //--------------------------------------------------------------------------------------
543 // Interpolator(lo,hi,v1,v2)
544 // Maps a value x between lo and hi to a value y between v1 and v2
545 // y = v1 + (x-lo)/(hi-lo)*(v2-v1)
546 // y = v1 + (x-lo) * coef with coef = (v2-v1)/(hi-lo)
547 // y = v1 + x*coef - lo*coef
548 // y = v1 - lo*coef + x*coef
549 // y = offset + x*coef with offset = v1 - lo*coef
550 //--------------------------------------------------------------------------------------
551 class Interpolator
552 {
553 private:
554
555 //--------------------------------------------------------------------------------------
556 // Range(lo,hi) clip a value between lo and hi
557 //--------------------------------------------------------------------------------------
558 struct Range
559 {
560 double fLo;
561 double fHi;
562
563 Range(double x, double y) : fLo(std::min<double>(x,y)), fHi(std::max<double>(x,y)) {}
564 double operator()(double x) { return (x<fLo) ? fLo : (x>fHi) ? fHi : x; }
565 };
566
567
568 Range fRange;
569 double fCoef;
570 double fOffset;
571
572 public:
573
574 Interpolator(double lo, double hi, double v1, double v2) : fRange(lo,hi)
575 {
576 if (hi != lo) {
577 // regular case
578 fCoef = (v2-v1)/(hi-lo);
579 fOffset = v1 - lo*fCoef;
580 } else {
581 // degenerate case, avoids division by zero
582 fCoef = 0;
583 fOffset = (v1+v2)/2;
584 }
585 }
586 double operator()(double v)
587 {
588 double x = fRange(v);
589 return fOffset + x*fCoef;
590 }
591
592 void getLowHigh(double& amin, double& amax)
593 {
594 amin = fRange.fLo;
595 amax = fRange.fHi;
596 }
597 };
598
599 //--------------------------------------------------------------------------------------
600 // Interpolator3pt(lo,mi,hi,v1,vm,v2)
601 // Map values between lo mid hi to values between v1 vm v2
602 //--------------------------------------------------------------------------------------
603 class Interpolator3pt
604 {
605
606 private:
607
608 Interpolator fSegment1;
609 Interpolator fSegment2;
610 double fMid;
611
612 public:
613
614 Interpolator3pt(double lo, double mi, double hi, double v1, double vm, double v2) :
615 fSegment1(lo, mi, v1, vm),
616 fSegment2(mi, hi, vm, v2),
617 fMid(mi) {}
618 double operator()(double x) { return (x < fMid) ? fSegment1(x) : fSegment2(x); }
619
620 void getMappingValues(double& amin, double& amid, double& amax)
621 {
622 fSegment1.getLowHigh(amin, amid);
623 fSegment2.getLowHigh(amid, amax);
624 }
625 };
626
627 //--------------------------------------------------------------------------------------
628 // Abstract ValueConverter class. Converts values between UI and Faust representations
629 //--------------------------------------------------------------------------------------
630 class ValueConverter
631 {
632
633 public:
634
635 virtual ~ValueConverter() {}
636 virtual double ui2faust(double x) = 0;
637 virtual double faust2ui(double x) = 0;
638 };
639
640 //--------------------------------------------------------------------------------------
641 // A converter than can be updated
642 //--------------------------------------------------------------------------------------
643
644 class UpdatableValueConverter : public ValueConverter {
645
646 protected:
647
648 bool fActive;
649
650 public:
651
652 UpdatableValueConverter():fActive(true)
653 {}
654 virtual ~UpdatableValueConverter()
655 {}
656
657 virtual void setMappingValues(double amin, double amid, double amax, double min, double init, double max) = 0;
658 virtual void getMappingValues(double& amin, double& amid, double& amax) = 0;
659
660 void setActive(bool on_off) { fActive = on_off; }
661 bool getActive() { return fActive; }
662
663 };
664
665
666 //--------------------------------------------------------------------------------------
667 // Linear conversion between ui and Faust values
668 //--------------------------------------------------------------------------------------
669 class LinearValueConverter : public ValueConverter
670 {
671
672 private:
673
674 Interpolator fUI2F;
675 Interpolator fF2UI;
676
677 public:
678
679 LinearValueConverter(double umin, double umax, double fmin, double fmax) :
680 fUI2F(umin,umax,fmin,fmax), fF2UI(fmin,fmax,umin,umax)
681 {}
682
683 LinearValueConverter() : fUI2F(0.,0.,0.,0.), fF2UI(0.,0.,0.,0.)
684 {}
685 virtual double ui2faust(double x) { return fUI2F(x); }
686 virtual double faust2ui(double x) { return fF2UI(x); }
687
688 };
689
690 //--------------------------------------------------------------------------------------
691 // Two segments linear conversion between ui and Faust values
692 //--------------------------------------------------------------------------------------
693 class LinearValueConverter2 : public UpdatableValueConverter
694 {
695
696 private:
697
698 Interpolator3pt fUI2F;
699 Interpolator3pt fF2UI;
700
701 public:
702
703 LinearValueConverter2(double amin, double amid, double amax, double min, double init, double max) :
704 fUI2F(amin, amid, amax, min, init, max), fF2UI(min, init, max, amin, amid, amax)
705 {}
706
707 LinearValueConverter2() : fUI2F(0.,0.,0.,0.,0.,0.), fF2UI(0.,0.,0.,0.,0.,0.)
708 {}
709
710 virtual double ui2faust(double x) { return fUI2F(x); }
711 virtual double faust2ui(double x) { return fF2UI(x); }
712
713 virtual void setMappingValues(double amin, double amid, double amax, double min, double init, double max)
714 {
715 fUI2F = Interpolator3pt(amin, amid, amax, min, init, max);
716 fF2UI = Interpolator3pt(min, init, max, amin, amid, amax);
717 }
718
719 virtual void getMappingValues(double& amin, double& amid, double& amax)
720 {
721 fUI2F.getMappingValues(amin, amid, amax);
722 }
723
724 };
725
726 //--------------------------------------------------------------------------------------
727 // Logarithmic conversion between ui and Faust values
728 //--------------------------------------------------------------------------------------
729 class LogValueConverter : public LinearValueConverter
730 {
731
732 public:
733
734 LogValueConverter(double umin, double umax, double fmin, double fmax) :
735 LinearValueConverter(umin, umax, std::log(std::max<double>(DBL_MIN, fmin)), std::log(std::max<double>(DBL_MIN, fmax)))
736 {}
737
738 virtual double ui2faust(double x) { return std::exp(LinearValueConverter::ui2faust(x)); }
739 virtual double faust2ui(double x) { return LinearValueConverter::faust2ui(std::log(std::max<double>(x, DBL_MIN))); }
740
741 };
742
743 //--------------------------------------------------------------------------------------
744 // Exponential conversion between ui and Faust values
745 //--------------------------------------------------------------------------------------
746 class ExpValueConverter : public LinearValueConverter
747 {
748
749 public:
750
751 ExpValueConverter(double umin, double umax, double fmin, double fmax) :
752 LinearValueConverter(umin, umax, std::min<double>(DBL_MAX, std::exp(fmin)), std::min<double>(DBL_MAX, std::exp(fmax)))
753 {}
754
755 virtual double ui2faust(double x) { return std::log(LinearValueConverter::ui2faust(x)); }
756 virtual double faust2ui(double x) { return LinearValueConverter::faust2ui(std::min<double>(DBL_MAX, std::exp(x))); }
757
758 };
759
760 //--------------------------------------------------------------------------------------
761 // Convert accelerometer or gyroscope values to Faust values
762 // Using an Up curve (curve 0)
763 //--------------------------------------------------------------------------------------
764 class AccUpConverter : public UpdatableValueConverter
765 {
766
767 private:
768
769 Interpolator3pt fA2F;
770 Interpolator3pt fF2A;
771
772 public:
773
774 AccUpConverter(double amin, double amid, double amax, double fmin, double fmid, double fmax) :
775 fA2F(amin,amid,amax,fmin,fmid,fmax),
776 fF2A(fmin,fmid,fmax,amin,amid,amax)
777 {}
778
779 virtual double ui2faust(double x) { return fA2F(x); }
780 virtual double faust2ui(double x) { return fF2A(x); }
781
782 virtual void setMappingValues(double amin, double amid, double amax, double fmin, double fmid, double fmax)
783 {
784 //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccUpConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax);
785 fA2F = Interpolator3pt(amin, amid, amax, fmin, fmid, fmax);
786 fF2A = Interpolator3pt(fmin, fmid, fmax, amin, amid, amax);
787 }
788
789 virtual void getMappingValues(double& amin, double& amid, double& amax)
790 {
791 fA2F.getMappingValues(amin, amid, amax);
792 }
793
794 };
795
796 //--------------------------------------------------------------------------------------
797 // Convert accelerometer or gyroscope values to Faust values
798 // Using a Down curve (curve 1)
799 //--------------------------------------------------------------------------------------
800 class AccDownConverter : public UpdatableValueConverter
801 {
802
803 private:
804
805 Interpolator3pt fA2F;
806 Interpolator3pt fF2A;
807
808 public:
809
810 AccDownConverter(double amin, double amid, double amax, double fmin, double fmid, double fmax) :
811 fA2F(amin,amid,amax,fmax,fmid,fmin),
812 fF2A(fmin,fmid,fmax,amax,amid,amin)
813 {}
814
815 virtual double ui2faust(double x) { return fA2F(x); }
816 virtual double faust2ui(double x) { return fF2A(x); }
817
818 virtual void setMappingValues(double amin, double amid, double amax, double fmin, double fmid, double fmax)
819 {
820 //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccDownConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax);
821 fA2F = Interpolator3pt(amin, amid, amax, fmax, fmid, fmin);
822 fF2A = Interpolator3pt(fmin, fmid, fmax, amax, amid, amin);
823 }
824
825 virtual void getMappingValues(double& amin, double& amid, double& amax)
826 {
827 fA2F.getMappingValues(amin, amid, amax);
828 }
829 };
830
831 //--------------------------------------------------------------------------------------
832 // Convert accelerometer or gyroscope values to Faust values
833 // Using an Up-Down curve (curve 2)
834 //--------------------------------------------------------------------------------------
835 class AccUpDownConverter : public UpdatableValueConverter
836 {
837
838 private:
839
840 Interpolator3pt fA2F;
841 Interpolator fF2A;
842
843 public:
844
845 AccUpDownConverter(double amin, double amid, double amax, double fmin, double fmid, double fmax) :
846 fA2F(amin,amid,amax,fmin,fmax,fmin),
847 fF2A(fmin,fmax,amin,amax) // Special, pseudo inverse of a non monotonic function
848 {}
849
850 virtual double ui2faust(double x) { return fA2F(x); }
851 virtual double faust2ui(double x) { return fF2A(x); }
852
853 virtual void setMappingValues(double amin, double amid, double amax, double fmin, double fmid, double fmax)
854 {
855 //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccUpDownConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax);
856 fA2F = Interpolator3pt(amin, amid, amax, fmin, fmax, fmin);
857 fF2A = Interpolator(fmin, fmax, amin, amax);
858 }
859
860 virtual void getMappingValues(double& amin, double& amid, double& amax)
861 {
862 fA2F.getMappingValues(amin, amid, amax);
863 }
864 };
865
866 //--------------------------------------------------------------------------------------
867 // Convert accelerometer or gyroscope values to Faust values
868 // Using a Down-Up curve (curve 3)
869 //--------------------------------------------------------------------------------------
870 class AccDownUpConverter : public UpdatableValueConverter
871 {
872
873 private:
874
875 Interpolator3pt fA2F;
876 Interpolator fF2A;
877
878 public:
879
880 AccDownUpConverter(double amin, double amid, double amax, double fmin, double fmid, double fmax) :
881 fA2F(amin,amid,amax,fmax,fmin,fmax),
882 fF2A(fmin,fmax,amin,amax) // Special, pseudo inverse of a non monotonic function
883 {}
884
885 virtual double ui2faust(double x) { return fA2F(x); }
886 virtual double faust2ui(double x) { return fF2A(x); }
887
888 virtual void setMappingValues(double amin, double amid, double amax, double fmin, double fmid, double fmax)
889 {
890 //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccDownUpConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax);
891 fA2F = Interpolator3pt(amin, amid, amax, fmax, fmin, fmax);
892 fF2A = Interpolator(fmin, fmax, amin, amax);
893 }
894
895 virtual void getMappingValues(double& amin, double& amid, double& amax)
896 {
897 fA2F.getMappingValues(amin, amid, amax);
898 }
899 };
900
901 //--------------------------------------------------------------------------------------
902 // Base class for ZoneControl
903 //--------------------------------------------------------------------------------------
904 class ZoneControl
905 {
906
907 protected:
908
909 FAUSTFLOAT* fZone;
910
911 public:
912
913 ZoneControl(FAUSTFLOAT* zone) : fZone(zone) {}
914 virtual ~ZoneControl() {}
915
916 virtual void update(double v) const {}
917
918 virtual void setMappingValues(int curve, double amin, double amid, double amax, double min, double init, double max) {}
919 virtual void getMappingValues(double& amin, double& amid, double& amax) {}
920
921 FAUSTFLOAT* getZone() { return fZone; }
922
923 virtual void setActive(bool on_off) {}
924 virtual bool getActive() { return false; }
925
926 virtual int getCurve() { return -1; }
927
928 };
929
930 //--------------------------------------------------------------------------------------
931 // Useful to implement accelerometers metadata as a list of ZoneControl for each axes
932 //--------------------------------------------------------------------------------------
933 class ConverterZoneControl : public ZoneControl
934 {
935
936 protected:
937
938 ValueConverter* fValueConverter;
939
940 public:
941
942 ConverterZoneControl(FAUSTFLOAT* zone, ValueConverter* converter) : ZoneControl(zone), fValueConverter(converter) {}
943 virtual ~ConverterZoneControl() { delete fValueConverter; } // Assuming fValueConverter is not kept elsewhere...
944
945 virtual void update(double v) const { *fZone = fValueConverter->ui2faust(v); }
946
947 ValueConverter* getConverter() { return fValueConverter; }
948
949 };
950
951 //--------------------------------------------------------------------------------------
952 // Association of a zone and a four value converter, each one for each possible curve.
953 // Useful to implement accelerometers metadata as a list of ZoneControl for each axes
954 //--------------------------------------------------------------------------------------
955 class CurveZoneControl : public ZoneControl
956 {
957
958 private:
959
960 std::vector<UpdatableValueConverter*> fValueConverters;
961 int fCurve;
962
963 public:
964
965 CurveZoneControl(FAUSTFLOAT* zone, int curve, double amin, double amid, double amax, double min, double init, double max) : ZoneControl(zone), fCurve(0)
966 {
967 assert(curve >= 0 && curve <= 3);
968 fValueConverters.push_back(new AccUpConverter(amin, amid, amax, min, init, max));
969 fValueConverters.push_back(new AccDownConverter(amin, amid, amax, min, init, max));
970 fValueConverters.push_back(new AccUpDownConverter(amin, amid, amax, min, init, max));
971 fValueConverters.push_back(new AccDownUpConverter(amin, amid, amax, min, init, max));
972 fCurve = curve;
973 }
974 virtual ~CurveZoneControl()
975 {
976 std::vector<UpdatableValueConverter*>::iterator it;
977 for (it = fValueConverters.begin(); it != fValueConverters.end(); it++) {
978 delete(*it);
979 }
980 }
981 void update(double v) const { if (fValueConverters[fCurve]->getActive()) *fZone = fValueConverters[fCurve]->ui2faust(v); }
982
983 void setMappingValues(int curve, double amin, double amid, double amax, double min, double init, double max)
984 {
985 fValueConverters[curve]->setMappingValues(amin, amid, amax, min, init, max);
986 fCurve = curve;
987 }
988
989 void getMappingValues(double& amin, double& amid, double& amax)
990 {
991 fValueConverters[fCurve]->getMappingValues(amin, amid, amax);
992 }
993
994 void setActive(bool on_off)
995 {
996 std::vector<UpdatableValueConverter*>::iterator it;
997 for (it = fValueConverters.begin(); it != fValueConverters.end(); it++) {
998 (*it)->setActive(on_off);
999 }
1000 }
1001
1002 int getCurve() { return fCurve; }
1003 };
1004
1005 class ZoneReader
1006 {
1007
1008 private:
1009
1010 FAUSTFLOAT* fZone;
1011 Interpolator fInterpolator;
1012
1013 public:
1014
1015 ZoneReader(FAUSTFLOAT* zone, double lo, double hi) : fZone(zone), fInterpolator(lo, hi, 0, 255) {}
1016
1017 virtual ~ZoneReader() {}
1018
1019 int getValue()
1020 {
1021 return (fZone != nullptr) ? int(fInterpolator(*fZone)) : 127;
1022 }
1023
1024 };
1025
1026 #endif
1027 /************************** END ValueConverter.h **************************/
1028
1029 class APIUI : public PathBuilder, public Meta, public UI
1030 {
1031 public:
1032
1033 enum ItemType { kButton = 0, kCheckButton, kVSlider, kHSlider, kNumEntry, kHBargraph, kVBargraph };
1034
1035 protected:
1036
1037 enum { kLin = 0, kLog = 1, kExp = 2 };
1038
1039 int fNumParameters;
1040 std::vector<std::string> fPaths;
1041 std::vector<std::string> fLabels;
1042 std::map<std::string, int> fPathMap;
1043 std::map<std::string, int> fLabelMap;
1044 std::vector<ValueConverter*> fConversion;
1045 std::vector<FAUSTFLOAT*> fZone;
1046 std::vector<FAUSTFLOAT> fInit;
1047 std::vector<FAUSTFLOAT> fMin;
1048 std::vector<FAUSTFLOAT> fMax;
1049 std::vector<FAUSTFLOAT> fStep;
1050 std::vector<ItemType> fItemType;
1051 std::vector<std::map<std::string, std::string> > fMetaData;
1052 std::vector<ZoneControl*> fAcc[3];
1053 std::vector<ZoneControl*> fGyr[3];
1054
1055 // Screen color control
1056 // "...[screencolor:red]..." etc.
1057 bool fHasScreenControl; // true if control screen color metadata
1058 ZoneReader* fRedReader;
1059 ZoneReader* fGreenReader;
1060 ZoneReader* fBlueReader;
1061
1062 // Current values controlled by metadata
1063 std::string fCurrentUnit;
1064 int fCurrentScale;
1065 std::string fCurrentAcc;
1066 std::string fCurrentGyr;
1067 std::string fCurrentColor;
1068 std::string fCurrentTooltip;
1069 std::map<std::string, std::string> fCurrentMetadata;
1070
1071 // Add a generic parameter
1072 virtual void addParameter(const char* label,
1073 FAUSTFLOAT* zone,
1074 FAUSTFLOAT init,
1075 FAUSTFLOAT min,
1076 FAUSTFLOAT max,
1077 FAUSTFLOAT step,
1078 ItemType type)
1079 {
1080 std::string path = buildPath(label);
1081 fPathMap[path] = fLabelMap[label] = fNumParameters++;
1082 fPaths.push_back(path);
1083 fLabels.push_back(label);
1084 fZone.push_back(zone);
1085 fInit.push_back(init);
1086 fMin.push_back(min);
1087 fMax.push_back(max);
1088 fStep.push_back(step);
1089 fItemType.push_back(type);
1090
1091 // handle scale metadata
1092 switch (fCurrentScale) {
1093 case kLin:
1094 fConversion.push_back(new LinearValueConverter(0, 1, min, max));
1095 break;
1096 case kLog:
1097 fConversion.push_back(new LogValueConverter(0, 1, min, max));
1098 break;
1099 case kExp: fConversion.push_back(new ExpValueConverter(0, 1, min, max));
1100 break;
1101 }
1102 fCurrentScale = kLin;
1103
1104 if (fCurrentAcc.size() > 0 && fCurrentGyr.size() > 0) {
1105 std::cerr << "warning : 'acc' and 'gyr' metadata used for the same " << label << " parameter !!\n";
1106 }
1107
1108 // handle acc metadata "...[acc : <axe> <curve> <amin> <amid> <amax>]..."
1109 if (fCurrentAcc.size() > 0) {
1110 std::istringstream iss(fCurrentAcc);
1111 int axe, curve;
1112 double amin, amid, amax;
1113 iss >> axe >> curve >> amin >> amid >> amax;
1114
1115 if ((0 <= axe) && (axe < 3) &&
1116 (0 <= curve) && (curve < 4) &&
1117 (amin < amax) && (amin <= amid) && (amid <= amax))
1118 {
1119 fAcc[axe].push_back(new CurveZoneControl(zone, curve, amin, amid, amax, min, init, max));
1120 } else {
1121 std::cerr << "incorrect acc metadata : " << fCurrentAcc << std::endl;
1122 }
1123 fCurrentAcc = "";
1124 }
1125
1126 // handle gyr metadata "...[gyr : <axe> <curve> <amin> <amid> <amax>]..."
1127 if (fCurrentGyr.size() > 0) {
1128 std::istringstream iss(fCurrentGyr);
1129 int axe, curve;
1130 double amin, amid, amax;
1131 iss >> axe >> curve >> amin >> amid >> amax;
1132
1133 if ((0 <= axe) && (axe < 3) &&
1134 (0 <= curve) && (curve < 4) &&
1135 (amin < amax) && (amin <= amid) && (amid <= amax))
1136 {
1137 fGyr[axe].push_back(new CurveZoneControl(zone, curve, amin, amid, amax, min, init, max));
1138 } else {
1139 std::cerr << "incorrect gyr metadata : " << fCurrentGyr << std::endl;
1140 }
1141 fCurrentGyr = "";
1142 }
1143
1144 // handle screencolor metadata "...[screencolor:red|green|blue|white]..."
1145 if (fCurrentColor.size() > 0) {
1146 if ((fCurrentColor == "red") && (fRedReader == 0)) {
1147 fRedReader = new ZoneReader(zone, min, max);
1148 fHasScreenControl = true;
1149 } else if ((fCurrentColor == "green") && (fGreenReader == 0)) {
1150 fGreenReader = new ZoneReader(zone, min, max);
1151 fHasScreenControl = true;
1152 } else if ((fCurrentColor == "blue") && (fBlueReader == 0)) {
1153 fBlueReader = new ZoneReader(zone, min, max);
1154 fHasScreenControl = true;
1155 } else if ((fCurrentColor == "white") && (fRedReader == 0) && (fGreenReader == 0) && (fBlueReader == 0)) {
1156 fRedReader = new ZoneReader(zone, min, max);
1157 fGreenReader = new ZoneReader(zone, min, max);
1158 fBlueReader = new ZoneReader(zone, min, max);
1159 fHasScreenControl = true;
1160 } else {
1161 std::cerr << "incorrect screencolor metadata : " << fCurrentColor << std::endl;
1162 }
1163 }
1164 fCurrentColor = "";
1165
1166 fMetaData.push_back(fCurrentMetadata);
1167 fCurrentMetadata.clear();
1168 }
1169
1170 int getZoneIndex(std::vector<ZoneControl*>* table, int p, int val)
1171 {
1172 FAUSTFLOAT* zone = fZone[p];
1173 for (size_t i = 0; i < table[val].size(); i++) {
1174 if (zone == table[val][i]->getZone()) return int(i);
1175 }
1176 return -1;
1177 }
1178
1179 void setConverter(std::vector<ZoneControl*>* table, int p, int val, int curve, double amin, double amid, double amax)
1180 {
1181 int id1 = getZoneIndex(table, p, 0);
1182 int id2 = getZoneIndex(table, p, 1);
1183 int id3 = getZoneIndex(table, p, 2);
1184
1185 // Deactivates everywhere..
1186 if (id1 != -1) table[0][id1]->setActive(false);
1187 if (id2 != -1) table[1][id2]->setActive(false);
1188 if (id3 != -1) table[2][id3]->setActive(false);
1189
1190 if (val == -1) { // Means: no more mapping...
1191 // So stay all deactivated...
1192 } else {
1193 int id4 = getZoneIndex(table, p, val);
1194 if (id4 != -1) {
1195 // Reactivate the one we edit...
1196 table[val][id4]->setMappingValues(curve, amin, amid, amax, fMin[p], fInit[p], fMax[p]);
1197 table[val][id4]->setActive(true);
1198 } else {
1199 // Allocate a new CurveZoneControl which is 'active' by default
1200 FAUSTFLOAT* zone = fZone[p];
1201 table[val].push_back(new CurveZoneControl(zone, curve, amin, amid, amax, fMin[p], fInit[p], fMax[p]));
1202 }
1203 }
1204 }
1205
1206 void getConverter(std::vector<ZoneControl*>* table, int p, int& val, int& curve, double& amin, double& amid, double& amax)
1207 {
1208 int id1 = getZoneIndex(table, p, 0);
1209 int id2 = getZoneIndex(table, p, 1);
1210 int id3 = getZoneIndex(table, p, 2);
1211
1212 if (id1 != -1) {
1213 val = 0;
1214 curve = table[val][id1]->getCurve();
1215 table[val][id1]->getMappingValues(amin, amid, amax);
1216 } else if (id2 != -1) {
1217 val = 1;
1218 curve = table[val][id2]->getCurve();
1219 table[val][id2]->getMappingValues(amin, amid, amax);
1220 } else if (id3 != -1) {
1221 val = 2;
1222 curve = table[val][id3]->getCurve();
1223 table[val][id3]->getMappingValues(amin, amid, amax);
1224 } else {
1225 val = -1; // No mapping
1226 curve = 0;
1227 amin = -100.;
1228 amid = 0.;
1229 amax = 100.;
1230 }
1231 }
1232
1233 public:
1234
1235 enum Type { kAcc = 0, kGyr = 1, kNoType };
1236
1237 APIUI() : fNumParameters(0), fHasScreenControl(false), fRedReader(0), fGreenReader(0), fBlueReader(0), fCurrentScale(kLin)
1238 {}
1239
1240 virtual ~APIUI()
1241 {
1242 for (auto& it : fConversion) delete it;
1243 for (int i = 0; i < 3; i++) {
1244 for (auto& it : fAcc[i]) delete it;
1245 for (auto& it : fGyr[i]) delete it;
1246 }
1247 delete fRedReader;
1248 delete fGreenReader;
1249 delete fBlueReader;
1250 }
1251
1252 // -- widget's layouts
1253
1254 virtual void openTabBox(const char* label) { pushLabel(label); }
1255 virtual void openHorizontalBox(const char* label) { pushLabel(label); }
1256 virtual void openVerticalBox(const char* label) { pushLabel(label); }
1257 virtual void closeBox() { popLabel(); }
1258
1259 // -- active widgets
1260
1261 virtual void addButton(const char* label, FAUSTFLOAT* zone)
1262 {
1263 addParameter(label, zone, 0, 0, 1, 1, kButton);
1264 }
1265
1266 virtual void addCheckButton(const char* label, FAUSTFLOAT* zone)
1267 {
1268 addParameter(label, zone, 0, 0, 1, 1, kCheckButton);
1269 }
1270
1271 virtual void addVerticalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step)
1272 {
1273 addParameter(label, zone, init, min, max, step, kVSlider);
1274 }
1275
1276 virtual void addHorizontalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step)
1277 {
1278 addParameter(label, zone, init, min, max, step, kHSlider);
1279 }
1280
1281 virtual void addNumEntry(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step)
1282 {
1283 addParameter(label, zone, init, min, max, step, kNumEntry);
1284 }
1285
1286 // -- passive widgets
1287
1288 virtual void addHorizontalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max)
1289 {
1290 addParameter(label, zone, min, min, max, (max-min)/1000.0, kHBargraph);
1291 }
1292
1293 virtual void addVerticalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max)
1294 {
1295 addParameter(label, zone, min, min, max, (max-min)/1000.0, kVBargraph);
1296 }
1297
1298 // -- soundfiles
1299
1300 virtual void addSoundfile(const char* label, const char* filename, Soundfile** sf_zone) {}
1301
1302 // -- metadata declarations
1303
1304 virtual void declare(FAUSTFLOAT* zone, const char* key, const char* val)
1305 {
1306 // Keep metadata
1307 fCurrentMetadata[key] = val;
1308
1309 if (strcmp(key, "scale") == 0) {
1310 if (strcmp(val, "log") == 0) {
1311 fCurrentScale = kLog;
1312 } else if (strcmp(val, "exp") == 0) {
1313 fCurrentScale = kExp;
1314 } else {
1315 fCurrentScale = kLin;
1316 }
1317 } else if (strcmp(key, "unit") == 0) {
1318 fCurrentUnit = val;
1319 } else if (strcmp(key, "acc") == 0) {
1320 fCurrentAcc = val;
1321 } else if (strcmp(key, "gyr") == 0) {
1322 fCurrentGyr = val;
1323 } else if (strcmp(key, "screencolor") == 0) {
1324 fCurrentColor = val; // val = "red", "green", "blue" or "white"
1325 } else if (strcmp(key, "tooltip") == 0) {
1326 fCurrentTooltip = val;
1327 }
1328 }
1329
1330 virtual void declare(const char* key, const char* val)
1331 {}
1332
1333 //-------------------------------------------------------------------------------
1334 // Simple API part
1335 //-------------------------------------------------------------------------------
1336 int getParamsCount() { return fNumParameters; }
1337 int getParamIndex(const char* path)
1338 {
1339 if (fPathMap.find(path) != fPathMap.end()) {
1340 return fPathMap[path];
1341 } else if (fLabelMap.find(path) != fLabelMap.end()) {
1342 return fLabelMap[path];
1343 } else {
1344 return -1;
1345 }
1346 }
1347 const char* getParamAddress(int p) { return fPaths[p].c_str(); }
1348 const char* getParamLabel(int p) { return fLabels[p].c_str(); }
1349 std::map<const char*, const char*> getMetadata(int p)
1350 {
1351 std::map<const char*, const char*> res;
1352 std::map<std::string, std::string> metadata = fMetaData[p];
1353 for (auto it : metadata) {
1354 res[it.first.c_str()] = it.second.c_str();
1355 }
1356 return res;
1357 }
1358
1359 const char* getMetadata(int p, const char* key)
1360 {
1361 return (fMetaData[p].find(key) != fMetaData[p].end()) ? fMetaData[p][key].c_str() : "";
1362 }
1363 FAUSTFLOAT getParamMin(int p) { return fMin[p]; }
1364 FAUSTFLOAT getParamMax(int p) { return fMax[p]; }
1365 FAUSTFLOAT getParamStep(int p) { return fStep[p]; }
1366 FAUSTFLOAT getParamInit(int p) { return fInit[p]; }
1367
1368 FAUSTFLOAT* getParamZone(int p) { return fZone[p]; }
1369 FAUSTFLOAT getParamValue(int p) { return *fZone[p]; }
1370 void setParamValue(int p, FAUSTFLOAT v) { *fZone[p] = v; }
1371
1372 double getParamRatio(int p) { return fConversion[p]->faust2ui(*fZone[p]); }
1373 void setParamRatio(int p, double r) { *fZone[p] = fConversion[p]->ui2faust(r); }
1374
1375 double value2ratio(int p, double r) { return fConversion[p]->faust2ui(r); }
1376 double ratio2value(int p, double r) { return fConversion[p]->ui2faust(r); }
1377
1378 /**
1379 * Return the control type (kAcc, kGyr, or -1) for a given parameter
1380 *
1381 * @param p - the UI parameter index
1382 *
1383 * @return the type
1384 */
1385 Type getParamType(int p)
1386 {
1387 if (p >= 0) {
1388 if (getZoneIndex(fAcc, p, 0) != -1
1389 || getZoneIndex(fAcc, p, 1) != -1
1390 || getZoneIndex(fAcc, p, 2) != -1) {
1391 return kAcc;
1392 } else if (getZoneIndex(fGyr, p, 0) != -1
1393 || getZoneIndex(fGyr, p, 1) != -1
1394 || getZoneIndex(fGyr, p, 2) != -1) {
1395 return kGyr;
1396 }
1397 }
1398 return kNoType;
1399 }
1400
1401 /**
1402 * Return the Item type (kButton = 0, kCheckButton, kVSlider, kHSlider, kNumEntry, kHBargraph, kVBargraph) for a given parameter
1403 *
1404 * @param p - the UI parameter index
1405 *
1406 * @return the Item type
1407 */
1408 ItemType getParamItemType(int p)
1409 {
1410 return fItemType[p];
1411 }
1412
1413 /**
1414 * Set a new value coming from an accelerometer, propagate it to all relevant FAUSTFLOAT* zones.
1415 *
1416 * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer
1417 * @param value - the new value
1418 *
1419 */
1420 void propagateAcc(int acc, double value)
1421 {
1422 for (size_t i = 0; i < fAcc[acc].size(); i++) {
1423 fAcc[acc][i]->update(value);
1424 }
1425 }
1426
1427 /**
1428 * Used to edit accelerometer curves and mapping. Set curve and related mapping for a given UI parameter.
1429 *
1430 * @param p - the UI parameter index
1431 * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer (-1 means "no mapping")
1432 * @param curve - between 0 and 3
1433 * @param amin - mapping 'min' point
1434 * @param amid - mapping 'middle' point
1435 * @param amax - mapping 'max' point
1436 *
1437 */
1438 void setAccConverter(int p, int acc, int curve, double amin, double amid, double amax)
1439 {
1440 setConverter(fAcc, p, acc, curve, amin, amid, amax);
1441 }
1442
1443 /**
1444 * Used to edit gyroscope curves and mapping. Set curve and related mapping for a given UI parameter.
1445 *
1446 * @param p - the UI parameter index
1447 * @param acc - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope (-1 means "no mapping")
1448 * @param curve - between 0 and 3
1449 * @param amin - mapping 'min' point
1450 * @param amid - mapping 'middle' point
1451 * @param amax - mapping 'max' point
1452 *
1453 */
1454 void setGyrConverter(int p, int gyr, int curve, double amin, double amid, double amax)
1455 {
1456 setConverter(fGyr, p, gyr, curve, amin, amid, amax);
1457 }
1458
1459 /**
1460 * Used to edit accelerometer curves and mapping. Get curve and related mapping for a given UI parameter.
1461 *
1462 * @param p - the UI parameter index
1463 * @param acc - the acc value to be retrieved (-1 means "no mapping")
1464 * @param curve - the curve value to be retrieved
1465 * @param amin - the amin value to be retrieved
1466 * @param amid - the amid value to be retrieved
1467 * @param amax - the amax value to be retrieved
1468 *
1469 */
1470 void getAccConverter(int p, int& acc, int& curve, double& amin, double& amid, double& amax)
1471 {
1472 getConverter(fAcc, p, acc, curve, amin, amid, amax);
1473 }
1474
1475 /**
1476 * Used to edit gyroscope curves and mapping. Get curve and related mapping for a given UI parameter.
1477 *
1478 * @param p - the UI parameter index
1479 * @param gyr - the gyr value to be retrieved (-1 means "no mapping")
1480 * @param curve - the curve value to be retrieved
1481 * @param amin - the amin value to be retrieved
1482 * @param amid - the amid value to be retrieved
1483 * @param amax - the amax value to be retrieved
1484 *
1485 */
1486 void getGyrConverter(int p, int& gyr, int& curve, double& amin, double& amid, double& amax)
1487 {
1488 getConverter(fGyr, p, gyr, curve, amin, amid, amax);
1489 }
1490
1491 /**
1492 * Set a new value coming from an gyroscope, propagate it to all relevant FAUSTFLOAT* zones.
1493 *
1494 * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope
1495 * @param value - the new value
1496 *
1497 */
1498 void propagateGyr(int gyr, double value)
1499 {
1500 for (size_t i = 0; i < fGyr[gyr].size(); i++) {
1501 fGyr[gyr][i]->update(value);
1502 }
1503 }
1504
1505 /**
1506 * Get the number of FAUSTFLOAT* zones controlled with the accelerometer
1507 *
1508 * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer
1509 * @return the number of zones
1510 *
1511 */
1512 int getAccCount(int acc)
1513 {
1514 return (acc >= 0 && acc < 3) ? int(fAcc[acc].size()) : 0;
1515 }
1516
1517 /**
1518 * Get the number of FAUSTFLOAT* zones controlled with the gyroscope
1519 *
1520 * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope
1521 * @param the number of zones
1522 *
1523 */
1524 int getGyrCount(int gyr)
1525 {
1526 return (gyr >= 0 && gyr < 3) ? int(fGyr[gyr].size()) : 0;
1527 }
1528
1529 // getScreenColor() : -1 means no screen color control (no screencolor metadata found)
1530 // otherwise return 0x00RRGGBB a ready to use color
1531 int getScreenColor()
1532 {
1533 if (fHasScreenControl) {
1534 int r = (fRedReader) ? fRedReader->getValue() : 0;
1535 int g = (fGreenReader) ? fGreenReader->getValue() : 0;
1536 int b = (fBlueReader) ? fBlueReader->getValue() : 0;
1537 return (r<<16) | (g<<8) | b;
1538 } else {
1539 return -1;
1540 }
1541 }
1542
1543 };
1544
1545 #endif
1546 /************************** END APIUI.h **************************/
1547
1548 // NOTE: "faust -scn name" changes the last line above to
1549 // #include <faust/name/name.h>
1550
1551 //----------------------------------------------------------------------------
1552 // FAUST Generated Code
1553 //----------------------------------------------------------------------------
1554
1555
1556 #ifndef FAUSTFLOAT
1557 #define FAUSTFLOAT float
1558 #endif
1559
1560 #include <algorithm>
1561 #include <cmath>
1562 #include <math.h>
1563
1564
1565 #ifndef FAUSTCLASS
1566 #define FAUSTCLASS compressordsp
1567 #endif
1568
1569 #ifdef __APPLE__
1570 #define exp10f __exp10f
1571 #define exp10 __exp10
1572 #endif
1573
1574 class compressordsp : public dsp {
1575
1576 private:
1577
1578 FAUSTFLOAT fCheckbox0;
1579 FAUSTFLOAT fHslider0;
1580 int fSampleRate;
1581 float fConst0;
1582 FAUSTFLOAT fHslider1;
1583 FAUSTFLOAT fHslider2;
1584 FAUSTFLOAT fHslider3;
1585 float fRec5[2];
1586 float fRec4[2];
1587 FAUSTFLOAT fHslider4;
1588 float fRec3[2];
1589 float fRec2[2];
1590 float fRec1[2];
1591 float fRec0[2];
1592 FAUSTFLOAT fHbargraph0;
1593
1594 public:
1595
1596 void metadata(Meta* m) {
1597 m->declare("analyzers.lib/name", "Faust Analyzer Library");
1598 m->declare("analyzers.lib/version", "0.1");
1599 m->declare("author", "Julius Smith");
1600 m->declare("basics.lib/name", "Faust Basic Element Library");
1601 m->declare("basics.lib/version", "0.1");
1602 m->declare("compressors.lib/compression_gain_mono:author", "Julius O. Smith III");
1603 m->declare("compressors.lib/compression_gain_mono:copyright", "Copyright (C) 2014-2020 by Julius O. Smith III <jos@ccrma.stanford.edu>");
1604 m->declare("compressors.lib/compression_gain_mono:license", "MIT-style STK-4.3 license");
1605 m->declare("compressors.lib/compressor_lad_mono:author", "Julius O. Smith III");
1606 m->declare("compressors.lib/compressor_lad_mono:copyright", "Copyright (C) 2014-2020 by Julius O. Smith III <jos@ccrma.stanford.edu>");
1607 m->declare("compressors.lib/compressor_lad_mono:license", "MIT-style STK-4.3 license");
1608 m->declare("compressors.lib/compressor_mono:author", "Julius O. Smith III");
1609 m->declare("compressors.lib/compressor_mono:copyright", "Copyright (C) 2014-2020 by Julius O. Smith III <jos@ccrma.stanford.edu>");
1610 m->declare("compressors.lib/compressor_mono:license", "MIT-style STK-4.3 license");
1611 m->declare("compressors.lib/name", "Faust Compressor Effect Library");
1612 m->declare("compressors.lib/version", "0.0");
1613 m->declare("description", "Compressor demo application, adapted from the Faust Library's dm.compressor_demo in demos.lib");
1614 m->declare("documentation", "https://faustlibraries.grame.fr/libs/compressors/#cocompressor_mono");
1615 m->declare("filename", "compressordsp.dsp");
1616 m->declare("license", "MIT Style STK-4.2");
1617 m->declare("maths.lib/author", "GRAME");
1618 m->declare("maths.lib/copyright", "GRAME");
1619 m->declare("maths.lib/license", "LGPL with exception");
1620 m->declare("maths.lib/name", "Faust Math Library");
1621 m->declare("maths.lib/version", "2.3");
1622 m->declare("name", "compressor");
1623 m->declare("platform.lib/name", "Generic Platform Library");
1624 m->declare("platform.lib/version", "0.1");
1625 m->declare("signals.lib/name", "Faust Signal Routing Library");
1626 m->declare("signals.lib/version", "0.0");
1627 m->declare("version", "0.0");
1628 }
1629
1630 virtual int getNumInputs() {
1631 return 1;
1632 }
1633 virtual int getNumOutputs() {
1634 return 1;
1635 }
1636 virtual int getInputRate(int channel) {
1637 int rate;
1638 switch ((channel)) {
1639 case 0: {
1640 rate = 1;
1641 break;
1642 }
1643 default: {
1644 rate = -1;
1645 break;
1646 }
1647 }
1648 return rate;
1649 }
1650 virtual int getOutputRate(int channel) {
1651 int rate;
1652 switch ((channel)) {
1653 case 0: {
1654 rate = 1;
1655 break;
1656 }
1657 default: {
1658 rate = -1;
1659 break;
1660 }
1661 }
1662 return rate;
1663 }
1664
1665 static void classInit(int sample_rate) {
1666 }
1667
1668 virtual void instanceConstants(int sample_rate) {
1669 fSampleRate = sample_rate;
1670 fConst0 = (1.0f / std::min<float>(192000.0f, std::max<float>(1.0f, float(fSampleRate))));
1671 }
1672
1673 virtual void instanceResetUserInterface() {
1674 fCheckbox0 = FAUSTFLOAT(0.0f);
1675 fHslider0 = FAUSTFLOAT(2.0f);
1676 fHslider1 = FAUSTFLOAT(15.0f);
1677 fHslider2 = FAUSTFLOAT(2.0f);
1678 fHslider3 = FAUSTFLOAT(40.0f);
1679 fHslider4 = FAUSTFLOAT(-24.0f);
1680 }
1681
1682 virtual void instanceClear() {
1683 for (int l0 = 0; (l0 < 2); l0 = (l0 + 1)) {
1684 fRec5[l0] = 0.0f;
1685 }
1686 for (int l1 = 0; (l1 < 2); l1 = (l1 + 1)) {
1687 fRec4[l1] = 0.0f;
1688 }
1689 for (int l2 = 0; (l2 < 2); l2 = (l2 + 1)) {
1690 fRec3[l2] = 0.0f;
1691 }
1692 for (int l3 = 0; (l3 < 2); l3 = (l3 + 1)) {
1693 fRec2[l3] = 0.0f;
1694 }
1695 for (int l4 = 0; (l4 < 2); l4 = (l4 + 1)) {
1696 fRec1[l4] = 0.0f;
1697 }
1698 for (int l5 = 0; (l5 < 2); l5 = (l5 + 1)) {
1699 fRec0[l5] = 0.0f;
1700 }
1701 }
1702
1703 virtual void init(int sample_rate) {
1704 classInit(sample_rate);
1705 instanceInit(sample_rate);
1706 }
1707 virtual void instanceInit(int sample_rate) {
1708 instanceConstants(sample_rate);
1709 instanceResetUserInterface();
1710 instanceClear();
1711 }
1712
1713 virtual compressordsp* clone() {
1714 return new compressordsp();
1715 }
1716
1717 virtual int getSampleRate() {
1718 return fSampleRate;
1719 }
1720
1721 virtual void buildUserInterface(UI* ui_interface) {
1722 ui_interface->declare(0, "tooltip", "References: https://faustlibraries.grame.fr/libs/compressors/ http://en.wikipedia.org/wiki/Dynamic_range_compression");
1723 ui_interface->openVerticalBox("COMPRESSOR");
1724 ui_interface->declare(0, "0", "");
1725 ui_interface->openHorizontalBox("0x00");
1726 ui_interface->declare(&fCheckbox0, "0", "");
1727 ui_interface->declare(&fCheckbox0, "tooltip", "When this is checked, the compressor has no effect");
1728 ui_interface->addCheckButton("Bypass", &fCheckbox0);
1729 ui_interface->declare(&fHbargraph0, "1", "");
1730 ui_interface->declare(&fHbargraph0, "tooltip", "Compressor gain in dB");
1731 ui_interface->declare(&fHbargraph0, "unit", "dB");
1732 ui_interface->addHorizontalBargraph("Compressor Gain", &fHbargraph0, -50.0f, 10.0f);
1733 ui_interface->closeBox();
1734 ui_interface->declare(0, "1", "");
1735 ui_interface->openHorizontalBox("0x00");
1736 ui_interface->declare(0, "3", "");
1737 ui_interface->openHorizontalBox("Compression Control");
1738 ui_interface->declare(&fHslider2, "0", "");
1739 ui_interface->declare(&fHslider2, "style", "knob");
1740 ui_interface->declare(&fHslider2, "tooltip", "A compression Ratio of N means that for each N dB increase in input signal level above Threshold, the output level goes up 1 dB");
1741 ui_interface->addHorizontalSlider("Ratio", &fHslider2, 2.0f, 1.0f, 20.0f, 0.100000001f);
1742 ui_interface->declare(&fHslider4, "1", "");
1743 ui_interface->declare(&fHslider4, "style", "knob");
1744 ui_interface->declare(&fHslider4, "tooltip", "When the signal level exceeds the Threshold (in dB), its level is compressed according to the Ratio");
1745 ui_interface->declare(&fHslider4, "unit", "dB");
1746 ui_interface->addHorizontalSlider("Threshold", &fHslider4, -24.0f, -100.0f, 10.0f, 0.100000001f);
1747 ui_interface->closeBox();
1748 ui_interface->declare(0, "4", "");
1749 ui_interface->openHorizontalBox("Compression Response");
1750 ui_interface->declare(&fHslider1, "1", "");
1751 ui_interface->declare(&fHslider1, "scale", "log");
1752 ui_interface->declare(&fHslider1, "style", "knob");
1753 ui_interface->declare(&fHslider1, "tooltip", "Time constant in ms (1/e smoothing time) for the compression gain to approach (exponentially) a new lower target level (the compression `kicking in')");
1754 ui_interface->declare(&fHslider1, "unit", "ms");
1755 ui_interface->addHorizontalSlider("Attack", &fHslider1, 15.0f, 1.0f, 1000.0f, 0.100000001f);
1756 ui_interface->declare(&fHslider3, "2", "");
1757 ui_interface->declare(&fHslider3, "scale", "log");
1758 ui_interface->declare(&fHslider3, "style", "knob");
1759 ui_interface->declare(&fHslider3, "tooltip", "Time constant in ms (1/e smoothing time) for the compression gain to approach (exponentially) a new higher target level (the compression 'releasing')");
1760 ui_interface->declare(&fHslider3, "unit", "ms");
1761 ui_interface->addHorizontalSlider("Release", &fHslider3, 40.0f, 1.0f, 1000.0f, 0.100000001f);
1762 ui_interface->closeBox();
1763 ui_interface->closeBox();
1764 ui_interface->declare(&fHslider0, "5", "");
1765 ui_interface->declare(&fHslider0, "tooltip", "The compressed-signal output level is increased by this amount (in dB) to make up for the level lost due to compression");
1766 ui_interface->declare(&fHslider0, "unit", "dB");
1767 ui_interface->addHorizontalSlider("MakeUpGain", &fHslider0, 2.0f, -96.0f, 96.0f, 0.100000001f);
1768 ui_interface->closeBox();
1769 }
1770
1771 virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) {
1772 FAUSTFLOAT* input0 = inputs[0];
1773 FAUSTFLOAT* output0 = outputs[0];
1774 int iSlow0 = int(float(fCheckbox0));
1775 float fSlow1 = std::pow(10.0f, (0.0500000007f * float(fHslider0)));
1776 float fSlow2 = std::max<float>(fConst0, (0.00100000005f * float(fHslider1)));
1777 float fSlow3 = (0.5f * fSlow2);
1778 int iSlow4 = (std::fabs(fSlow3) < 1.1920929e-07f);
1779 float fSlow5 = (iSlow4 ? 0.0f : std::exp((0.0f - (fConst0 / (iSlow4 ? 1.0f : fSlow3)))));
1780 float fSlow6 = ((1.0f / std::max<float>(1.00000001e-07f, float(fHslider2))) + -1.0f);
1781 int iSlow7 = (std::fabs(fSlow2) < 1.1920929e-07f);
1782 float fSlow8 = (iSlow7 ? 0.0f : std::exp((0.0f - (fConst0 / (iSlow7 ? 1.0f : fSlow2)))));
1783 float fSlow9 = std::max<float>(fConst0, (0.00100000005f * float(fHslider3)));
1784 int iSlow10 = (std::fabs(fSlow9) < 1.1920929e-07f);
1785 float fSlow11 = (iSlow10 ? 0.0f : std::exp((0.0f - (fConst0 / (iSlow10 ? 1.0f : fSlow9)))));
1786 float fSlow12 = float(fHslider4);
1787 float fSlow13 = (1.0f - fSlow5);
1788 for (int i = 0; (i < count); i = (i + 1)) {
1789 float fTemp0 = float(input0[i]);
1790 float fTemp1 = (iSlow0 ? 0.0f : fTemp0);
1791 float fTemp2 = std::fabs(fTemp1);
1792 float fTemp3 = ((fRec4[1] > fTemp2) ? fSlow11 : fSlow8);
1793 fRec5[0] = ((fRec5[1] * fTemp3) + (fTemp2 * (1.0f - fTemp3)));
1794 fRec4[0] = fRec5[0];
1795 fRec3[0] = ((fRec3[1] * fSlow5) + (fSlow6 * (std::max<float>(((20.0f * std::log10(fRec4[0])) - fSlow12), 0.0f) * fSlow13)));
1796 float fTemp4 = (fTemp1 * std::pow(10.0f, (0.0500000007f * fRec3[0])));
1797 float fTemp5 = std::fabs(fTemp4);
1798 float fTemp6 = ((fRec1[1] > fTemp5) ? fSlow11 : fSlow8);
1799 fRec2[0] = ((fRec2[1] * fTemp6) + (fTemp5 * (1.0f - fTemp6)));
1800 fRec1[0] = fRec2[0];
1801 fRec0[0] = ((fSlow5 * fRec0[1]) + (fSlow6 * (std::max<float>(((20.0f * std::log10(fRec1[0])) - fSlow12), 0.0f) * fSlow13)));
1802 fHbargraph0 = FAUSTFLOAT((20.0f * std::log10(std::pow(10.0f, (0.0500000007f * fRec0[0])))));
1803 output0[i] = FAUSTFLOAT((iSlow0 ? fTemp0 : (fSlow1 * fTemp4)));
1804 fRec5[1] = fRec5[0];
1805 fRec4[1] = fRec4[0];
1806 fRec3[1] = fRec3[0];
1807 fRec2[1] = fRec2[0];
1808 fRec1[1] = fRec1[0];
1809 fRec0[1] = fRec0[0];
1810 }
1811 }
1812
1813 };
1814
1815 #endif
0 /* ------------------------------------------------------------
1 author: "Romain Michon"
2 license: "LGPL"
3 name: "freeverb"
4 version: "0.0"
5 Code generated with Faust 2.28.6 (https://faust.grame.fr)
6 Compilation options: -lang cpp -inpl -scal -ftz 0
7 ------------------------------------------------------------ */
8
9 #ifndef __freeverbdsp_H__
10 #define __freeverbdsp_H__
11
12 // NOTE: ANY INCLUDE-GUARD HERE MUST BE DERIVED FROM THE CLASS NAME
13 //
14 // faust2header.cpp - FAUST Architecture File
15 // This is a simple variation of matlabplot.cpp in the Faust distribution
16 // aimed at creating a simple C++ header file (.h) containing a Faust DSP.
17 // See the Makefile for how to use it.
18
19 /************************** BEGIN dsp.h **************************/
20 /************************************************************************
21 FAUST Architecture File
22 Copyright (C) 2003-2017 GRAME, Centre National de Creation Musicale
23 ---------------------------------------------------------------------
24 This Architecture section is free software; you can redistribute it
25 and/or modify it under the terms of the GNU General Public License
26 as published by the Free Software Foundation; either version 3 of
27 the License, or (at your option) any later version.
28
29 This program is distributed in the hope that it will be useful,
30 but WITHOUT ANY WARRANTY; without even the implied warranty of
31 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 GNU General Public License for more details.
33
34 You should have received a copy of the GNU General Public License
35 along with this program; If not, see <http://www.gnu.org/licenses/>.
36
37 EXCEPTION : As a special exception, you may create a larger work
38 that contains this FAUST architecture section and distribute
39 that work under terms of your choice, so long as this FAUST
40 architecture section is not modified.
41 ************************************************************************/
42
43 #ifndef __dsp__
44 #define __dsp__
45
46 #include <string>
47 #include <vector>
48
49 #ifndef FAUSTFLOAT
50 #define FAUSTFLOAT float
51 #endif
52
53 struct UI;
54 struct Meta;
55
56 /**
57 * DSP memory manager.
58 */
59
60 struct dsp_memory_manager {
61
62 virtual ~dsp_memory_manager() {}
63
64 virtual void* allocate(size_t size) = 0;
65 virtual void destroy(void* ptr) = 0;
66
67 };
68
69 /**
70 * Signal processor definition.
71 */
72
73 class dsp {
74
75 public:
76
77 dsp() {}
78 virtual ~dsp() {}
79
80 /* Return instance number of audio inputs */
81 virtual int getNumInputs() = 0;
82
83 /* Return instance number of audio outputs */
84 virtual int getNumOutputs() = 0;
85
86 /**
87 * Trigger the ui_interface parameter with instance specific calls
88 * to 'openTabBox', 'addButton', 'addVerticalSlider'... in order to build the UI.
89 *
90 * @param ui_interface - the user interface builder
91 */
92 virtual void buildUserInterface(UI* ui_interface) = 0;
93
94 /* Returns the sample rate currently used by the instance */
95 virtual int getSampleRate() = 0;
96
97 /**
98 * Global init, calls the following methods:
99 * - static class 'classInit': static tables initialization
100 * - 'instanceInit': constants and instance state initialization
101 *
102 * @param sample_rate - the sampling rate in Hertz
103 */
104 virtual void init(int sample_rate) = 0;
105
106 /**
107 * Init instance state
108 *
109 * @param sample_rate - the sampling rate in Hertz
110 */
111 virtual void instanceInit(int sample_rate) = 0;
112
113 /**
114 * Init instance constant state
115 *
116 * @param sample_rate - the sampling rate in Hertz
117 */
118 virtual void instanceConstants(int sample_rate) = 0;
119
120 /* Init default control parameters values */
121 virtual void instanceResetUserInterface() = 0;
122
123 /* Init instance state (delay lines...) */
124 virtual void instanceClear() = 0;
125
126 /**
127 * Return a clone of the instance.
128 *
129 * @return a copy of the instance on success, otherwise a null pointer.
130 */
131 virtual dsp* clone() = 0;
132
133 /**
134 * Trigger the Meta* parameter with instance specific calls to 'declare' (key, value) metadata.
135 *
136 * @param m - the Meta* meta user
137 */
138 virtual void metadata(Meta* m) = 0;
139
140 /**
141 * DSP instance computation, to be called with successive in/out audio buffers.
142 *
143 * @param count - the number of frames to compute
144 * @param inputs - the input audio buffers as an array of non-interleaved FAUSTFLOAT samples (eiher float, double or quad)
145 * @param outputs - the output audio buffers as an array of non-interleaved FAUSTFLOAT samples (eiher float, double or quad)
146 *
147 */
148 virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) = 0;
149
150 /**
151 * DSP instance computation: alternative method to be used by subclasses.
152 *
153 * @param date_usec - the timestamp in microsec given by audio driver.
154 * @param count - the number of frames to compute
155 * @param inputs - the input audio buffers as an array of non-interleaved FAUSTFLOAT samples (either float, double or quad)
156 * @param outputs - the output audio buffers as an array of non-interleaved FAUSTFLOAT samples (either float, double or quad)
157 *
158 */
159 virtual void compute(double /*date_usec*/, int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { compute(count, inputs, outputs); }
160
161 };
162
163 /**
164 * Generic DSP decorator.
165 */
166
167 class decorator_dsp : public dsp {
168
169 protected:
170
171 dsp* fDSP;
172
173 public:
174
175 decorator_dsp(dsp* dsp = nullptr):fDSP(dsp) {}
176 virtual ~decorator_dsp() { delete fDSP; }
177
178 virtual int getNumInputs() { return fDSP->getNumInputs(); }
179 virtual int getNumOutputs() { return fDSP->getNumOutputs(); }
180 virtual void buildUserInterface(UI* ui_interface) { fDSP->buildUserInterface(ui_interface); }
181 virtual int getSampleRate() { return fDSP->getSampleRate(); }
182 virtual void init(int sample_rate) { fDSP->init(sample_rate); }
183 virtual void instanceInit(int sample_rate) { fDSP->instanceInit(sample_rate); }
184 virtual void instanceConstants(int sample_rate) { fDSP->instanceConstants(sample_rate); }
185 virtual void instanceResetUserInterface() { fDSP->instanceResetUserInterface(); }
186 virtual void instanceClear() { fDSP->instanceClear(); }
187 virtual decorator_dsp* clone() { return new decorator_dsp(fDSP->clone()); }
188 virtual void metadata(Meta* m) { fDSP->metadata(m); }
189 // Beware: subclasses usually have to overload the two 'compute' methods
190 virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { fDSP->compute(count, inputs, outputs); }
191 virtual void compute(double date_usec, int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { fDSP->compute(date_usec, count, inputs, outputs); }
192
193 };
194
195 /**
196 * DSP factory class.
197 */
198
199 class dsp_factory {
200
201 protected:
202
203 // So that to force sub-classes to use deleteDSPFactory(dsp_factory* factory);
204 virtual ~dsp_factory() {}
205
206 public:
207
208 virtual std::string getName() = 0;
209 virtual std::string getSHAKey() = 0;
210 virtual std::string getDSPCode() = 0;
211 virtual std::string getCompileOptions() = 0;
212 virtual std::vector<std::string> getLibraryList() = 0;
213 virtual std::vector<std::string> getIncludePathnames() = 0;
214
215 virtual dsp* createDSPInstance() = 0;
216
217 virtual void setMemoryManager(dsp_memory_manager* manager) = 0;
218 virtual dsp_memory_manager* getMemoryManager() = 0;
219
220 };
221
222 /**
223 * On Intel set FZ (Flush to Zero) and DAZ (Denormals Are Zero)
224 * flags to avoid costly denormals.
225 */
226
227 #ifdef __SSE__
228 #include <xmmintrin.h>
229 #ifdef __SSE2__
230 #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8040)
231 #else
232 #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8000)
233 #endif
234 #else
235 #define AVOIDDENORMALS
236 #endif
237
238 #endif
239 /************************** END dsp.h **************************/
240
241 /************************** BEGIN APIUI.h **************************/
242 /************************************************************************
243 FAUST Architecture File
244 Copyright (C) 2003-2017 GRAME, Centre National de Creation Musicale
245 ---------------------------------------------------------------------
246 This Architecture section is free software; you can redistribute it
247 and/or modify it under the terms of the GNU General Public License
248 as published by the Free Software Foundation; either version 3 of
249 the License, or (at your option) any later version.
250
251 This program is distributed in the hope that it will be useful,
252 but WITHOUT ANY WARRANTY; without even the implied warranty of
253 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
254 GNU General Public License for more details.
255
256 You should have received a copy of the GNU General Public License
257 along with this program; If not, see <http://www.gnu.org/licenses/>.
258
259 EXCEPTION : As a special exception, you may create a larger work
260 that contains this FAUST architecture section and distribute
261 that work under terms of your choice, so long as this FAUST
262 architecture section is not modified.
263 ************************************************************************/
264
265 #ifndef API_UI_H
266 #define API_UI_H
267
268 #include <sstream>
269 #include <string>
270 #include <vector>
271 #include <iostream>
272 #include <map>
273
274 /************************** BEGIN meta.h **************************/
275 /************************************************************************
276 FAUST Architecture File
277 Copyright (C) 2003-2017 GRAME, Centre National de Creation Musicale
278 ---------------------------------------------------------------------
279 This Architecture section is free software; you can redistribute it
280 and/or modify it under the terms of the GNU General Public License
281 as published by the Free Software Foundation; either version 3 of
282 the License, or (at your option) any later version.
283
284 This program is distributed in the hope that it will be useful,
285 but WITHOUT ANY WARRANTY; without even the implied warranty of
286 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
287 GNU General Public License for more details.
288
289 You should have received a copy of the GNU General Public License
290 along with this program; If not, see <http://www.gnu.org/licenses/>.
291
292 EXCEPTION : As a special exception, you may create a larger work
293 that contains this FAUST architecture section and distribute
294 that work under terms of your choice, so long as this FAUST
295 architecture section is not modified.
296 ************************************************************************/
297
298 #ifndef __meta__
299 #define __meta__
300
301 struct Meta
302 {
303 virtual ~Meta() {};
304 virtual void declare(const char* key, const char* value) = 0;
305
306 };
307
308 #endif
309 /************************** END meta.h **************************/
310 /************************** BEGIN UI.h **************************/
311 /************************************************************************
312 FAUST Architecture File
313 Copyright (C) 2003-2020 GRAME, Centre National de Creation Musicale
314 ---------------------------------------------------------------------
315 This Architecture section is free software; you can redistribute it
316 and/or modify it under the terms of the GNU General Public License
317 as published by the Free Software Foundation; either version 3 of
318 the License, or (at your option) any later version.
319
320 This program is distributed in the hope that it will be useful,
321 but WITHOUT ANY WARRANTY; without even the implied warranty of
322 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
323 GNU General Public License for more details.
324
325 You should have received a copy of the GNU General Public License
326 along with this program; If not, see <http://www.gnu.org/licenses/>.
327
328 EXCEPTION : As a special exception, you may create a larger work
329 that contains this FAUST architecture section and distribute
330 that work under terms of your choice, so long as this FAUST
331 architecture section is not modified.
332 ************************************************************************/
333
334 #ifndef __UI_H__
335 #define __UI_H__
336
337 #ifndef FAUSTFLOAT
338 #define FAUSTFLOAT float
339 #endif
340
341 /*******************************************************************************
342 * UI : Faust DSP User Interface
343 * User Interface as expected by the buildUserInterface() method of a DSP.
344 * This abstract class contains only the method that the Faust compiler can
345 * generate to describe a DSP user interface.
346 ******************************************************************************/
347
348 struct Soundfile;
349
350 template <typename REAL>
351 struct UIReal
352 {
353 UIReal() {}
354 virtual ~UIReal() {}
355
356 // -- widget's layouts
357
358 virtual void openTabBox(const char* label) = 0;
359 virtual void openHorizontalBox(const char* label) = 0;
360 virtual void openVerticalBox(const char* label) = 0;
361 virtual void closeBox() = 0;
362
363 // -- active widgets
364
365 virtual void addButton(const char* label, REAL* zone) = 0;
366 virtual void addCheckButton(const char* label, REAL* zone) = 0;
367 virtual void addVerticalSlider(const char* label, REAL* zone, REAL init, REAL min, REAL max, REAL step) = 0;
368 virtual void addHorizontalSlider(const char* label, REAL* zone, REAL init, REAL min, REAL max, REAL step) = 0;
369 virtual void addNumEntry(const char* label, REAL* zone, REAL init, REAL min, REAL max, REAL step) = 0;
370
371 // -- passive widgets
372
373 virtual void addHorizontalBargraph(const char* label, REAL* zone, REAL min, REAL max) = 0;
374 virtual void addVerticalBargraph(const char* label, REAL* zone, REAL min, REAL max) = 0;
375
376 // -- soundfiles
377
378 virtual void addSoundfile(const char* label, const char* filename, Soundfile** sf_zone) = 0;
379
380 // -- metadata declarations
381
382 virtual void declare(REAL* zone, const char* key, const char* val) {}
383 };
384
385 struct UI : public UIReal<FAUSTFLOAT>
386 {
387 UI() {}
388 virtual ~UI() {}
389 };
390
391 #endif
392 /************************** END UI.h **************************/
393 /************************** BEGIN PathBuilder.h **************************/
394 /************************************************************************
395 FAUST Architecture File
396 Copyright (C) 2003-2017 GRAME, Centre National de Creation Musicale
397 ---------------------------------------------------------------------
398 This Architecture section is free software; you can redistribute it
399 and/or modify it under the terms of the GNU General Public License
400 as published by the Free Software Foundation; either version 3 of
401 the License, or (at your option) any later version.
402
403 This program is distributed in the hope that it will be useful,
404 but WITHOUT ANY WARRANTY; without even the implied warranty of
405 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
406 GNU General Public License for more details.
407
408 You should have received a copy of the GNU General Public License
409 along with this program; If not, see <http://www.gnu.org/licenses/>.
410
411 EXCEPTION : As a special exception, you may create a larger work
412 that contains this FAUST architecture section and distribute
413 that work under terms of your choice, so long as this FAUST
414 architecture section is not modified.
415 ************************************************************************/
416
417 #ifndef FAUST_PATHBUILDER_H
418 #define FAUST_PATHBUILDER_H
419
420 #include <vector>
421 #include <string>
422 #include <algorithm>
423
424 /*******************************************************************************
425 * PathBuilder : Faust User Interface
426 * Helper class to build complete hierarchical path for UI items.
427 ******************************************************************************/
428
429 class PathBuilder
430 {
431
432 protected:
433
434 std::vector<std::string> fControlsLevel;
435
436 public:
437
438 PathBuilder() {}
439 virtual ~PathBuilder() {}
440
441 std::string buildPath(const std::string& label)
442 {
443 std::string res = "/";
444 for (size_t i = 0; i < fControlsLevel.size(); i++) {
445 res += fControlsLevel[i];
446 res += "/";
447 }
448 res += label;
449 std::replace(res.begin(), res.end(), ' ', '_');
450 return res;
451 }
452
453 std::string buildLabel(std::string label)
454 {
455 std::replace(label.begin(), label.end(), ' ', '_');
456 return label;
457 }
458
459 void pushLabel(const std::string& label) { fControlsLevel.push_back(label); }
460 void popLabel() { fControlsLevel.pop_back(); }
461
462 };
463
464 #endif // FAUST_PATHBUILDER_H
465 /************************** END PathBuilder.h **************************/
466 /************************** BEGIN ValueConverter.h **************************/
467 /************************************************************************
468 FAUST Architecture File
469 Copyright (C) 2003-2017 GRAME, Centre National de Creation Musicale
470 ---------------------------------------------------------------------
471 This Architecture section is free software; you can redistribute it
472 and/or modify it under the terms of the GNU General Public License
473 as published by the Free Software Foundation; either version 3 of
474 the License, or (at your option) any later version.
475
476 This program is distributed in the hope that it will be useful,
477 but WITHOUT ANY WARRANTY; without even the implied warranty of
478 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
479 GNU General Public License for more details.
480
481 You should have received a copy of the GNU General Public License
482 along with this program; If not, see <http://www.gnu.org/licenses/>.
483
484 EXCEPTION : As a special exception, you may create a larger work
485 that contains this FAUST architecture section and distribute
486 that work under terms of your choice, so long as this FAUST
487 architecture section is not modified.
488 ************************************************************************/
489
490 #ifndef __ValueConverter__
491 #define __ValueConverter__
492
493 /***************************************************************************************
494 ValueConverter.h
495 (GRAME, Copyright 2015-2019)
496
497 Set of conversion objects used to map user interface values (for example a gui slider
498 delivering values between 0 and 1) to faust values (for example a vslider between
499 20 and 20000) using a log scale.
500
501 -- Utilities
502
503 Range(lo,hi) : clip a value x between lo and hi
504 Interpolator(lo,hi,v1,v2) : Maps a value x between lo and hi to a value y between v1 and v2
505 Interpolator3pt(lo,mi,hi,v1,vm,v2) : Map values between lo mid hi to values between v1 vm v2
506
507 -- Value Converters
508
509 ValueConverter::ui2faust(x)
510 ValueConverter::faust2ui(x)
511
512 -- ValueConverters used for sliders depending of the scale
513
514 LinearValueConverter(umin, umax, fmin, fmax)
515 LinearValueConverter2(lo, mi, hi, v1, vm, v2) using 2 segments
516 LogValueConverter(umin, umax, fmin, fmax)
517 ExpValueConverter(umin, umax, fmin, fmax)
518
519 -- ValueConverters used for accelerometers based on 3 points
520
521 AccUpConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 0
522 AccDownConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 1
523 AccUpDownConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 2
524 AccDownUpConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 3
525
526 -- lists of ZoneControl are used to implement accelerometers metadata for each axes
527
528 ZoneControl(zone, valueConverter) : a zone with an accelerometer data converter
529
530 -- ZoneReader are used to implement screencolor metadata
531
532 ZoneReader(zone, valueConverter) : a zone with a data converter
533
534 ****************************************************************************************/
535
536 #include <float.h>
537 #include <algorithm> // std::max
538 #include <cmath>
539 #include <vector>
540 #include <assert.h>
541
542 //--------------------------------------------------------------------------------------
543 // Interpolator(lo,hi,v1,v2)
544 // Maps a value x between lo and hi to a value y between v1 and v2
545 // y = v1 + (x-lo)/(hi-lo)*(v2-v1)
546 // y = v1 + (x-lo) * coef with coef = (v2-v1)/(hi-lo)
547 // y = v1 + x*coef - lo*coef
548 // y = v1 - lo*coef + x*coef
549 // y = offset + x*coef with offset = v1 - lo*coef
550 //--------------------------------------------------------------------------------------
551 class Interpolator
552 {
553 private:
554
555 //--------------------------------------------------------------------------------------
556 // Range(lo,hi) clip a value between lo and hi
557 //--------------------------------------------------------------------------------------
558 struct Range
559 {
560 double fLo;
561 double fHi;
562
563 Range(double x, double y) : fLo(std::min<double>(x,y)), fHi(std::max<double>(x,y)) {}
564 double operator()(double x) { return (x<fLo) ? fLo : (x>fHi) ? fHi : x; }
565 };
566
567
568 Range fRange;
569 double fCoef;
570 double fOffset;
571
572 public:
573
574 Interpolator(double lo, double hi, double v1, double v2) : fRange(lo,hi)
575 {
576 if (hi != lo) {
577 // regular case
578 fCoef = (v2-v1)/(hi-lo);
579 fOffset = v1 - lo*fCoef;
580 } else {
581 // degenerate case, avoids division by zero
582 fCoef = 0;
583 fOffset = (v1+v2)/2;
584 }
585 }
586 double operator()(double v)
587 {
588 double x = fRange(v);
589 return fOffset + x*fCoef;
590 }
591
592 void getLowHigh(double& amin, double& amax)
593 {
594 amin = fRange.fLo;
595 amax = fRange.fHi;
596 }
597 };
598
599 //--------------------------------------------------------------------------------------
600 // Interpolator3pt(lo,mi,hi,v1,vm,v2)
601 // Map values between lo mid hi to values between v1 vm v2
602 //--------------------------------------------------------------------------------------
603 class Interpolator3pt
604 {
605
606 private:
607
608 Interpolator fSegment1;
609 Interpolator fSegment2;
610 double fMid;
611
612 public:
613
614 Interpolator3pt(double lo, double mi, double hi, double v1, double vm, double v2) :
615 fSegment1(lo, mi, v1, vm),
616 fSegment2(mi, hi, vm, v2),
617 fMid(mi) {}
618 double operator()(double x) { return (x < fMid) ? fSegment1(x) : fSegment2(x); }
619
620 void getMappingValues(double& amin, double& amid, double& amax)
621 {
622 fSegment1.getLowHigh(amin, amid);
623 fSegment2.getLowHigh(amid, amax);
624 }
625 };
626
627 //--------------------------------------------------------------------------------------
628 // Abstract ValueConverter class. Converts values between UI and Faust representations
629 //--------------------------------------------------------------------------------------
630 class ValueConverter
631 {
632
633 public:
634
635 virtual ~ValueConverter() {}
636 virtual double ui2faust(double x) = 0;
637 virtual double faust2ui(double x) = 0;
638 };
639
640 //--------------------------------------------------------------------------------------
641 // A converter than can be updated
642 //--------------------------------------------------------------------------------------
643
644 class UpdatableValueConverter : public ValueConverter {
645
646 protected:
647
648 bool fActive;
649
650 public:
651
652 UpdatableValueConverter():fActive(true)
653 {}
654 virtual ~UpdatableValueConverter()
655 {}
656
657 virtual void setMappingValues(double amin, double amid, double amax, double min, double init, double max) = 0;
658 virtual void getMappingValues(double& amin, double& amid, double& amax) = 0;
659
660 void setActive(bool on_off) { fActive = on_off; }
661 bool getActive() { return fActive; }
662
663 };
664
665
666 //--------------------------------------------------------------------------------------
667 // Linear conversion between ui and Faust values
668 //--------------------------------------------------------------------------------------
669 class LinearValueConverter : public ValueConverter
670 {
671
672 private:
673
674 Interpolator fUI2F;
675 Interpolator fF2UI;
676
677 public:
678
679 LinearValueConverter(double umin, double umax, double fmin, double fmax) :
680 fUI2F(umin,umax,fmin,fmax), fF2UI(fmin,fmax,umin,umax)
681 {}
682
683 LinearValueConverter() : fUI2F(0.,0.,0.,0.), fF2UI(0.,0.,0.,0.)
684 {}
685 virtual double ui2faust(double x) { return fUI2F(x); }
686 virtual double faust2ui(double x) { return fF2UI(x); }
687
688 };
689
690 //--------------------------------------------------------------------------------------
691 // Two segments linear conversion between ui and Faust values
692 //--------------------------------------------------------------------------------------
693 class LinearValueConverter2 : public UpdatableValueConverter
694 {
695
696 private:
697
698 Interpolator3pt fUI2F;
699 Interpolator3pt fF2UI;
700
701 public:
702
703 LinearValueConverter2(double amin, double amid, double amax, double min, double init, double max) :
704 fUI2F(amin, amid, amax, min, init, max), fF2UI(min, init, max, amin, amid, amax)
705 {}
706
707 LinearValueConverter2() : fUI2F(0.,0.,0.,0.,0.,0.), fF2UI(0.,0.,0.,0.,0.,0.)
708 {}
709
710 virtual double ui2faust(double x) { return fUI2F(x); }
711 virtual double faust2ui(double x) { return fF2UI(x); }
712
713 virtual void setMappingValues(double amin, double amid, double amax, double min, double init, double max)
714 {
715 fUI2F = Interpolator3pt(amin, amid, amax, min, init, max);
716 fF2UI = Interpolator3pt(min, init, max, amin, amid, amax);
717 }
718
719 virtual void getMappingValues(double& amin, double& amid, double& amax)
720 {
721 fUI2F.getMappingValues(amin, amid, amax);
722 }
723
724 };
725
726 //--------------------------------------------------------------------------------------
727 // Logarithmic conversion between ui and Faust values
728 //--------------------------------------------------------------------------------------
729 class LogValueConverter : public LinearValueConverter
730 {
731
732 public:
733
734 LogValueConverter(double umin, double umax, double fmin, double fmax) :
735 LinearValueConverter(umin, umax, std::log(std::max<double>(DBL_MIN, fmin)), std::log(std::max<double>(DBL_MIN, fmax)))
736 {}
737
738 virtual double ui2faust(double x) { return std::exp(LinearValueConverter::ui2faust(x)); }
739 virtual double faust2ui(double x) { return LinearValueConverter::faust2ui(std::log(std::max<double>(x, DBL_MIN))); }
740
741 };
742
743 //--------------------------------------------------------------------------------------
744 // Exponential conversion between ui and Faust values
745 //--------------------------------------------------------------------------------------
746 class ExpValueConverter : public LinearValueConverter
747 {
748
749 public:
750
751 ExpValueConverter(double umin, double umax, double fmin, double fmax) :
752 LinearValueConverter(umin, umax, std::min<double>(DBL_MAX, std::exp(fmin)), std::min<double>(DBL_MAX, std::exp(fmax)))
753 {}
754
755 virtual double ui2faust(double x) { return std::log(LinearValueConverter::ui2faust(x)); }
756 virtual double faust2ui(double x) { return LinearValueConverter::faust2ui(std::min<double>(DBL_MAX, std::exp(x))); }
757
758 };
759
760 //--------------------------------------------------------------------------------------
761 // Convert accelerometer or gyroscope values to Faust values
762 // Using an Up curve (curve 0)
763 //--------------------------------------------------------------------------------------
764 class AccUpConverter : public UpdatableValueConverter
765 {
766
767 private:
768
769 Interpolator3pt fA2F;
770 Interpolator3pt fF2A;
771
772 public:
773
774 AccUpConverter(double amin, double amid, double amax, double fmin, double fmid, double fmax) :
775 fA2F(amin,amid,amax,fmin,fmid,fmax),
776 fF2A(fmin,fmid,fmax,amin,amid,amax)
777 {}
778
779 virtual double ui2faust(double x) { return fA2F(x); }
780 virtual double faust2ui(double x) { return fF2A(x); }
781
782 virtual void setMappingValues(double amin, double amid, double amax, double fmin, double fmid, double fmax)
783 {
784 //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccUpConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax);
785 fA2F = Interpolator3pt(amin, amid, amax, fmin, fmid, fmax);
786 fF2A = Interpolator3pt(fmin, fmid, fmax, amin, amid, amax);
787 }
788
789 virtual void getMappingValues(double& amin, double& amid, double& amax)
790 {
791 fA2F.getMappingValues(amin, amid, amax);
792 }
793
794 };
795
796 //--------------------------------------------------------------------------------------
797 // Convert accelerometer or gyroscope values to Faust values
798 // Using a Down curve (curve 1)
799 //--------------------------------------------------------------------------------------
800 class AccDownConverter : public UpdatableValueConverter
801 {
802
803 private:
804
805 Interpolator3pt fA2F;
806 Interpolator3pt fF2A;
807
808 public:
809
810 AccDownConverter(double amin, double amid, double amax, double fmin, double fmid, double fmax) :
811 fA2F(amin,amid,amax,fmax,fmid,fmin),
812 fF2A(fmin,fmid,fmax,amax,amid,amin)
813 {}
814
815 virtual double ui2faust(double x) { return fA2F(x); }
816 virtual double faust2ui(double x) { return fF2A(x); }
817
818 virtual void setMappingValues(double amin, double amid, double amax, double fmin, double fmid, double fmax)
819 {
820 //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccDownConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax);
821 fA2F = Interpolator3pt(amin, amid, amax, fmax, fmid, fmin);
822 fF2A = Interpolator3pt(fmin, fmid, fmax, amax, amid, amin);
823 }
824
825 virtual void getMappingValues(double& amin, double& amid, double& amax)
826 {
827 fA2F.getMappingValues(amin, amid, amax);
828 }
829 };
830
831 //--------------------------------------------------------------------------------------
832 // Convert accelerometer or gyroscope values to Faust values
833 // Using an Up-Down curve (curve 2)
834 //--------------------------------------------------------------------------------------
835 class AccUpDownConverter : public UpdatableValueConverter
836 {
837
838 private:
839
840 Interpolator3pt fA2F;
841 Interpolator fF2A;
842
843 public:
844
845 AccUpDownConverter(double amin, double amid, double amax, double fmin, double fmid, double fmax) :
846 fA2F(amin,amid,amax,fmin,fmax,fmin),
847 fF2A(fmin,fmax,amin,amax) // Special, pseudo inverse of a non monotonic function
848 {}
849
850 virtual double ui2faust(double x) { return fA2F(x); }
851 virtual double faust2ui(double x) { return fF2A(x); }
852
853 virtual void setMappingValues(double amin, double amid, double amax, double fmin, double fmid, double fmax)
854 {
855 //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccUpDownConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax);
856 fA2F = Interpolator3pt(amin, amid, amax, fmin, fmax, fmin);
857 fF2A = Interpolator(fmin, fmax, amin, amax);
858 }
859
860 virtual void getMappingValues(double& amin, double& amid, double& amax)
861 {
862 fA2F.getMappingValues(amin, amid, amax);
863 }
864 };
865
866 //--------------------------------------------------------------------------------------
867 // Convert accelerometer or gyroscope values to Faust values
868 // Using a Down-Up curve (curve 3)
869 //--------------------------------------------------------------------------------------
870 class AccDownUpConverter : public UpdatableValueConverter
871 {
872
873 private:
874
875 Interpolator3pt fA2F;
876 Interpolator fF2A;
877
878 public:
879
880 AccDownUpConverter(double amin, double amid, double amax, double fmin, double fmid, double fmax) :
881 fA2F(amin,amid,amax,fmax,fmin,fmax),
882 fF2A(fmin,fmax,amin,amax) // Special, pseudo inverse of a non monotonic function
883 {}
884
885 virtual double ui2faust(double x) { return fA2F(x); }
886 virtual double faust2ui(double x) { return fF2A(x); }
887
888 virtual void setMappingValues(double amin, double amid, double amax, double fmin, double fmid, double fmax)
889 {
890 //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccDownUpConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax);
891 fA2F = Interpolator3pt(amin, amid, amax, fmax, fmin, fmax);
892 fF2A = Interpolator(fmin, fmax, amin, amax);
893 }
894
895 virtual void getMappingValues(double& amin, double& amid, double& amax)
896 {
897 fA2F.getMappingValues(amin, amid, amax);
898 }
899 };
900
901 //--------------------------------------------------------------------------------------
902 // Base class for ZoneControl
903 //--------------------------------------------------------------------------------------
904 class ZoneControl
905 {
906
907 protected:
908
909 FAUSTFLOAT* fZone;
910
911 public:
912
913 ZoneControl(FAUSTFLOAT* zone) : fZone(zone) {}
914 virtual ~ZoneControl() {}
915
916 virtual void update(double v) const {}
917
918 virtual void setMappingValues(int curve, double amin, double amid, double amax, double min, double init, double max) {}
919 virtual void getMappingValues(double& amin, double& amid, double& amax) {}
920
921 FAUSTFLOAT* getZone() { return fZone; }
922
923 virtual void setActive(bool on_off) {}
924 virtual bool getActive() { return false; }
925
926 virtual int getCurve() { return -1; }
927
928 };
929
930 //--------------------------------------------------------------------------------------
931 // Useful to implement accelerometers metadata as a list of ZoneControl for each axes
932 //--------------------------------------------------------------------------------------
933 class ConverterZoneControl : public ZoneControl
934 {
935
936 protected:
937
938 ValueConverter* fValueConverter;
939
940 public:
941
942 ConverterZoneControl(FAUSTFLOAT* zone, ValueConverter* converter) : ZoneControl(zone), fValueConverter(converter) {}
943 virtual ~ConverterZoneControl() { delete fValueConverter; } // Assuming fValueConverter is not kept elsewhere...
944
945 virtual void update(double v) const { *fZone = fValueConverter->ui2faust(v); }
946
947 ValueConverter* getConverter() { return fValueConverter; }
948
949 };
950
951 //--------------------------------------------------------------------------------------
952 // Association of a zone and a four value converter, each one for each possible curve.
953 // Useful to implement accelerometers metadata as a list of ZoneControl for each axes
954 //--------------------------------------------------------------------------------------
955 class CurveZoneControl : public ZoneControl
956 {
957
958 private:
959
960 std::vector<UpdatableValueConverter*> fValueConverters;
961 int fCurve;
962
963 public:
964
965 CurveZoneControl(FAUSTFLOAT* zone, int curve, double amin, double amid, double amax, double min, double init, double max) : ZoneControl(zone), fCurve(0)
966 {
967 assert(curve >= 0 && curve <= 3);
968 fValueConverters.push_back(new AccUpConverter(amin, amid, amax, min, init, max));
969 fValueConverters.push_back(new AccDownConverter(amin, amid, amax, min, init, max));
970 fValueConverters.push_back(new AccUpDownConverter(amin, amid, amax, min, init, max));
971 fValueConverters.push_back(new AccDownUpConverter(amin, amid, amax, min, init, max));
972 fCurve = curve;
973 }
974 virtual ~CurveZoneControl()
975 {
976 std::vector<UpdatableValueConverter*>::iterator it;
977 for (it = fValueConverters.begin(); it != fValueConverters.end(); it++) {
978 delete(*it);
979 }
980 }
981 void update(double v) const { if (fValueConverters[fCurve]->getActive()) *fZone = fValueConverters[fCurve]->ui2faust(v); }
982
983 void setMappingValues(int curve, double amin, double amid, double amax, double min, double init, double max)
984 {
985 fValueConverters[curve]->setMappingValues(amin, amid, amax, min, init, max);
986 fCurve = curve;
987 }
988
989 void getMappingValues(double& amin, double& amid, double& amax)
990 {
991 fValueConverters[fCurve]->getMappingValues(amin, amid, amax);
992 }
993
994 void setActive(bool on_off)
995 {
996 std::vector<UpdatableValueConverter*>::iterator it;
997 for (it = fValueConverters.begin(); it != fValueConverters.end(); it++) {
998 (*it)->setActive(on_off);
999 }
1000 }
1001
1002 int getCurve() { return fCurve; }
1003 };
1004
1005 class ZoneReader
1006 {
1007
1008 private:
1009
1010 FAUSTFLOAT* fZone;
1011 Interpolator fInterpolator;
1012
1013 public:
1014
1015 ZoneReader(FAUSTFLOAT* zone, double lo, double hi) : fZone(zone), fInterpolator(lo, hi, 0, 255) {}
1016
1017 virtual ~ZoneReader() {}
1018
1019 int getValue()
1020 {
1021 return (fZone != nullptr) ? int(fInterpolator(*fZone)) : 127;
1022 }
1023
1024 };
1025
1026 #endif
1027 /************************** END ValueConverter.h **************************/
1028
1029 class APIUI : public PathBuilder, public Meta, public UI
1030 {
1031 public:
1032
1033 enum ItemType { kButton = 0, kCheckButton, kVSlider, kHSlider, kNumEntry, kHBargraph, kVBargraph };
1034
1035 protected:
1036
1037 enum { kLin = 0, kLog = 1, kExp = 2 };
1038
1039 int fNumParameters;
1040 std::vector<std::string> fPaths;
1041 std::vector<std::string> fLabels;
1042 std::map<std::string, int> fPathMap;
1043 std::map<std::string, int> fLabelMap;
1044 std::vector<ValueConverter*> fConversion;
1045 std::vector<FAUSTFLOAT*> fZone;
1046 std::vector<FAUSTFLOAT> fInit;
1047 std::vector<FAUSTFLOAT> fMin;
1048 std::vector<FAUSTFLOAT> fMax;
1049 std::vector<FAUSTFLOAT> fStep;
1050 std::vector<ItemType> fItemType;
1051 std::vector<std::map<std::string, std::string> > fMetaData;
1052 std::vector<ZoneControl*> fAcc[3];
1053 std::vector<ZoneControl*> fGyr[3];
1054
1055 // Screen color control
1056 // "...[screencolor:red]..." etc.
1057 bool fHasScreenControl; // true if control screen color metadata
1058 ZoneReader* fRedReader;
1059 ZoneReader* fGreenReader;
1060 ZoneReader* fBlueReader;
1061
1062 // Current values controlled by metadata
1063 std::string fCurrentUnit;
1064 int fCurrentScale;
1065 std::string fCurrentAcc;
1066 std::string fCurrentGyr;
1067 std::string fCurrentColor;
1068 std::string fCurrentTooltip;
1069 std::map<std::string, std::string> fCurrentMetadata;
1070
1071 // Add a generic parameter
1072 virtual void addParameter(const char* label,
1073 FAUSTFLOAT* zone,
1074 FAUSTFLOAT init,
1075 FAUSTFLOAT min,
1076 FAUSTFLOAT max,
1077 FAUSTFLOAT step,
1078 ItemType type)
1079 {
1080 std::string path = buildPath(label);
1081 fPathMap[path] = fLabelMap[label] = fNumParameters++;
1082 fPaths.push_back(path);
1083 fLabels.push_back(label);
1084 fZone.push_back(zone);
1085 fInit.push_back(init);
1086 fMin.push_back(min);
1087 fMax.push_back(max);
1088 fStep.push_back(step);
1089 fItemType.push_back(type);
1090
1091 // handle scale metadata
1092 switch (fCurrentScale) {
1093 case kLin:
1094 fConversion.push_back(new LinearValueConverter(0, 1, min, max));
1095 break;
1096 case kLog:
1097 fConversion.push_back(new LogValueConverter(0, 1, min, max));
1098 break;
1099 case kExp: fConversion.push_back(new ExpValueConverter(0, 1, min, max));
1100 break;
1101 }
1102 fCurrentScale = kLin;
1103
1104 if (fCurrentAcc.size() > 0 && fCurrentGyr.size() > 0) {
1105 std::cerr << "warning : 'acc' and 'gyr' metadata used for the same " << label << " parameter !!\n";
1106 }
1107
1108 // handle acc metadata "...[acc : <axe> <curve> <amin> <amid> <amax>]..."
1109 if (fCurrentAcc.size() > 0) {
1110 std::istringstream iss(fCurrentAcc);
1111 int axe, curve;
1112 double amin, amid, amax;
1113 iss >> axe >> curve >> amin >> amid >> amax;
1114
1115 if ((0 <= axe) && (axe < 3) &&
1116 (0 <= curve) && (curve < 4) &&
1117 (amin < amax) && (amin <= amid) && (amid <= amax))
1118 {
1119 fAcc[axe].push_back(new CurveZoneControl(zone, curve, amin, amid, amax, min, init, max));
1120 } else {
1121 std::cerr << "incorrect acc metadata : " << fCurrentAcc << std::endl;
1122 }
1123 fCurrentAcc = "";
1124 }
1125
1126 // handle gyr metadata "...[gyr : <axe> <curve> <amin> <amid> <amax>]..."
1127 if (fCurrentGyr.size() > 0) {
1128 std::istringstream iss(fCurrentGyr);
1129 int axe, curve;
1130 double amin, amid, amax;
1131 iss >> axe >> curve >> amin >> amid >> amax;
1132
1133 if ((0 <= axe) && (axe < 3) &&
1134 (0 <= curve) && (curve < 4) &&
1135 (amin < amax) && (amin <= amid) && (amid <= amax))
1136 {
1137 fGyr[axe].push_back(new CurveZoneControl(zone, curve, amin, amid, amax, min, init, max));
1138 } else {
1139 std::cerr << "incorrect gyr metadata : " << fCurrentGyr << std::endl;
1140 }
1141 fCurrentGyr = "";
1142 }
1143
1144 // handle screencolor metadata "...[screencolor:red|green|blue|white]..."
1145 if (fCurrentColor.size() > 0) {
1146 if ((fCurrentColor == "red") && (fRedReader == 0)) {
1147 fRedReader = new ZoneReader(zone, min, max);
1148 fHasScreenControl = true;
1149 } else if ((fCurrentColor == "green") && (fGreenReader == 0)) {
1150 fGreenReader = new ZoneReader(zone, min, max);
1151 fHasScreenControl = true;
1152 } else if ((fCurrentColor == "blue") && (fBlueReader == 0)) {
1153 fBlueReader = new ZoneReader(zone, min, max);
1154 fHasScreenControl = true;
1155 } else if ((fCurrentColor == "white") && (fRedReader == 0) && (fGreenReader == 0) && (fBlueReader == 0)) {
1156 fRedReader = new ZoneReader(zone, min, max);
1157 fGreenReader = new ZoneReader(zone, min, max);
1158 fBlueReader = new ZoneReader(zone, min, max);
1159 fHasScreenControl = true;
1160 } else {
1161 std::cerr << "incorrect screencolor metadata : " << fCurrentColor << std::endl;
1162 }
1163 }
1164 fCurrentColor = "";
1165
1166 fMetaData.push_back(fCurrentMetadata);
1167 fCurrentMetadata.clear();
1168 }
1169
1170 int getZoneIndex(std::vector<ZoneControl*>* table, int p, int val)
1171 {
1172 FAUSTFLOAT* zone = fZone[p];
1173 for (size_t i = 0; i < table[val].size(); i++) {
1174 if (zone == table[val][i]->getZone()) return int(i);
1175 }
1176 return -1;
1177 }
1178
1179 void setConverter(std::vector<ZoneControl*>* table, int p, int val, int curve, double amin, double amid, double amax)
1180 {
1181 int id1 = getZoneIndex(table, p, 0);
1182 int id2 = getZoneIndex(table, p, 1);
1183 int id3 = getZoneIndex(table, p, 2);
1184
1185 // Deactivates everywhere..
1186 if (id1 != -1) table[0][id1]->setActive(false);
1187 if (id2 != -1) table[1][id2]->setActive(false);
1188 if (id3 != -1) table[2][id3]->setActive(false);
1189
1190 if (val == -1) { // Means: no more mapping...
1191 // So stay all deactivated...
1192 } else {
1193 int id4 = getZoneIndex(table, p, val);
1194 if (id4 != -1) {
1195 // Reactivate the one we edit...
1196 table[val][id4]->setMappingValues(curve, amin, amid, amax, fMin[p], fInit[p], fMax[p]);
1197 table[val][id4]->setActive(true);
1198 } else {
1199 // Allocate a new CurveZoneControl which is 'active' by default
1200 FAUSTFLOAT* zone = fZone[p];
1201 table[val].push_back(new CurveZoneControl(zone, curve, amin, amid, amax, fMin[p], fInit[p], fMax[p]));
1202 }
1203 }
1204 }
1205
1206 void getConverter(std::vector<ZoneControl*>* table, int p, int& val, int& curve, double& amin, double& amid, double& amax)
1207 {
1208 int id1 = getZoneIndex(table, p, 0);
1209 int id2 = getZoneIndex(table, p, 1);
1210 int id3 = getZoneIndex(table, p, 2);
1211
1212 if (id1 != -1) {
1213 val = 0;
1214 curve = table[val][id1]->getCurve();
1215 table[val][id1]->getMappingValues(amin, amid, amax);
1216 } else if (id2 != -1) {
1217 val = 1;
1218 curve = table[val][id2]->getCurve();
1219 table[val][id2]->getMappingValues(amin, amid, amax);
1220 } else if (id3 != -1) {
1221 val = 2;
1222 curve = table[val][id3]->getCurve();
1223 table[val][id3]->getMappingValues(amin, amid, amax);
1224 } else {
1225 val = -1; // No mapping
1226 curve = 0;
1227 amin = -100.;
1228 amid = 0.;
1229 amax = 100.;
1230 }
1231 }
1232
1233 public:
1234
1235 enum Type { kAcc = 0, kGyr = 1, kNoType };
1236
1237 APIUI() : fNumParameters(0), fHasScreenControl(false), fRedReader(0), fGreenReader(0), fBlueReader(0), fCurrentScale(kLin)
1238 {}
1239
1240 virtual ~APIUI()
1241 {
1242 for (auto& it : fConversion) delete it;
1243 for (int i = 0; i < 3; i++) {
1244 for (auto& it : fAcc[i]) delete it;
1245 for (auto& it : fGyr[i]) delete it;
1246 }
1247 delete fRedReader;
1248 delete fGreenReader;
1249 delete fBlueReader;
1250 }
1251
1252 // -- widget's layouts
1253
1254 virtual void openTabBox(const char* label) { pushLabel(label); }
1255 virtual void openHorizontalBox(const char* label) { pushLabel(label); }
1256 virtual void openVerticalBox(const char* label) { pushLabel(label); }
1257 virtual void closeBox() { popLabel(); }
1258
1259 // -- active widgets
1260
1261 virtual void addButton(const char* label, FAUSTFLOAT* zone)
1262 {
1263 addParameter(label, zone, 0, 0, 1, 1, kButton);
1264 }
1265
1266 virtual void addCheckButton(const char* label, FAUSTFLOAT* zone)
1267 {
1268 addParameter(label, zone, 0, 0, 1, 1, kCheckButton);
1269 }
1270
1271 virtual void addVerticalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step)
1272 {
1273 addParameter(label, zone, init, min, max, step, kVSlider);
1274 }
1275
1276 virtual void addHorizontalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step)
1277 {
1278 addParameter(label, zone, init, min, max, step, kHSlider);
1279 }
1280
1281 virtual void addNumEntry(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step)
1282 {
1283 addParameter(label, zone, init, min, max, step, kNumEntry);
1284 }
1285
1286 // -- passive widgets
1287
1288 virtual void addHorizontalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max)
1289 {
1290 addParameter(label, zone, min, min, max, (max-min)/1000.0, kHBargraph);
1291 }
1292
1293 virtual void addVerticalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max)
1294 {
1295 addParameter(label, zone, min, min, max, (max-min)/1000.0, kVBargraph);
1296 }
1297
1298 // -- soundfiles
1299
1300 virtual void addSoundfile(const char* label, const char* filename, Soundfile** sf_zone) {}
1301
1302 // -- metadata declarations
1303
1304 virtual void declare(FAUSTFLOAT* zone, const char* key, const char* val)
1305 {
1306 // Keep metadata
1307 fCurrentMetadata[key] = val;
1308
1309 if (strcmp(key, "scale") == 0) {
1310 if (strcmp(val, "log") == 0) {
1311 fCurrentScale = kLog;
1312 } else if (strcmp(val, "exp") == 0) {
1313 fCurrentScale = kExp;
1314 } else {
1315 fCurrentScale = kLin;
1316 }
1317 } else if (strcmp(key, "unit") == 0) {
1318 fCurrentUnit = val;
1319 } else if (strcmp(key, "acc") == 0) {
1320 fCurrentAcc = val;
1321 } else if (strcmp(key, "gyr") == 0) {
1322 fCurrentGyr = val;
1323 } else if (strcmp(key, "screencolor") == 0) {
1324 fCurrentColor = val; // val = "red", "green", "blue" or "white"
1325 } else if (strcmp(key, "tooltip") == 0) {
1326 fCurrentTooltip = val;
1327 }
1328 }
1329
1330 virtual void declare(const char* key, const char* val)
1331 {}
1332
1333 //-------------------------------------------------------------------------------
1334 // Simple API part
1335 //-------------------------------------------------------------------------------
1336 int getParamsCount() { return fNumParameters; }
1337 int getParamIndex(const char* path)
1338 {
1339 if (fPathMap.find(path) != fPathMap.end()) {
1340 return fPathMap[path];
1341 } else if (fLabelMap.find(path) != fLabelMap.end()) {
1342 return fLabelMap[path];
1343 } else {
1344 return -1;
1345 }
1346 }
1347 const char* getParamAddress(int p) { return fPaths[p].c_str(); }
1348 const char* getParamLabel(int p) { return fLabels[p].c_str(); }
1349 std::map<const char*, const char*> getMetadata(int p)
1350 {
1351 std::map<const char*, const char*> res;
1352 std::map<std::string, std::string> metadata = fMetaData[p];
1353 for (auto it : metadata) {
1354 res[it.first.c_str()] = it.second.c_str();
1355 }
1356 return res;
1357 }
1358
1359 const char* getMetadata(int p, const char* key)
1360 {
1361 return (fMetaData[p].find(key) != fMetaData[p].end()) ? fMetaData[p][key].c_str() : "";
1362 }
1363 FAUSTFLOAT getParamMin(int p) { return fMin[p]; }
1364 FAUSTFLOAT getParamMax(int p) { return fMax[p]; }
1365 FAUSTFLOAT getParamStep(int p) { return fStep[p]; }
1366 FAUSTFLOAT getParamInit(int p) { return fInit[p]; }
1367
1368 FAUSTFLOAT* getParamZone(int p) { return fZone[p]; }
1369 FAUSTFLOAT getParamValue(int p) { return *fZone[p]; }
1370 void setParamValue(int p, FAUSTFLOAT v) { *fZone[p] = v; }
1371
1372 double getParamRatio(int p) { return fConversion[p]->faust2ui(*fZone[p]); }
1373 void setParamRatio(int p, double r) { *fZone[p] = fConversion[p]->ui2faust(r); }
1374
1375 double value2ratio(int p, double r) { return fConversion[p]->faust2ui(r); }
1376 double ratio2value(int p, double r) { return fConversion[p]->ui2faust(r); }
1377
1378 /**
1379 * Return the control type (kAcc, kGyr, or -1) for a given parameter
1380 *
1381 * @param p - the UI parameter index
1382 *
1383 * @return the type
1384 */
1385 Type getParamType(int p)
1386 {
1387 if (p >= 0) {
1388 if (getZoneIndex(fAcc, p, 0) != -1
1389 || getZoneIndex(fAcc, p, 1) != -1
1390 || getZoneIndex(fAcc, p, 2) != -1) {
1391 return kAcc;
1392 } else if (getZoneIndex(fGyr, p, 0) != -1
1393 || getZoneIndex(fGyr, p, 1) != -1
1394 || getZoneIndex(fGyr, p, 2) != -1) {
1395 return kGyr;
1396 }
1397 }
1398 return kNoType;
1399 }
1400
1401 /**
1402 * Return the Item type (kButton = 0, kCheckButton, kVSlider, kHSlider, kNumEntry, kHBargraph, kVBargraph) for a given parameter
1403 *
1404 * @param p - the UI parameter index
1405 *
1406 * @return the Item type
1407 */
1408 ItemType getParamItemType(int p)
1409 {
1410 return fItemType[p];
1411 }
1412
1413 /**
1414 * Set a new value coming from an accelerometer, propagate it to all relevant FAUSTFLOAT* zones.
1415 *
1416 * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer
1417 * @param value - the new value
1418 *
1419 */
1420 void propagateAcc(int acc, double value)
1421 {
1422 for (size_t i = 0; i < fAcc[acc].size(); i++) {
1423 fAcc[acc][i]->update(value);
1424 }
1425 }
1426
1427 /**
1428 * Used to edit accelerometer curves and mapping. Set curve and related mapping for a given UI parameter.
1429 *
1430 * @param p - the UI parameter index
1431 * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer (-1 means "no mapping")
1432 * @param curve - between 0 and 3
1433 * @param amin - mapping 'min' point
1434 * @param amid - mapping 'middle' point
1435 * @param amax - mapping 'max' point
1436 *
1437 */
1438 void setAccConverter(int p, int acc, int curve, double amin, double amid, double amax)
1439 {
1440 setConverter(fAcc, p, acc, curve, amin, amid, amax);
1441 }
1442
1443 /**
1444 * Used to edit gyroscope curves and mapping. Set curve and related mapping for a given UI parameter.
1445 *
1446 * @param p - the UI parameter index
1447 * @param acc - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope (-1 means "no mapping")
1448 * @param curve - between 0 and 3
1449 * @param amin - mapping 'min' point
1450 * @param amid - mapping 'middle' point
1451 * @param amax - mapping 'max' point
1452 *
1453 */
1454 void setGyrConverter(int p, int gyr, int curve, double amin, double amid, double amax)
1455 {
1456 setConverter(fGyr, p, gyr, curve, amin, amid, amax);
1457 }
1458
1459 /**
1460 * Used to edit accelerometer curves and mapping. Get curve and related mapping for a given UI parameter.
1461 *
1462 * @param p - the UI parameter index
1463 * @param acc - the acc value to be retrieved (-1 means "no mapping")
1464 * @param curve - the curve value to be retrieved
1465 * @param amin - the amin value to be retrieved
1466 * @param amid - the amid value to be retrieved
1467 * @param amax - the amax value to be retrieved
1468 *
1469 */
1470 void getAccConverter(int p, int& acc, int& curve, double& amin, double& amid, double& amax)
1471 {
1472 getConverter(fAcc, p, acc, curve, amin, amid, amax);
1473 }
1474
1475 /**
1476 * Used to edit gyroscope curves and mapping. Get curve and related mapping for a given UI parameter.
1477 *
1478 * @param p - the UI parameter index
1479 * @param gyr - the gyr value to be retrieved (-1 means "no mapping")
1480 * @param curve - the curve value to be retrieved
1481 * @param amin - the amin value to be retrieved
1482 * @param amid - the amid value to be retrieved
1483 * @param amax - the amax value to be retrieved
1484 *
1485 */
1486 void getGyrConverter(int p, int& gyr, int& curve, double& amin, double& amid, double& amax)
1487 {
1488 getConverter(fGyr, p, gyr, curve, amin, amid, amax);
1489 }
1490
1491 /**
1492 * Set a new value coming from an gyroscope, propagate it to all relevant FAUSTFLOAT* zones.
1493 *
1494 * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope
1495 * @param value - the new value
1496 *
1497 */
1498 void propagateGyr(int gyr, double value)
1499 {
1500 for (size_t i = 0; i < fGyr[gyr].size(); i++) {
1501 fGyr[gyr][i]->update(value);
1502 }
1503 }
1504
1505 /**
1506 * Get the number of FAUSTFLOAT* zones controlled with the accelerometer
1507 *
1508 * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer
1509 * @return the number of zones
1510 *
1511 */
1512 int getAccCount(int acc)
1513 {
1514 return (acc >= 0 && acc < 3) ? int(fAcc[acc].size()) : 0;
1515 }
1516
1517 /**
1518 * Get the number of FAUSTFLOAT* zones controlled with the gyroscope
1519 *
1520 * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope
1521 * @param the number of zones
1522 *
1523 */
1524 int getGyrCount(int gyr)
1525 {
1526 return (gyr >= 0 && gyr < 3) ? int(fGyr[gyr].size()) : 0;
1527 }
1528
1529 // getScreenColor() : -1 means no screen color control (no screencolor metadata found)
1530 // otherwise return 0x00RRGGBB a ready to use color
1531 int getScreenColor()
1532 {
1533 if (fHasScreenControl) {
1534 int r = (fRedReader) ? fRedReader->getValue() : 0;
1535 int g = (fGreenReader) ? fGreenReader->getValue() : 0;
1536 int b = (fBlueReader) ? fBlueReader->getValue() : 0;
1537 return (r<<16) | (g<<8) | b;
1538 } else {
1539 return -1;
1540 }
1541 }
1542
1543 };
1544
1545 #endif
1546 /************************** END APIUI.h **************************/
1547
1548 // NOTE: "faust -scn name" changes the last line above to
1549 // #include <faust/name/name.h>
1550
1551 //----------------------------------------------------------------------------
1552 // FAUST Generated Code
1553 //----------------------------------------------------------------------------
1554
1555
1556 #ifndef FAUSTFLOAT
1557 #define FAUSTFLOAT float
1558 #endif
1559
1560 #include <algorithm>
1561 #include <cmath>
1562 #include <math.h>
1563
1564
1565 #ifndef FAUSTCLASS
1566 #define FAUSTCLASS freeverbdsp
1567 #endif
1568
1569 #ifdef __APPLE__
1570 #define exp10f __exp10f
1571 #define exp10 __exp10
1572 #endif
1573
1574 class freeverbdsp : public dsp {
1575
1576 private:
1577
1578 int fSampleRate;
1579 float fConst0;
1580 float fConst1;
1581 FAUSTFLOAT fVslider0;
1582 float fConst2;
1583 FAUSTFLOAT fVslider1;
1584 float fRec9[2];
1585 FAUSTFLOAT fVslider2;
1586 int IOTA;
1587 float fVec0[8192];
1588 int iConst3;
1589 float fRec8[2];
1590 float fRec11[2];
1591 float fVec1[8192];
1592 int iConst4;
1593 float fRec10[2];
1594 float fRec13[2];
1595 float fVec2[8192];
1596 int iConst5;
1597 float fRec12[2];
1598 float fRec15[2];
1599 float fVec3[8192];
1600 int iConst6;
1601 float fRec14[2];
1602 float fRec17[2];
1603 float fVec4[8192];
1604 int iConst7;
1605 float fRec16[2];
1606 float fRec19[2];
1607 float fVec5[8192];
1608 int iConst8;
1609 float fRec18[2];
1610 float fRec21[2];
1611 float fVec6[8192];
1612 int iConst9;
1613 float fRec20[2];
1614 float fRec23[2];
1615 float fVec7[8192];
1616 int iConst10;
1617 float fRec22[2];
1618 float fVec8[2048];
1619 int iConst11;
1620 int iConst12;
1621 float fRec6[2];
1622 float fVec9[2048];
1623 int iConst13;
1624 int iConst14;
1625 float fRec4[2];
1626 float fVec10[2048];
1627 int iConst15;
1628 int iConst16;
1629 float fRec2[2];
1630 float fVec11[1024];
1631 int iConst17;
1632 int iConst18;
1633 float fRec0[2];
1634 float fRec33[2];
1635 float fVec12[8192];
1636 float fConst19;
1637 FAUSTFLOAT fVslider3;
1638 float fRec32[2];
1639 float fRec35[2];
1640 float fVec13[8192];
1641 float fRec34[2];
1642 float fRec37[2];
1643 float fVec14[8192];
1644 float fRec36[2];
1645 float fRec39[2];
1646 float fVec15[8192];
1647 float fRec38[2];
1648 float fRec41[2];
1649 float fVec16[8192];
1650 float fRec40[2];
1651 float fRec43[2];
1652 float fVec17[8192];
1653 float fRec42[2];
1654 float fRec45[2];
1655 float fVec18[8192];
1656 float fRec44[2];
1657 float fRec47[2];
1658 float fVec19[8192];
1659 float fRec46[2];
1660 float fVec20[2048];
1661 float fRec30[2];
1662 float fVec21[2048];
1663 float fRec28[2];
1664 float fVec22[2048];
1665 float fRec26[2];
1666 float fVec23[2048];
1667 float fRec24[2];
1668
1669 public:
1670
1671 void metadata(Meta* m) {
1672 m->declare("author", "Romain Michon");
1673 m->declare("delays.lib/name", "Faust Delay Library");
1674 m->declare("delays.lib/version", "0.1");
1675 m->declare("description", "Freeverb implementation in Faust, from the Faust Library's dm.freeverb_demo in demos.lib");
1676 m->declare("filename", "freeverbdsp.dsp");
1677 m->declare("filters.lib/allpass_comb:author", "Julius O. Smith III");
1678 m->declare("filters.lib/allpass_comb:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
1679 m->declare("filters.lib/allpass_comb:license", "MIT-style STK-4.3 license");
1680 m->declare("filters.lib/lowpass0_highpass1", "MIT-style STK-4.3 license");
1681 m->declare("filters.lib/name", "Faust Filters Library");
1682 m->declare("license", "LGPL");
1683 m->declare("maths.lib/author", "GRAME");
1684 m->declare("maths.lib/copyright", "GRAME");
1685 m->declare("maths.lib/license", "LGPL with exception");
1686 m->declare("maths.lib/name", "Faust Math Library");
1687 m->declare("maths.lib/version", "2.3");
1688 m->declare("name", "freeverb");
1689 m->declare("platform.lib/name", "Generic Platform Library");
1690 m->declare("platform.lib/version", "0.1");
1691 m->declare("reverbs.lib/name", "Faust Reverb Library");
1692 m->declare("reverbs.lib/version", "0.0");
1693 m->declare("version", "0.0");
1694 }
1695
1696 virtual int getNumInputs() {
1697 return 2;
1698 }
1699 virtual int getNumOutputs() {
1700 return 2;
1701 }
1702 virtual int getInputRate(int channel) {
1703 int rate;
1704 switch ((channel)) {
1705 case 0: {
1706 rate = 1;
1707 break;
1708 }
1709 case 1: {
1710 rate = 1;
1711 break;
1712 }
1713 default: {
1714 rate = -1;
1715 break;
1716 }
1717 }
1718 return rate;
1719 }
1720 virtual int getOutputRate(int channel) {
1721 int rate;
1722 switch ((channel)) {
1723 case 0: {
1724 rate = 1;
1725 break;
1726 }
1727 case 1: {
1728 rate = 1;
1729 break;
1730 }
1731 default: {
1732 rate = -1;
1733 break;
1734 }
1735 }
1736 return rate;
1737 }
1738
1739 static void classInit(int sample_rate) {
1740 }
1741
1742 virtual void instanceConstants(int sample_rate) {
1743 fSampleRate = sample_rate;
1744 fConst0 = std::min<float>(192000.0f, std::max<float>(1.0f, float(fSampleRate)));
1745 fConst1 = (12348.0f / fConst0);
1746 fConst2 = (17640.0f / fConst0);
1747 iConst3 = int((0.0253061224f * fConst0));
1748 iConst4 = int((0.0269387756f * fConst0));
1749 iConst5 = int((0.0289569162f * fConst0));
1750 iConst6 = int((0.0307482984f * fConst0));
1751 iConst7 = int((0.0322448984f * fConst0));
1752 iConst8 = int((0.033809524f * fConst0));
1753 iConst9 = int((0.0353061222f * fConst0));
1754 iConst10 = int((0.0366666652f * fConst0));
1755 iConst11 = int((0.0126077095f * fConst0));
1756 iConst12 = std::min<int>(1024, std::max<int>(0, (iConst11 + -1)));
1757 iConst13 = int((0.00999999978f * fConst0));
1758 iConst14 = std::min<int>(1024, std::max<int>(0, (iConst13 + -1)));
1759 iConst15 = int((0.00773242628f * fConst0));
1760 iConst16 = std::min<int>(1024, std::max<int>(0, (iConst15 + -1)));
1761 iConst17 = int((0.00510204071f * fConst0));
1762 iConst18 = std::min<int>(1024, std::max<int>(0, (iConst17 + -1)));
1763 fConst19 = (0.00104308384f * fConst0);
1764 }
1765
1766 virtual void instanceResetUserInterface() {
1767 fVslider0 = FAUSTFLOAT(0.10000000000000001f);
1768 fVslider1 = FAUSTFLOAT(0.5f);
1769 fVslider2 = FAUSTFLOAT(0.10000000000000001f);
1770 fVslider3 = FAUSTFLOAT(0.5f);
1771 }
1772
1773 virtual void instanceClear() {
1774 for (int l0 = 0; (l0 < 2); l0 = (l0 + 1)) {
1775 fRec9[l0] = 0.0f;
1776 }
1777 IOTA = 0;
1778 for (int l1 = 0; (l1 < 8192); l1 = (l1 + 1)) {
1779 fVec0[l1] = 0.0f;
1780 }
1781 for (int l2 = 0; (l2 < 2); l2 = (l2 + 1)) {
1782 fRec8[l2] = 0.0f;
1783 }
1784 for (int l3 = 0; (l3 < 2); l3 = (l3 + 1)) {
1785 fRec11[l3] = 0.0f;
1786 }
1787 for (int l4 = 0; (l4 < 8192); l4 = (l4 + 1)) {
1788 fVec1[l4] = 0.0f;
1789 }
1790 for (int l5 = 0; (l5 < 2); l5 = (l5 + 1)) {
1791 fRec10[l5] = 0.0f;
1792 }
1793 for (int l6 = 0; (l6 < 2); l6 = (l6 + 1)) {
1794 fRec13[l6] = 0.0f;
1795 }
1796 for (int l7 = 0; (l7 < 8192); l7 = (l7 + 1)) {
1797 fVec2[l7] = 0.0f;
1798 }
1799 for (int l8 = 0; (l8 < 2); l8 = (l8 + 1)) {
1800 fRec12[l8] = 0.0f;
1801 }
1802 for (int l9 = 0; (l9 < 2); l9 = (l9 + 1)) {
1803 fRec15[l9] = 0.0f;
1804 }
1805 for (int l10 = 0; (l10 < 8192); l10 = (l10 + 1)) {
1806 fVec3[l10] = 0.0f;
1807 }
1808 for (int l11 = 0; (l11 < 2); l11 = (l11 + 1)) {
1809 fRec14[l11] = 0.0f;
1810 }
1811 for (int l12 = 0; (l12 < 2); l12 = (l12 + 1)) {
1812 fRec17[l12] = 0.0f;
1813 }
1814 for (int l13 = 0; (l13 < 8192); l13 = (l13 + 1)) {
1815 fVec4[l13] = 0.0f;
1816 }
1817 for (int l14 = 0; (l14 < 2); l14 = (l14 + 1)) {
1818 fRec16[l14] = 0.0f;
1819 }
1820 for (int l15 = 0; (l15 < 2); l15 = (l15 + 1)) {
1821 fRec19[l15] = 0.0f;
1822 }
1823 for (int l16 = 0; (l16 < 8192); l16 = (l16 + 1)) {
1824 fVec5[l16] = 0.0f;
1825 }
1826 for (int l17 = 0; (l17 < 2); l17 = (l17 + 1)) {
1827 fRec18[l17] = 0.0f;
1828 }
1829 for (int l18 = 0; (l18 < 2); l18 = (l18 + 1)) {
1830 fRec21[l18] = 0.0f;
1831 }
1832 for (int l19 = 0; (l19 < 8192); l19 = (l19 + 1)) {
1833 fVec6[l19] = 0.0f;
1834 }
1835 for (int l20 = 0; (l20 < 2); l20 = (l20 + 1)) {
1836 fRec20[l20] = 0.0f;
1837 }
1838 for (int l21 = 0; (l21 < 2); l21 = (l21 + 1)) {
1839 fRec23[l21] = 0.0f;
1840 }
1841 for (int l22 = 0; (l22 < 8192); l22 = (l22 + 1)) {
1842 fVec7[l22] = 0.0f;
1843 }
1844 for (int l23 = 0; (l23 < 2); l23 = (l23 + 1)) {
1845 fRec22[l23] = 0.0f;
1846 }
1847 for (int l24 = 0; (l24 < 2048); l24 = (l24 + 1)) {
1848 fVec8[l24] = 0.0f;
1849 }
1850 for (int l25 = 0; (l25 < 2); l25 = (l25 + 1)) {
1851 fRec6[l25] = 0.0f;
1852 }
1853 for (int l26 = 0; (l26 < 2048); l26 = (l26 + 1)) {
1854 fVec9[l26] = 0.0f;
1855 }
1856 for (int l27 = 0; (l27 < 2); l27 = (l27 + 1)) {
1857 fRec4[l27] = 0.0f;
1858 }
1859 for (int l28 = 0; (l28 < 2048); l28 = (l28 + 1)) {
1860 fVec10[l28] = 0.0f;
1861 }
1862 for (int l29 = 0; (l29 < 2); l29 = (l29 + 1)) {
1863 fRec2[l29] = 0.0f;
1864 }
1865 for (int l30 = 0; (l30 < 1024); l30 = (l30 + 1)) {
1866 fVec11[l30] = 0.0f;
1867 }
1868 for (int l31 = 0; (l31 < 2); l31 = (l31 + 1)) {
1869 fRec0[l31] = 0.0f;
1870 }
1871 for (int l32 = 0; (l32 < 2); l32 = (l32 + 1)) {
1872 fRec33[l32] = 0.0f;
1873 }
1874 for (int l33 = 0; (l33 < 8192); l33 = (l33 + 1)) {
1875 fVec12[l33] = 0.0f;
1876 }
1877 for (int l34 = 0; (l34 < 2); l34 = (l34 + 1)) {
1878 fRec32[l34] = 0.0f;
1879 }
1880 for (int l35 = 0; (l35 < 2); l35 = (l35 + 1)) {
1881 fRec35[l35] = 0.0f;
1882 }
1883 for (int l36 = 0; (l36 < 8192); l36 = (l36 + 1)) {
1884 fVec13[l36] = 0.0f;
1885 }
1886 for (int l37 = 0; (l37 < 2); l37 = (l37 + 1)) {
1887 fRec34[l37] = 0.0f;
1888 }
1889 for (int l38 = 0; (l38 < 2); l38 = (l38 + 1)) {
1890 fRec37[l38] = 0.0f;
1891 }
1892 for (int l39 = 0; (l39 < 8192); l39 = (l39 + 1)) {
1893 fVec14[l39] = 0.0f;
1894 }
1895 for (int l40 = 0; (l40 < 2); l40 = (l40 + 1)) {
1896 fRec36[l40] = 0.0f;
1897 }
1898 for (int l41 = 0; (l41 < 2); l41 = (l41 + 1)) {
1899 fRec39[l41] = 0.0f;
1900 }
1901 for (int l42 = 0; (l42 < 8192); l42 = (l42 + 1)) {
1902 fVec15[l42] = 0.0f;
1903 }
1904 for (int l43 = 0; (l43 < 2); l43 = (l43 + 1)) {
1905 fRec38[l43] = 0.0f;
1906 }
1907 for (int l44 = 0; (l44 < 2); l44 = (l44 + 1)) {
1908 fRec41[l44] = 0.0f;
1909 }
1910 for (int l45 = 0; (l45 < 8192); l45 = (l45 + 1)) {
1911 fVec16[l45] = 0.0f;
1912 }
1913 for (int l46 = 0; (l46 < 2); l46 = (l46 + 1)) {
1914 fRec40[l46] = 0.0f;
1915 }
1916 for (int l47 = 0; (l47 < 2); l47 = (l47 + 1)) {
1917 fRec43[l47] = 0.0f;
1918 }
1919 for (int l48 = 0; (l48 < 8192); l48 = (l48 + 1)) {
1920 fVec17[l48] = 0.0f;
1921 }
1922 for (int l49 = 0; (l49 < 2); l49 = (l49 + 1)) {
1923 fRec42[l49] = 0.0f;
1924 }
1925 for (int l50 = 0; (l50 < 2); l50 = (l50 + 1)) {
1926 fRec45[l50] = 0.0f;
1927 }
1928 for (int l51 = 0; (l51 < 8192); l51 = (l51 + 1)) {
1929 fVec18[l51] = 0.0f;
1930 }
1931 for (int l52 = 0; (l52 < 2); l52 = (l52 + 1)) {
1932 fRec44[l52] = 0.0f;
1933 }
1934 for (int l53 = 0; (l53 < 2); l53 = (l53 + 1)) {
1935 fRec47[l53] = 0.0f;
1936 }
1937 for (int l54 = 0; (l54 < 8192); l54 = (l54 + 1)) {
1938 fVec19[l54] = 0.0f;
1939 }
1940 for (int l55 = 0; (l55 < 2); l55 = (l55 + 1)) {
1941 fRec46[l55] = 0.0f;
1942 }
1943 for (int l56 = 0; (l56 < 2048); l56 = (l56 + 1)) {
1944 fVec20[l56] = 0.0f;
1945 }
1946 for (int l57 = 0; (l57 < 2); l57 = (l57 + 1)) {
1947 fRec30[l57] = 0.0f;
1948 }
1949 for (int l58 = 0; (l58 < 2048); l58 = (l58 + 1)) {
1950 fVec21[l58] = 0.0f;
1951 }
1952 for (int l59 = 0; (l59 < 2); l59 = (l59 + 1)) {
1953 fRec28[l59] = 0.0f;
1954 }
1955 for (int l60 = 0; (l60 < 2048); l60 = (l60 + 1)) {
1956 fVec22[l60] = 0.0f;
1957 }
1958 for (int l61 = 0; (l61 < 2); l61 = (l61 + 1)) {
1959 fRec26[l61] = 0.0f;
1960 }
1961 for (int l62 = 0; (l62 < 2048); l62 = (l62 + 1)) {
1962 fVec23[l62] = 0.0f;
1963 }
1964 for (int l63 = 0; (l63 < 2); l63 = (l63 + 1)) {
1965 fRec24[l63] = 0.0f;
1966 }
1967 }
1968
1969 virtual void init(int sample_rate) {
1970 classInit(sample_rate);
1971 instanceInit(sample_rate);
1972 }
1973 virtual void instanceInit(int sample_rate) {
1974 instanceConstants(sample_rate);
1975 instanceResetUserInterface();
1976 instanceClear();
1977 }
1978
1979 virtual freeverbdsp* clone() {
1980 return new freeverbdsp();
1981 }
1982
1983 virtual int getSampleRate() {
1984 return fSampleRate;
1985 }
1986
1987 virtual void buildUserInterface(UI* ui_interface) {
1988 ui_interface->openHorizontalBox("Freeverb");
1989 ui_interface->declare(0, "0", "");
1990 ui_interface->openVerticalBox("0x00");
1991 ui_interface->declare(&fVslider1, "0", "");
1992 ui_interface->declare(&fVslider1, "style", "knob");
1993 ui_interface->declare(&fVslider1, "tooltip", "Somehow control the density of the reverb.");
1994 ui_interface->addVerticalSlider("Damp", &fVslider1, 0.5f, 0.0f, 1.0f, 0.0250000004f);
1995 ui_interface->declare(&fVslider0, "1", "");
1996 ui_interface->declare(&fVslider0, "style", "knob");
1997 ui_interface->declare(&fVslider0, "tooltip", "The room size between 0 and 1 with 1 for the largest room.");
1998 ui_interface->addVerticalSlider("RoomSize", &fVslider0, 0.100000001f, 0.0f, 1.0f, 0.0250000004f);
1999 ui_interface->declare(&fVslider3, "2", "");
2000 ui_interface->declare(&fVslider3, "style", "knob");
2001 ui_interface->declare(&fVslider3, "tooltip", "Spatial spread between 0 and 1 with 1 for maximum spread.");
2002 ui_interface->addVerticalSlider("Stereo Spread", &fVslider3, 0.5f, 0.0f, 1.0f, 0.00999999978f);
2003 ui_interface->closeBox();
2004 ui_interface->declare(&fVslider2, "1", "");
2005 ui_interface->declare(&fVslider2, "tooltip", "The amount of reverb applied to the signal between 0 and 1 with 1 for the maximum amount of reverb.");
2006 ui_interface->addVerticalSlider("Wet", &fVslider2, 0.100000001f, 0.0f, 1.0f, 0.0250000004f);
2007 ui_interface->closeBox();
2008 }
2009
2010 virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) {
2011 FAUSTFLOAT* input0 = inputs[0];
2012 FAUSTFLOAT* input1 = inputs[1];
2013 FAUSTFLOAT* output0 = outputs[0];
2014 FAUSTFLOAT* output1 = outputs[1];
2015 float fSlow0 = ((fConst1 * float(fVslider0)) + 0.699999988f);
2016 float fSlow1 = (fConst2 * float(fVslider1));
2017 float fSlow2 = (1.0f - fSlow1);
2018 float fSlow3 = float(fVslider2);
2019 float fSlow4 = (0.100000001f * fSlow3);
2020 float fSlow5 = (1.0f - fSlow3);
2021 int iSlow6 = int((fConst19 * float(fVslider3)));
2022 int iSlow7 = (iConst3 + iSlow6);
2023 int iSlow8 = (iConst4 + iSlow6);
2024 int iSlow9 = (iConst5 + iSlow6);
2025 int iSlow10 = (iConst6 + iSlow6);
2026 int iSlow11 = (iConst7 + iSlow6);
2027 int iSlow12 = (iConst8 + iSlow6);
2028 int iSlow13 = (iConst9 + iSlow6);
2029 int iSlow14 = (iConst10 + iSlow6);
2030 int iSlow15 = (iSlow6 + -1);
2031 int iSlow16 = std::min<int>(1024, std::max<int>(0, (iConst11 + iSlow15)));
2032 int iSlow17 = std::min<int>(1024, std::max<int>(0, (iConst13 + iSlow15)));
2033 int iSlow18 = std::min<int>(1024, std::max<int>(0, (iConst15 + iSlow15)));
2034 int iSlow19 = std::min<int>(1024, std::max<int>(0, (iConst17 + iSlow15)));
2035 for (int i = 0; (i < count); i = (i + 1)) {
2036 float fTemp0 = float(input0[i]);
2037 float fTemp1 = float(input1[i]);
2038 fRec9[0] = ((fSlow1 * fRec9[1]) + (fSlow2 * fRec8[1]));
2039 float fTemp2 = (fSlow4 * (fTemp0 + fTemp1));
2040 fVec0[(IOTA & 8191)] = ((fSlow0 * fRec9[0]) + fTemp2);
2041 fRec8[0] = fVec0[((IOTA - iConst3) & 8191)];
2042 fRec11[0] = ((fSlow1 * fRec11[1]) + (fSlow2 * fRec10[1]));
2043 fVec1[(IOTA & 8191)] = (fTemp2 + (fSlow0 * fRec11[0]));
2044 fRec10[0] = fVec1[((IOTA - iConst4) & 8191)];
2045 fRec13[0] = ((fSlow1 * fRec13[1]) + (fSlow2 * fRec12[1]));
2046 fVec2[(IOTA & 8191)] = (fTemp2 + (fSlow0 * fRec13[0]));
2047 fRec12[0] = fVec2[((IOTA - iConst5) & 8191)];
2048 fRec15[0] = ((fSlow1 * fRec15[1]) + (fSlow2 * fRec14[1]));
2049 fVec3[(IOTA & 8191)] = (fTemp2 + (fSlow0 * fRec15[0]));
2050 fRec14[0] = fVec3[((IOTA - iConst6) & 8191)];
2051 fRec17[0] = ((fSlow1 * fRec17[1]) + (fSlow2 * fRec16[1]));
2052 fVec4[(IOTA & 8191)] = (fTemp2 + (fSlow0 * fRec17[0]));
2053 fRec16[0] = fVec4[((IOTA - iConst7) & 8191)];
2054 fRec19[0] = ((fSlow1 * fRec19[1]) + (fSlow2 * fRec18[1]));
2055 fVec5[(IOTA & 8191)] = (fTemp2 + (fSlow0 * fRec19[0]));
2056 fRec18[0] = fVec5[((IOTA - iConst8) & 8191)];
2057 fRec21[0] = ((fSlow1 * fRec21[1]) + (fSlow2 * fRec20[1]));
2058 fVec6[(IOTA & 8191)] = (fTemp2 + (fSlow0 * fRec21[0]));
2059 fRec20[0] = fVec6[((IOTA - iConst9) & 8191)];
2060 fRec23[0] = ((fSlow1 * fRec23[1]) + (fSlow2 * fRec22[1]));
2061 fVec7[(IOTA & 8191)] = (fTemp2 + (fSlow0 * fRec23[0]));
2062 fRec22[0] = fVec7[((IOTA - iConst10) & 8191)];
2063 float fTemp3 = ((((((((fRec8[0] + fRec10[0]) + fRec12[0]) + fRec14[0]) + fRec16[0]) + fRec18[0]) + fRec20[0]) + fRec22[0]) + (0.5f * fRec6[1]));
2064 fVec8[(IOTA & 2047)] = fTemp3;
2065 fRec6[0] = fVec8[((IOTA - iConst12) & 2047)];
2066 float fRec7 = (0.0f - (0.5f * fTemp3));
2067 float fTemp4 = (fRec6[1] + (fRec7 + (0.5f * fRec4[1])));
2068 fVec9[(IOTA & 2047)] = fTemp4;
2069 fRec4[0] = fVec9[((IOTA - iConst14) & 2047)];
2070 float fRec5 = (0.0f - (0.5f * fTemp4));
2071 float fTemp5 = (fRec4[1] + (fRec5 + (0.5f * fRec2[1])));
2072 fVec10[(IOTA & 2047)] = fTemp5;
2073 fRec2[0] = fVec10[((IOTA - iConst16) & 2047)];
2074 float fRec3 = (0.0f - (0.5f * fTemp5));
2075 float fTemp6 = (fRec2[1] + (fRec3 + (0.5f * fRec0[1])));
2076 fVec11[(IOTA & 1023)] = fTemp6;
2077 fRec0[0] = fVec11[((IOTA - iConst18) & 1023)];
2078 float fRec1 = (0.0f - (0.5f * fTemp6));
2079 output0[i] = FAUSTFLOAT(((fRec1 + fRec0[1]) + (fSlow5 * fTemp0)));
2080 fRec33[0] = ((fSlow1 * fRec33[1]) + (fSlow2 * fRec32[1]));
2081 fVec12[(IOTA & 8191)] = (fTemp2 + (fSlow0 * fRec33[0]));
2082 fRec32[0] = fVec12[((IOTA - iSlow7) & 8191)];
2083 fRec35[0] = ((fSlow1 * fRec35[1]) + (fSlow2 * fRec34[1]));
2084 fVec13[(IOTA & 8191)] = (fTemp2 + (fSlow0 * fRec35[0]));
2085 fRec34[0] = fVec13[((IOTA - iSlow8) & 8191)];
2086 fRec37[0] = ((fSlow1 * fRec37[1]) + (fSlow2 * fRec36[1]));
2087 fVec14[(IOTA & 8191)] = (fTemp2 + (fSlow0 * fRec37[0]));
2088 fRec36[0] = fVec14[((IOTA - iSlow9) & 8191)];
2089 fRec39[0] = ((fSlow1 * fRec39[1]) + (fSlow2 * fRec38[1]));
2090 fVec15[(IOTA & 8191)] = (fTemp2 + (fSlow0 * fRec39[0]));
2091 fRec38[0] = fVec15[((IOTA - iSlow10) & 8191)];
2092 fRec41[0] = ((fSlow1 * fRec41[1]) + (fSlow2 * fRec40[1]));
2093 fVec16[(IOTA & 8191)] = (fTemp2 + (fSlow0 * fRec41[0]));
2094 fRec40[0] = fVec16[((IOTA - iSlow11) & 8191)];
2095 fRec43[0] = ((fSlow1 * fRec43[1]) + (fSlow2 * fRec42[1]));
2096 fVec17[(IOTA & 8191)] = (fTemp2 + (fSlow0 * fRec43[0]));
2097 fRec42[0] = fVec17[((IOTA - iSlow12) & 8191)];
2098 fRec45[0] = ((fSlow1 * fRec45[1]) + (fSlow2 * fRec44[1]));
2099 fVec18[(IOTA & 8191)] = (fTemp2 + (fSlow0 * fRec45[0]));
2100 fRec44[0] = fVec18[((IOTA - iSlow13) & 8191)];
2101 fRec47[0] = ((fSlow1 * fRec47[1]) + (fSlow2 * fRec46[1]));
2102 fVec19[(IOTA & 8191)] = (fTemp2 + (fSlow0 * fRec47[0]));
2103 fRec46[0] = fVec19[((IOTA - iSlow14) & 8191)];
2104 float fTemp7 = ((((((((fRec32[0] + fRec34[0]) + fRec36[0]) + fRec38[0]) + fRec40[0]) + fRec42[0]) + fRec44[0]) + fRec46[0]) + (0.5f * fRec30[1]));
2105 fVec20[(IOTA & 2047)] = fTemp7;
2106 fRec30[0] = fVec20[((IOTA - iSlow16) & 2047)];
2107 float fRec31 = (0.0f - (0.5f * fTemp7));
2108 float fTemp8 = (fRec30[1] + (fRec31 + (0.5f * fRec28[1])));
2109 fVec21[(IOTA & 2047)] = fTemp8;
2110 fRec28[0] = fVec21[((IOTA - iSlow17) & 2047)];
2111 float fRec29 = (0.0f - (0.5f * fTemp8));
2112 float fTemp9 = (fRec28[1] + (fRec29 + (0.5f * fRec26[1])));
2113 fVec22[(IOTA & 2047)] = fTemp9;
2114 fRec26[0] = fVec22[((IOTA - iSlow18) & 2047)];
2115 float fRec27 = (0.0f - (0.5f * fTemp9));
2116 float fTemp10 = (fRec26[1] + (fRec27 + (0.5f * fRec24[1])));
2117 fVec23[(IOTA & 2047)] = fTemp10;
2118 fRec24[0] = fVec23[((IOTA - iSlow19) & 2047)];
2119 float fRec25 = (0.0f - (0.5f * fTemp10));
2120 output1[i] = FAUSTFLOAT(((fRec25 + fRec24[1]) + (fSlow5 * fTemp1)));
2121 fRec9[1] = fRec9[0];
2122 IOTA = (IOTA + 1);
2123 fRec8[1] = fRec8[0];
2124 fRec11[1] = fRec11[0];
2125 fRec10[1] = fRec10[0];
2126 fRec13[1] = fRec13[0];
2127 fRec12[1] = fRec12[0];
2128 fRec15[1] = fRec15[0];
2129 fRec14[1] = fRec14[0];
2130 fRec17[1] = fRec17[0];
2131 fRec16[1] = fRec16[0];
2132 fRec19[1] = fRec19[0];
2133 fRec18[1] = fRec18[0];
2134 fRec21[1] = fRec21[0];
2135 fRec20[1] = fRec20[0];
2136 fRec23[1] = fRec23[0];
2137 fRec22[1] = fRec22[0];
2138 fRec6[1] = fRec6[0];
2139 fRec4[1] = fRec4[0];
2140 fRec2[1] = fRec2[0];
2141 fRec0[1] = fRec0[0];
2142 fRec33[1] = fRec33[0];
2143 fRec32[1] = fRec32[0];
2144 fRec35[1] = fRec35[0];
2145 fRec34[1] = fRec34[0];
2146 fRec37[1] = fRec37[0];
2147 fRec36[1] = fRec36[0];
2148 fRec39[1] = fRec39[0];
2149 fRec38[1] = fRec38[0];
2150 fRec41[1] = fRec41[0];
2151 fRec40[1] = fRec40[0];
2152 fRec43[1] = fRec43[0];
2153 fRec42[1] = fRec42[0];
2154 fRec45[1] = fRec45[0];
2155 fRec44[1] = fRec44[0];
2156 fRec47[1] = fRec47[0];
2157 fRec46[1] = fRec46[0];
2158 fRec30[1] = fRec30[0];
2159 fRec28[1] = fRec28[0];
2160 fRec26[1] = fRec26[0];
2161 fRec24[1] = fRec24[0];
2162 }
2163 }
2164
2165 };
2166
2167 #endif
0 /* ------------------------------------------------------------
1 name: "freeverbmonodsp"
2 Code generated with Faust 2.28.6 (https://faust.grame.fr)
3 Compilation options: -lang cpp -inpl -scal -ftz 0
4 ------------------------------------------------------------ */
5
6 #ifndef __freeverbmonodsp_H__
7 #define __freeverbmonodsp_H__
8
9 // NOTE: ANY INCLUDE-GUARD HERE MUST BE DERIVED FROM THE CLASS NAME
10 //
11 // faust2header.cpp - FAUST Architecture File
12 // This is a simple variation of matlabplot.cpp in the Faust distribution
13 // aimed at creating a simple C++ header file (.h) containing a Faust DSP.
14 // See the Makefile for how to use it.
15
16 /************************** BEGIN dsp.h **************************/
17 /************************************************************************
18 FAUST Architecture File
19 Copyright (C) 2003-2017 GRAME, Centre National de Creation Musicale
20 ---------------------------------------------------------------------
21 This Architecture section is free software; you can redistribute it
22 and/or modify it under the terms of the GNU General Public License
23 as published by the Free Software Foundation; either version 3 of
24 the License, or (at your option) any later version.
25
26 This program is distributed in the hope that it will be useful,
27 but WITHOUT ANY WARRANTY; without even the implied warranty of
28 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 GNU General Public License for more details.
30
31 You should have received a copy of the GNU General Public License
32 along with this program; If not, see <http://www.gnu.org/licenses/>.
33
34 EXCEPTION : As a special exception, you may create a larger work
35 that contains this FAUST architecture section and distribute
36 that work under terms of your choice, so long as this FAUST
37 architecture section is not modified.
38 ************************************************************************/
39
40 #ifndef __dsp__
41 #define __dsp__
42
43 #include <string>
44 #include <vector>
45
46 #ifndef FAUSTFLOAT
47 #define FAUSTFLOAT float
48 #endif
49
50 struct UI;
51 struct Meta;
52
53 /**
54 * DSP memory manager.
55 */
56
57 struct dsp_memory_manager {
58
59 virtual ~dsp_memory_manager() {}
60
61 virtual void* allocate(size_t size) = 0;
62 virtual void destroy(void* ptr) = 0;
63
64 };
65
66 /**
67 * Signal processor definition.
68 */
69
70 class dsp {
71
72 public:
73
74 dsp() {}
75 virtual ~dsp() {}
76
77 /* Return instance number of audio inputs */
78 virtual int getNumInputs() = 0;
79
80 /* Return instance number of audio outputs */
81 virtual int getNumOutputs() = 0;
82
83 /**
84 * Trigger the ui_interface parameter with instance specific calls
85 * to 'openTabBox', 'addButton', 'addVerticalSlider'... in order to build the UI.
86 *
87 * @param ui_interface - the user interface builder
88 */
89 virtual void buildUserInterface(UI* ui_interface) = 0;
90
91 /* Returns the sample rate currently used by the instance */
92 virtual int getSampleRate() = 0;
93
94 /**
95 * Global init, calls the following methods:
96 * - static class 'classInit': static tables initialization
97 * - 'instanceInit': constants and instance state initialization
98 *
99 * @param sample_rate - the sampling rate in Hertz
100 */
101 virtual void init(int sample_rate) = 0;
102
103 /**
104 * Init instance state
105 *
106 * @param sample_rate - the sampling rate in Hertz
107 */
108 virtual void instanceInit(int sample_rate) = 0;
109
110 /**
111 * Init instance constant state
112 *
113 * @param sample_rate - the sampling rate in Hertz
114 */
115 virtual void instanceConstants(int sample_rate) = 0;
116
117 /* Init default control parameters values */
118 virtual void instanceResetUserInterface() = 0;
119
120 /* Init instance state (delay lines...) */
121 virtual void instanceClear() = 0;
122
123 /**
124 * Return a clone of the instance.
125 *
126 * @return a copy of the instance on success, otherwise a null pointer.
127 */
128 virtual dsp* clone() = 0;
129
130 /**
131 * Trigger the Meta* parameter with instance specific calls to 'declare' (key, value) metadata.
132 *
133 * @param m - the Meta* meta user
134 */
135 virtual void metadata(Meta* m) = 0;
136
137 /**
138 * DSP instance computation, to be called with successive in/out audio buffers.
139 *
140 * @param count - the number of frames to compute
141 * @param inputs - the input audio buffers as an array of non-interleaved FAUSTFLOAT samples (eiher float, double or quad)
142 * @param outputs - the output audio buffers as an array of non-interleaved FAUSTFLOAT samples (eiher float, double or quad)
143 *
144 */
145 virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) = 0;
146
147 /**
148 * DSP instance computation: alternative method to be used by subclasses.
149 *
150 * @param date_usec - the timestamp in microsec given by audio driver.
151 * @param count - the number of frames to compute
152 * @param inputs - the input audio buffers as an array of non-interleaved FAUSTFLOAT samples (either float, double or quad)
153 * @param outputs - the output audio buffers as an array of non-interleaved FAUSTFLOAT samples (either float, double or quad)
154 *
155 */
156 virtual void compute(double /*date_usec*/, int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { compute(count, inputs, outputs); }
157
158 };
159
160 /**
161 * Generic DSP decorator.
162 */
163
164 class decorator_dsp : public dsp {
165
166 protected:
167
168 dsp* fDSP;
169
170 public:
171
172 decorator_dsp(dsp* dsp = nullptr):fDSP(dsp) {}
173 virtual ~decorator_dsp() { delete fDSP; }
174
175 virtual int getNumInputs() { return fDSP->getNumInputs(); }
176 virtual int getNumOutputs() { return fDSP->getNumOutputs(); }
177 virtual void buildUserInterface(UI* ui_interface) { fDSP->buildUserInterface(ui_interface); }
178 virtual int getSampleRate() { return fDSP->getSampleRate(); }
179 virtual void init(int sample_rate) { fDSP->init(sample_rate); }
180 virtual void instanceInit(int sample_rate) { fDSP->instanceInit(sample_rate); }
181 virtual void instanceConstants(int sample_rate) { fDSP->instanceConstants(sample_rate); }
182 virtual void instanceResetUserInterface() { fDSP->instanceResetUserInterface(); }
183 virtual void instanceClear() { fDSP->instanceClear(); }
184 virtual decorator_dsp* clone() { return new decorator_dsp(fDSP->clone()); }
185 virtual void metadata(Meta* m) { fDSP->metadata(m); }
186 // Beware: subclasses usually have to overload the two 'compute' methods
187 virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { fDSP->compute(count, inputs, outputs); }
188 virtual void compute(double date_usec, int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { fDSP->compute(date_usec, count, inputs, outputs); }
189
190 };
191
192 /**
193 * DSP factory class.
194 */
195
196 class dsp_factory {
197
198 protected:
199
200 // So that to force sub-classes to use deleteDSPFactory(dsp_factory* factory);
201 virtual ~dsp_factory() {}
202
203 public:
204
205 virtual std::string getName() = 0;
206 virtual std::string getSHAKey() = 0;
207 virtual std::string getDSPCode() = 0;
208 virtual std::string getCompileOptions() = 0;
209 virtual std::vector<std::string> getLibraryList() = 0;
210 virtual std::vector<std::string> getIncludePathnames() = 0;
211
212 virtual dsp* createDSPInstance() = 0;
213
214 virtual void setMemoryManager(dsp_memory_manager* manager) = 0;
215 virtual dsp_memory_manager* getMemoryManager() = 0;
216
217 };
218
219 /**
220 * On Intel set FZ (Flush to Zero) and DAZ (Denormals Are Zero)
221 * flags to avoid costly denormals.
222 */
223
224 #ifdef __SSE__
225 #include <xmmintrin.h>
226 #ifdef __SSE2__
227 #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8040)
228 #else
229 #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8000)
230 #endif
231 #else
232 #define AVOIDDENORMALS
233 #endif
234
235 #endif
236 /************************** END dsp.h **************************/
237
238 /************************** BEGIN APIUI.h **************************/
239 /************************************************************************
240 FAUST Architecture File
241 Copyright (C) 2003-2017 GRAME, Centre National de Creation Musicale
242 ---------------------------------------------------------------------
243 This Architecture section is free software; you can redistribute it
244 and/or modify it under the terms of the GNU General Public License
245 as published by the Free Software Foundation; either version 3 of
246 the License, or (at your option) any later version.
247
248 This program is distributed in the hope that it will be useful,
249 but WITHOUT ANY WARRANTY; without even the implied warranty of
250 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
251 GNU General Public License for more details.
252
253 You should have received a copy of the GNU General Public License
254 along with this program; If not, see <http://www.gnu.org/licenses/>.
255
256 EXCEPTION : As a special exception, you may create a larger work
257 that contains this FAUST architecture section and distribute
258 that work under terms of your choice, so long as this FAUST
259 architecture section is not modified.
260 ************************************************************************/
261
262 #ifndef API_UI_H
263 #define API_UI_H
264
265 #include <sstream>
266 #include <string>
267 #include <vector>
268 #include <iostream>
269 #include <map>
270
271 /************************** BEGIN meta.h **************************/
272 /************************************************************************
273 FAUST Architecture File
274 Copyright (C) 2003-2017 GRAME, Centre National de Creation Musicale
275 ---------------------------------------------------------------------
276 This Architecture section is free software; you can redistribute it
277 and/or modify it under the terms of the GNU General Public License
278 as published by the Free Software Foundation; either version 3 of
279 the License, or (at your option) any later version.
280
281 This program is distributed in the hope that it will be useful,
282 but WITHOUT ANY WARRANTY; without even the implied warranty of
283 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
284 GNU General Public License for more details.
285
286 You should have received a copy of the GNU General Public License
287 along with this program; If not, see <http://www.gnu.org/licenses/>.
288
289 EXCEPTION : As a special exception, you may create a larger work
290 that contains this FAUST architecture section and distribute
291 that work under terms of your choice, so long as this FAUST
292 architecture section is not modified.
293 ************************************************************************/
294
295 #ifndef __meta__
296 #define __meta__
297
298 struct Meta
299 {
300 virtual ~Meta() {};
301 virtual void declare(const char* key, const char* value) = 0;
302
303 };
304
305 #endif
306 /************************** END meta.h **************************/
307 /************************** BEGIN UI.h **************************/
308 /************************************************************************
309 FAUST Architecture File
310 Copyright (C) 2003-2020 GRAME, Centre National de Creation Musicale
311 ---------------------------------------------------------------------
312 This Architecture section is free software; you can redistribute it
313 and/or modify it under the terms of the GNU General Public License
314 as published by the Free Software Foundation; either version 3 of
315 the License, or (at your option) any later version.
316
317 This program is distributed in the hope that it will be useful,
318 but WITHOUT ANY WARRANTY; without even the implied warranty of
319 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
320 GNU General Public License for more details.
321
322 You should have received a copy of the GNU General Public License
323 along with this program; If not, see <http://www.gnu.org/licenses/>.
324
325 EXCEPTION : As a special exception, you may create a larger work
326 that contains this FAUST architecture section and distribute
327 that work under terms of your choice, so long as this FAUST
328 architecture section is not modified.
329 ************************************************************************/
330
331 #ifndef __UI_H__
332 #define __UI_H__
333
334 #ifndef FAUSTFLOAT
335 #define FAUSTFLOAT float
336 #endif
337
338 /*******************************************************************************
339 * UI : Faust DSP User Interface
340 * User Interface as expected by the buildUserInterface() method of a DSP.
341 * This abstract class contains only the method that the Faust compiler can
342 * generate to describe a DSP user interface.
343 ******************************************************************************/
344
345 struct Soundfile;
346
347 template <typename REAL>
348 struct UIReal
349 {
350 UIReal() {}
351 virtual ~UIReal() {}
352
353 // -- widget's layouts
354
355 virtual void openTabBox(const char* label) = 0;
356 virtual void openHorizontalBox(const char* label) = 0;
357 virtual void openVerticalBox(const char* label) = 0;
358 virtual void closeBox() = 0;
359
360 // -- active widgets
361
362 virtual void addButton(const char* label, REAL* zone) = 0;
363 virtual void addCheckButton(const char* label, REAL* zone) = 0;
364 virtual void addVerticalSlider(const char* label, REAL* zone, REAL init, REAL min, REAL max, REAL step) = 0;
365 virtual void addHorizontalSlider(const char* label, REAL* zone, REAL init, REAL min, REAL max, REAL step) = 0;
366 virtual void addNumEntry(const char* label, REAL* zone, REAL init, REAL min, REAL max, REAL step) = 0;
367
368 // -- passive widgets
369
370 virtual void addHorizontalBargraph(const char* label, REAL* zone, REAL min, REAL max) = 0;
371 virtual void addVerticalBargraph(const char* label, REAL* zone, REAL min, REAL max) = 0;
372
373 // -- soundfiles
374
375 virtual void addSoundfile(const char* label, const char* filename, Soundfile** sf_zone) = 0;
376
377 // -- metadata declarations
378
379 virtual void declare(REAL* zone, const char* key, const char* val) {}
380 };
381
382 struct UI : public UIReal<FAUSTFLOAT>
383 {
384 UI() {}
385 virtual ~UI() {}
386 };
387
388 #endif
389 /************************** END UI.h **************************/
390 /************************** BEGIN PathBuilder.h **************************/
391 /************************************************************************
392 FAUST Architecture File
393 Copyright (C) 2003-2017 GRAME, Centre National de Creation Musicale
394 ---------------------------------------------------------------------
395 This Architecture section is free software; you can redistribute it
396 and/or modify it under the terms of the GNU General Public License
397 as published by the Free Software Foundation; either version 3 of
398 the License, or (at your option) any later version.
399
400 This program is distributed in the hope that it will be useful,
401 but WITHOUT ANY WARRANTY; without even the implied warranty of
402 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
403 GNU General Public License for more details.
404
405 You should have received a copy of the GNU General Public License
406 along with this program; If not, see <http://www.gnu.org/licenses/>.
407
408 EXCEPTION : As a special exception, you may create a larger work
409 that contains this FAUST architecture section and distribute
410 that work under terms of your choice, so long as this FAUST
411 architecture section is not modified.
412 ************************************************************************/
413
414 #ifndef FAUST_PATHBUILDER_H
415 #define FAUST_PATHBUILDER_H
416
417 #include <vector>
418 #include <string>
419 #include <algorithm>
420
421 /*******************************************************************************
422 * PathBuilder : Faust User Interface
423 * Helper class to build complete hierarchical path for UI items.
424 ******************************************************************************/
425
426 class PathBuilder
427 {
428
429 protected:
430
431 std::vector<std::string> fControlsLevel;
432
433 public:
434
435 PathBuilder() {}
436 virtual ~PathBuilder() {}
437
438 std::string buildPath(const std::string& label)
439 {
440 std::string res = "/";
441 for (size_t i = 0; i < fControlsLevel.size(); i++) {
442 res += fControlsLevel[i];
443 res += "/";
444 }
445 res += label;
446 std::replace(res.begin(), res.end(), ' ', '_');
447 return res;
448 }
449
450 std::string buildLabel(std::string label)
451 {
452 std::replace(label.begin(), label.end(), ' ', '_');
453 return label;
454 }
455
456 void pushLabel(const std::string& label) { fControlsLevel.push_back(label); }
457 void popLabel() { fControlsLevel.pop_back(); }
458
459 };
460
461 #endif // FAUST_PATHBUILDER_H
462 /************************** END PathBuilder.h **************************/
463 /************************** BEGIN ValueConverter.h **************************/
464 /************************************************************************
465 FAUST Architecture File
466 Copyright (C) 2003-2017 GRAME, Centre National de Creation Musicale
467 ---------------------------------------------------------------------
468 This Architecture section is free software; you can redistribute it
469 and/or modify it under the terms of the GNU General Public License
470 as published by the Free Software Foundation; either version 3 of
471 the License, or (at your option) any later version.
472
473 This program is distributed in the hope that it will be useful,
474 but WITHOUT ANY WARRANTY; without even the implied warranty of
475 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
476 GNU General Public License for more details.
477
478 You should have received a copy of the GNU General Public License
479 along with this program; If not, see <http://www.gnu.org/licenses/>.
480
481 EXCEPTION : As a special exception, you may create a larger work
482 that contains this FAUST architecture section and distribute
483 that work under terms of your choice, so long as this FAUST
484 architecture section is not modified.
485 ************************************************************************/
486
487 #ifndef __ValueConverter__
488 #define __ValueConverter__
489
490 /***************************************************************************************
491 ValueConverter.h
492 (GRAME, Copyright 2015-2019)
493
494 Set of conversion objects used to map user interface values (for example a gui slider
495 delivering values between 0 and 1) to faust values (for example a vslider between
496 20 and 20000) using a log scale.
497
498 -- Utilities
499
500 Range(lo,hi) : clip a value x between lo and hi
501 Interpolator(lo,hi,v1,v2) : Maps a value x between lo and hi to a value y between v1 and v2
502 Interpolator3pt(lo,mi,hi,v1,vm,v2) : Map values between lo mid hi to values between v1 vm v2
503
504 -- Value Converters
505
506 ValueConverter::ui2faust(x)
507 ValueConverter::faust2ui(x)
508
509 -- ValueConverters used for sliders depending of the scale
510
511 LinearValueConverter(umin, umax, fmin, fmax)
512 LinearValueConverter2(lo, mi, hi, v1, vm, v2) using 2 segments
513 LogValueConverter(umin, umax, fmin, fmax)
514 ExpValueConverter(umin, umax, fmin, fmax)
515
516 -- ValueConverters used for accelerometers based on 3 points
517
518 AccUpConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 0
519 AccDownConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 1
520 AccUpDownConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 2
521 AccDownUpConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 3
522
523 -- lists of ZoneControl are used to implement accelerometers metadata for each axes
524
525 ZoneControl(zone, valueConverter) : a zone with an accelerometer data converter
526
527 -- ZoneReader are used to implement screencolor metadata
528
529 ZoneReader(zone, valueConverter) : a zone with a data converter
530
531 ****************************************************************************************/
532
533 #include <float.h>
534 #include <algorithm> // std::max
535 #include <cmath>
536 #include <vector>
537 #include <assert.h>
538
539 //--------------------------------------------------------------------------------------
540 // Interpolator(lo,hi,v1,v2)
541 // Maps a value x between lo and hi to a value y between v1 and v2
542 // y = v1 + (x-lo)/(hi-lo)*(v2-v1)
543 // y = v1 + (x-lo) * coef with coef = (v2-v1)/(hi-lo)
544 // y = v1 + x*coef - lo*coef
545 // y = v1 - lo*coef + x*coef
546 // y = offset + x*coef with offset = v1 - lo*coef
547 //--------------------------------------------------------------------------------------
548 class Interpolator
549 {
550 private:
551
552 //--------------------------------------------------------------------------------------
553 // Range(lo,hi) clip a value between lo and hi
554 //--------------------------------------------------------------------------------------
555 struct Range
556 {
557 double fLo;
558 double fHi;
559
560 Range(double x, double y) : fLo(std::min<double>(x,y)), fHi(std::max<double>(x,y)) {}
561 double operator()(double x) { return (x<fLo) ? fLo : (x>fHi) ? fHi : x; }
562 };
563
564
565 Range fRange;
566 double fCoef;
567 double fOffset;
568
569 public:
570
571 Interpolator(double lo, double hi, double v1, double v2) : fRange(lo,hi)
572 {
573 if (hi != lo) {
574 // regular case
575 fCoef = (v2-v1)/(hi-lo);
576 fOffset = v1 - lo*fCoef;
577 } else {
578 // degenerate case, avoids division by zero
579 fCoef = 0;
580 fOffset = (v1+v2)/2;
581 }
582 }
583 double operator()(double v)
584 {
585 double x = fRange(v);
586 return fOffset + x*fCoef;
587 }
588
589 void getLowHigh(double& amin, double& amax)
590 {
591 amin = fRange.fLo;
592 amax = fRange.fHi;
593 }
594 };
595
596 //--------------------------------------------------------------------------------------
597 // Interpolator3pt(lo,mi,hi,v1,vm,v2)
598 // Map values between lo mid hi to values between v1 vm v2
599 //--------------------------------------------------------------------------------------
600 class Interpolator3pt
601 {
602
603 private:
604
605 Interpolator fSegment1;
606 Interpolator fSegment2;
607 double fMid;
608
609 public:
610
611 Interpolator3pt(double lo, double mi, double hi, double v1, double vm, double v2) :
612 fSegment1(lo, mi, v1, vm),
613 fSegment2(mi, hi, vm, v2),
614 fMid(mi) {}
615 double operator()(double x) { return (x < fMid) ? fSegment1(x) : fSegment2(x); }
616
617 void getMappingValues(double& amin, double& amid, double& amax)
618 {
619 fSegment1.getLowHigh(amin, amid);
620 fSegment2.getLowHigh(amid, amax);
621 }
622 };
623
624 //--------------------------------------------------------------------------------------
625 // Abstract ValueConverter class. Converts values between UI and Faust representations
626 //--------------------------------------------------------------------------------------
627 class ValueConverter
628 {
629
630 public:
631
632 virtual ~ValueConverter() {}
633 virtual double ui2faust(double x) = 0;
634 virtual double faust2ui(double x) = 0;
635 };
636
637 //--------------------------------------------------------------------------------------
638 // A converter than can be updated
639 //--------------------------------------------------------------------------------------
640
641 class UpdatableValueConverter : public ValueConverter {
642
643 protected:
644
645 bool fActive;
646
647 public:
648
649 UpdatableValueConverter():fActive(true)
650 {}
651 virtual ~UpdatableValueConverter()
652 {}
653
654 virtual void setMappingValues(double amin, double amid, double amax, double min, double init, double max) = 0;
655 virtual void getMappingValues(double& amin, double& amid, double& amax) = 0;
656
657 void setActive(bool on_off) { fActive = on_off; }
658 bool getActive() { return fActive; }
659
660 };
661
662
663 //--------------------------------------------------------------------------------------
664 // Linear conversion between ui and Faust values
665 //--------------------------------------------------------------------------------------
666 class LinearValueConverter : public ValueConverter
667 {
668
669 private:
670
671 Interpolator fUI2F;
672 Interpolator fF2UI;
673
674 public:
675
676 LinearValueConverter(double umin, double umax, double fmin, double fmax) :
677 fUI2F(umin,umax,fmin,fmax), fF2UI(fmin,fmax,umin,umax)
678 {}
679
680 LinearValueConverter() : fUI2F(0.,0.,0.,0.), fF2UI(0.,0.,0.,0.)
681 {}
682 virtual double ui2faust(double x) { return fUI2F(x); }
683 virtual double faust2ui(double x) { return fF2UI(x); }
684
685 };
686
687 //--------------------------------------------------------------------------------------
688 // Two segments linear conversion between ui and Faust values
689 //--------------------------------------------------------------------------------------
690 class LinearValueConverter2 : public UpdatableValueConverter
691 {
692
693 private:
694
695 Interpolator3pt fUI2F;
696 Interpolator3pt fF2UI;
697
698 public:
699
700 LinearValueConverter2(double amin, double amid, double amax, double min, double init, double max) :
701 fUI2F(amin, amid, amax, min, init, max), fF2UI(min, init, max, amin, amid, amax)
702 {}
703
704 LinearValueConverter2() : fUI2F(0.,0.,0.,0.,0.,0.), fF2UI(0.,0.,0.,0.,0.,0.)
705 {}
706
707 virtual double ui2faust(double x) { return fUI2F(x); }
708 virtual double faust2ui(double x) { return fF2UI(x); }
709
710 virtual void setMappingValues(double amin, double amid, double amax, double min, double init, double max)
711 {
712 fUI2F = Interpolator3pt(amin, amid, amax, min, init, max);
713 fF2UI = Interpolator3pt(min, init, max, amin, amid, amax);
714 }
715
716 virtual void getMappingValues(double& amin, double& amid, double& amax)
717 {
718 fUI2F.getMappingValues(amin, amid, amax);
719 }
720
721 };
722
723 //--------------------------------------------------------------------------------------
724 // Logarithmic conversion between ui and Faust values
725 //--------------------------------------------------------------------------------------
726 class LogValueConverter : public LinearValueConverter
727 {
728
729 public:
730
731 LogValueConverter(double umin, double umax, double fmin, double fmax) :
732 LinearValueConverter(umin, umax, std::log(std::max<double>(DBL_MIN, fmin)), std::log(std::max<double>(DBL_MIN, fmax)))
733 {}
734
735 virtual double ui2faust(double x) { return std::exp(LinearValueConverter::ui2faust(x)); }
736 virtual double faust2ui(double x) { return LinearValueConverter::faust2ui(std::log(std::max<double>(x, DBL_MIN))); }
737
738 };
739
740 //--------------------------------------------------------------------------------------
741 // Exponential conversion between ui and Faust values
742 //--------------------------------------------------------------------------------------
743 class ExpValueConverter : public LinearValueConverter
744 {
745
746 public:
747
748 ExpValueConverter(double umin, double umax, double fmin, double fmax) :
749 LinearValueConverter(umin, umax, std::min<double>(DBL_MAX, std::exp(fmin)), std::min<double>(DBL_MAX, std::exp(fmax)))
750 {}
751
752 virtual double ui2faust(double x) { return std::log(LinearValueConverter::ui2faust(x)); }
753 virtual double faust2ui(double x) { return LinearValueConverter::faust2ui(std::min<double>(DBL_MAX, std::exp(x))); }
754
755 };
756
757 //--------------------------------------------------------------------------------------
758 // Convert accelerometer or gyroscope values to Faust values
759 // Using an Up curve (curve 0)
760 //--------------------------------------------------------------------------------------
761 class AccUpConverter : public UpdatableValueConverter
762 {
763
764 private:
765
766 Interpolator3pt fA2F;
767 Interpolator3pt fF2A;
768
769 public:
770
771 AccUpConverter(double amin, double amid, double amax, double fmin, double fmid, double fmax) :
772 fA2F(amin,amid,amax,fmin,fmid,fmax),
773 fF2A(fmin,fmid,fmax,amin,amid,amax)
774 {}
775
776 virtual double ui2faust(double x) { return fA2F(x); }
777 virtual double faust2ui(double x) { return fF2A(x); }
778
779 virtual void setMappingValues(double amin, double amid, double amax, double fmin, double fmid, double fmax)
780 {
781 //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccUpConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax);
782 fA2F = Interpolator3pt(amin, amid, amax, fmin, fmid, fmax);
783 fF2A = Interpolator3pt(fmin, fmid, fmax, amin, amid, amax);
784 }
785
786 virtual void getMappingValues(double& amin, double& amid, double& amax)
787 {
788 fA2F.getMappingValues(amin, amid, amax);
789 }
790
791 };
792
793 //--------------------------------------------------------------------------------------
794 // Convert accelerometer or gyroscope values to Faust values
795 // Using a Down curve (curve 1)
796 //--------------------------------------------------------------------------------------
797 class AccDownConverter : public UpdatableValueConverter
798 {
799
800 private:
801
802 Interpolator3pt fA2F;
803 Interpolator3pt fF2A;
804
805 public:
806
807 AccDownConverter(double amin, double amid, double amax, double fmin, double fmid, double fmax) :
808 fA2F(amin,amid,amax,fmax,fmid,fmin),
809 fF2A(fmin,fmid,fmax,amax,amid,amin)
810 {}
811
812 virtual double ui2faust(double x) { return fA2F(x); }
813 virtual double faust2ui(double x) { return fF2A(x); }
814
815 virtual void setMappingValues(double amin, double amid, double amax, double fmin, double fmid, double fmax)
816 {
817 //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccDownConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax);
818 fA2F = Interpolator3pt(amin, amid, amax, fmax, fmid, fmin);
819 fF2A = Interpolator3pt(fmin, fmid, fmax, amax, amid, amin);
820 }
821
822 virtual void getMappingValues(double& amin, double& amid, double& amax)
823 {
824 fA2F.getMappingValues(amin, amid, amax);
825 }
826 };
827
828 //--------------------------------------------------------------------------------------
829 // Convert accelerometer or gyroscope values to Faust values
830 // Using an Up-Down curve (curve 2)
831 //--------------------------------------------------------------------------------------
832 class AccUpDownConverter : public UpdatableValueConverter
833 {
834
835 private:
836
837 Interpolator3pt fA2F;
838 Interpolator fF2A;
839
840 public:
841
842 AccUpDownConverter(double amin, double amid, double amax, double fmin, double fmid, double fmax) :
843 fA2F(amin,amid,amax,fmin,fmax,fmin),
844 fF2A(fmin,fmax,amin,amax) // Special, pseudo inverse of a non monotonic function
845 {}
846
847 virtual double ui2faust(double x) { return fA2F(x); }
848 virtual double faust2ui(double x) { return fF2A(x); }
849
850 virtual void setMappingValues(double amin, double amid, double amax, double fmin, double fmid, double fmax)
851 {
852 //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccUpDownConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax);
853 fA2F = Interpolator3pt(amin, amid, amax, fmin, fmax, fmin);
854 fF2A = Interpolator(fmin, fmax, amin, amax);
855 }
856
857 virtual void getMappingValues(double& amin, double& amid, double& amax)
858 {
859 fA2F.getMappingValues(amin, amid, amax);
860 }
861 };
862
863 //--------------------------------------------------------------------------------------
864 // Convert accelerometer or gyroscope values to Faust values
865 // Using a Down-Up curve (curve 3)
866 //--------------------------------------------------------------------------------------
867 class AccDownUpConverter : public UpdatableValueConverter
868 {
869
870 private:
871
872 Interpolator3pt fA2F;
873 Interpolator fF2A;
874
875 public:
876
877 AccDownUpConverter(double amin, double amid, double amax, double fmin, double fmid, double fmax) :
878 fA2F(amin,amid,amax,fmax,fmin,fmax),
879 fF2A(fmin,fmax,amin,amax) // Special, pseudo inverse of a non monotonic function
880 {}
881
882 virtual double ui2faust(double x) { return fA2F(x); }
883 virtual double faust2ui(double x) { return fF2A(x); }
884
885 virtual void setMappingValues(double amin, double amid, double amax, double fmin, double fmid, double fmax)
886 {
887 //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccDownUpConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax);
888 fA2F = Interpolator3pt(amin, amid, amax, fmax, fmin, fmax);
889 fF2A = Interpolator(fmin, fmax, amin, amax);
890 }
891
892 virtual void getMappingValues(double& amin, double& amid, double& amax)
893 {
894 fA2F.getMappingValues(amin, amid, amax);
895 }
896 };
897
898 //--------------------------------------------------------------------------------------
899 // Base class for ZoneControl
900 //--------------------------------------------------------------------------------------
901 class ZoneControl
902 {
903
904 protected:
905
906 FAUSTFLOAT* fZone;
907
908 public:
909
910 ZoneControl(FAUSTFLOAT* zone) : fZone(zone) {}
911 virtual ~ZoneControl() {}
912
913 virtual void update(double v) const {}
914
915 virtual void setMappingValues(int curve, double amin, double amid, double amax, double min, double init, double max) {}
916 virtual void getMappingValues(double& amin, double& amid, double& amax) {}
917
918 FAUSTFLOAT* getZone() { return fZone; }
919
920 virtual void setActive(bool on_off) {}
921 virtual bool getActive() { return false; }
922
923 virtual int getCurve() { return -1; }
924
925 };
926
927 //--------------------------------------------------------------------------------------
928 // Useful to implement accelerometers metadata as a list of ZoneControl for each axes
929 //--------------------------------------------------------------------------------------
930 class ConverterZoneControl : public ZoneControl
931 {
932
933 protected:
934
935 ValueConverter* fValueConverter;
936
937 public:
938
939 ConverterZoneControl(FAUSTFLOAT* zone, ValueConverter* converter) : ZoneControl(zone), fValueConverter(converter) {}
940 virtual ~ConverterZoneControl() { delete fValueConverter; } // Assuming fValueConverter is not kept elsewhere...
941
942 virtual void update(double v) const { *fZone = fValueConverter->ui2faust(v); }
943
944 ValueConverter* getConverter() { return fValueConverter; }
945
946 };
947
948 //--------------------------------------------------------------------------------------
949 // Association of a zone and a four value converter, each one for each possible curve.
950 // Useful to implement accelerometers metadata as a list of ZoneControl for each axes
951 //--------------------------------------------------------------------------------------
952 class CurveZoneControl : public ZoneControl
953 {
954
955 private:
956
957 std::vector<UpdatableValueConverter*> fValueConverters;
958 int fCurve;
959
960 public:
961
962 CurveZoneControl(FAUSTFLOAT* zone, int curve, double amin, double amid, double amax, double min, double init, double max) : ZoneControl(zone), fCurve(0)
963 {
964 assert(curve >= 0 && curve <= 3);
965 fValueConverters.push_back(new AccUpConverter(amin, amid, amax, min, init, max));
966 fValueConverters.push_back(new AccDownConverter(amin, amid, amax, min, init, max));
967 fValueConverters.push_back(new AccUpDownConverter(amin, amid, amax, min, init, max));
968 fValueConverters.push_back(new AccDownUpConverter(amin, amid, amax, min, init, max));
969 fCurve = curve;
970 }
971 virtual ~CurveZoneControl()
972 {
973 std::vector<UpdatableValueConverter*>::iterator it;
974 for (it = fValueConverters.begin(); it != fValueConverters.end(); it++) {
975 delete(*it);
976 }
977 }
978 void update(double v) const { if (fValueConverters[fCurve]->getActive()) *fZone = fValueConverters[fCurve]->ui2faust(v); }
979
980 void setMappingValues(int curve, double amin, double amid, double amax, double min, double init, double max)
981 {
982 fValueConverters[curve]->setMappingValues(amin, amid, amax, min, init, max);
983 fCurve = curve;
984 }
985
986 void getMappingValues(double& amin, double& amid, double& amax)
987 {
988 fValueConverters[fCurve]->getMappingValues(amin, amid, amax);
989 }
990
991 void setActive(bool on_off)
992 {
993 std::vector<UpdatableValueConverter*>::iterator it;
994 for (it = fValueConverters.begin(); it != fValueConverters.end(); it++) {
995 (*it)->setActive(on_off);
996 }
997 }
998
999 int getCurve() { return fCurve; }
1000 };
1001
1002 class ZoneReader
1003 {
1004
1005 private:
1006
1007 FAUSTFLOAT* fZone;
1008 Interpolator fInterpolator;
1009
1010 public:
1011
1012 ZoneReader(FAUSTFLOAT* zone, double lo, double hi) : fZone(zone), fInterpolator(lo, hi, 0, 255) {}
1013
1014 virtual ~ZoneReader() {}
1015
1016 int getValue()
1017 {
1018 return (fZone != nullptr) ? int(fInterpolator(*fZone)) : 127;
1019 }
1020
1021 };
1022
1023 #endif
1024 /************************** END ValueConverter.h **************************/
1025
1026 class APIUI : public PathBuilder, public Meta, public UI
1027 {
1028 public:
1029
1030 enum ItemType { kButton = 0, kCheckButton, kVSlider, kHSlider, kNumEntry, kHBargraph, kVBargraph };
1031
1032 protected:
1033
1034 enum { kLin = 0, kLog = 1, kExp = 2 };
1035
1036 int fNumParameters;
1037 std::vector<std::string> fPaths;
1038 std::vector<std::string> fLabels;
1039 std::map<std::string, int> fPathMap;
1040 std::map<std::string, int> fLabelMap;
1041 std::vector<ValueConverter*> fConversion;
1042 std::vector<FAUSTFLOAT*> fZone;
1043 std::vector<FAUSTFLOAT> fInit;
1044 std::vector<FAUSTFLOAT> fMin;
1045 std::vector<FAUSTFLOAT> fMax;
1046 std::vector<FAUSTFLOAT> fStep;
1047 std::vector<ItemType> fItemType;
1048 std::vector<std::map<std::string, std::string> > fMetaData;
1049 std::vector<ZoneControl*> fAcc[3];
1050 std::vector<ZoneControl*> fGyr[3];
1051
1052 // Screen color control
1053 // "...[screencolor:red]..." etc.
1054 bool fHasScreenControl; // true if control screen color metadata
1055 ZoneReader* fRedReader;
1056 ZoneReader* fGreenReader;
1057 ZoneReader* fBlueReader;
1058
1059 // Current values controlled by metadata
1060 std::string fCurrentUnit;
1061 int fCurrentScale;
1062 std::string fCurrentAcc;
1063 std::string fCurrentGyr;
1064 std::string fCurrentColor;
1065 std::string fCurrentTooltip;
1066 std::map<std::string, std::string> fCurrentMetadata;
1067
1068 // Add a generic parameter
1069 virtual void addParameter(const char* label,
1070 FAUSTFLOAT* zone,
1071 FAUSTFLOAT init,
1072 FAUSTFLOAT min,
1073 FAUSTFLOAT max,
1074 FAUSTFLOAT step,
1075 ItemType type)
1076 {
1077 std::string path = buildPath(label);
1078 fPathMap[path] = fLabelMap[label] = fNumParameters++;
1079 fPaths.push_back(path);
1080 fLabels.push_back(label);
1081 fZone.push_back(zone);
1082 fInit.push_back(init);
1083 fMin.push_back(min);
1084 fMax.push_back(max);
1085 fStep.push_back(step);
1086 fItemType.push_back(type);
1087
1088 // handle scale metadata
1089 switch (fCurrentScale) {
1090 case kLin:
1091 fConversion.push_back(new LinearValueConverter(0, 1, min, max));
1092 break;
1093 case kLog:
1094 fConversion.push_back(new LogValueConverter(0, 1, min, max));
1095 break;
1096 case kExp: fConversion.push_back(new ExpValueConverter(0, 1, min, max));
1097 break;
1098 }
1099 fCurrentScale = kLin;
1100
1101 if (fCurrentAcc.size() > 0 && fCurrentGyr.size() > 0) {
1102 std::cerr << "warning : 'acc' and 'gyr' metadata used for the same " << label << " parameter !!\n";
1103 }
1104
1105 // handle acc metadata "...[acc : <axe> <curve> <amin> <amid> <amax>]..."
1106 if (fCurrentAcc.size() > 0) {
1107 std::istringstream iss(fCurrentAcc);
1108 int axe, curve;
1109 double amin, amid, amax;
1110 iss >> axe >> curve >> amin >> amid >> amax;
1111
1112 if ((0 <= axe) && (axe < 3) &&
1113 (0 <= curve) && (curve < 4) &&
1114 (amin < amax) && (amin <= amid) && (amid <= amax))
1115 {
1116 fAcc[axe].push_back(new CurveZoneControl(zone, curve, amin, amid, amax, min, init, max));
1117 } else {
1118 std::cerr << "incorrect acc metadata : " << fCurrentAcc << std::endl;
1119 }
1120 fCurrentAcc = "";
1121 }
1122
1123 // handle gyr metadata "...[gyr : <axe> <curve> <amin> <amid> <amax>]..."
1124 if (fCurrentGyr.size() > 0) {
1125 std::istringstream iss(fCurrentGyr);
1126 int axe, curve;
1127 double amin, amid, amax;
1128 iss >> axe >> curve >> amin >> amid >> amax;
1129
1130 if ((0 <= axe) && (axe < 3) &&
1131 (0 <= curve) && (curve < 4) &&
1132 (amin < amax) && (amin <= amid) && (amid <= amax))
1133 {
1134 fGyr[axe].push_back(new CurveZoneControl(zone, curve, amin, amid, amax, min, init, max));
1135 } else {
1136 std::cerr << "incorrect gyr metadata : " << fCurrentGyr << std::endl;
1137 }
1138 fCurrentGyr = "";
1139 }
1140
1141 // handle screencolor metadata "...[screencolor:red|green|blue|white]..."
1142 if (fCurrentColor.size() > 0) {
1143 if ((fCurrentColor == "red") && (fRedReader == 0)) {
1144 fRedReader = new ZoneReader(zone, min, max);
1145 fHasScreenControl = true;
1146 } else if ((fCurrentColor == "green") && (fGreenReader == 0)) {
1147 fGreenReader = new ZoneReader(zone, min, max);
1148 fHasScreenControl = true;
1149 } else if ((fCurrentColor == "blue") && (fBlueReader == 0)) {
1150 fBlueReader = new ZoneReader(zone, min, max);
1151 fHasScreenControl = true;
1152 } else if ((fCurrentColor == "white") && (fRedReader == 0) && (fGreenReader == 0) && (fBlueReader == 0)) {
1153 fRedReader = new ZoneReader(zone, min, max);
1154 fGreenReader = new ZoneReader(zone, min, max);
1155 fBlueReader = new ZoneReader(zone, min, max);
1156 fHasScreenControl = true;
1157 } else {
1158 std::cerr << "incorrect screencolor metadata : " << fCurrentColor << std::endl;
1159 }
1160 }
1161 fCurrentColor = "";
1162
1163 fMetaData.push_back(fCurrentMetadata);
1164 fCurrentMetadata.clear();
1165 }
1166
1167 int getZoneIndex(std::vector<ZoneControl*>* table, int p, int val)
1168 {
1169 FAUSTFLOAT* zone = fZone[p];
1170 for (size_t i = 0; i < table[val].size(); i++) {
1171 if (zone == table[val][i]->getZone()) return int(i);
1172 }
1173 return -1;
1174 }
1175
1176 void setConverter(std::vector<ZoneControl*>* table, int p, int val, int curve, double amin, double amid, double amax)
1177 {
1178 int id1 = getZoneIndex(table, p, 0);
1179 int id2 = getZoneIndex(table, p, 1);
1180 int id3 = getZoneIndex(table, p, 2);
1181
1182 // Deactivates everywhere..
1183 if (id1 != -1) table[0][id1]->setActive(false);
1184 if (id2 != -1) table[1][id2]->setActive(false);
1185 if (id3 != -1) table[2][id3]->setActive(false);
1186
1187 if (val == -1) { // Means: no more mapping...
1188 // So stay all deactivated...
1189 } else {
1190 int id4 = getZoneIndex(table, p, val);
1191 if (id4 != -1) {
1192 // Reactivate the one we edit...
1193 table[val][id4]->setMappingValues(curve, amin, amid, amax, fMin[p], fInit[p], fMax[p]);
1194 table[val][id4]->setActive(true);
1195 } else {
1196 // Allocate a new CurveZoneControl which is 'active' by default
1197 FAUSTFLOAT* zone = fZone[p];
1198 table[val].push_back(new CurveZoneControl(zone, curve, amin, amid, amax, fMin[p], fInit[p], fMax[p]));
1199 }
1200 }
1201 }
1202
1203 void getConverter(std::vector<ZoneControl*>* table, int p, int& val, int& curve, double& amin, double& amid, double& amax)
1204 {
1205 int id1 = getZoneIndex(table, p, 0);
1206 int id2 = getZoneIndex(table, p, 1);
1207 int id3 = getZoneIndex(table, p, 2);
1208
1209 if (id1 != -1) {
1210 val = 0;
1211 curve = table[val][id1]->getCurve();
1212 table[val][id1]->getMappingValues(amin, amid, amax);
1213 } else if (id2 != -1) {
1214 val = 1;
1215 curve = table[val][id2]->getCurve();
1216 table[val][id2]->getMappingValues(amin, amid, amax);
1217 } else if (id3 != -1) {
1218 val = 2;
1219 curve = table[val][id3]->getCurve();
1220 table[val][id3]->getMappingValues(amin, amid, amax);
1221 } else {
1222 val = -1; // No mapping
1223 curve = 0;
1224 amin = -100.;
1225 amid = 0.;
1226 amax = 100.;
1227 }
1228 }
1229
1230 public:
1231
1232 enum Type { kAcc = 0, kGyr = 1, kNoType };
1233
1234 APIUI() : fNumParameters(0), fHasScreenControl(false), fRedReader(0), fGreenReader(0), fBlueReader(0), fCurrentScale(kLin)
1235 {}
1236
1237 virtual ~APIUI()
1238 {
1239 for (auto& it : fConversion) delete it;
1240 for (int i = 0; i < 3; i++) {
1241 for (auto& it : fAcc[i]) delete it;
1242 for (auto& it : fGyr[i]) delete it;
1243 }
1244 delete fRedReader;
1245 delete fGreenReader;
1246 delete fBlueReader;
1247 }
1248
1249 // -- widget's layouts
1250
1251 virtual void openTabBox(const char* label) { pushLabel(label); }
1252 virtual void openHorizontalBox(const char* label) { pushLabel(label); }
1253 virtual void openVerticalBox(const char* label) { pushLabel(label); }
1254 virtual void closeBox() { popLabel(); }
1255
1256 // -- active widgets
1257
1258 virtual void addButton(const char* label, FAUSTFLOAT* zone)
1259 {
1260 addParameter(label, zone, 0, 0, 1, 1, kButton);
1261 }
1262
1263 virtual void addCheckButton(const char* label, FAUSTFLOAT* zone)
1264 {
1265 addParameter(label, zone, 0, 0, 1, 1, kCheckButton);
1266 }
1267
1268 virtual void addVerticalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step)
1269 {
1270 addParameter(label, zone, init, min, max, step, kVSlider);
1271 }
1272
1273 virtual void addHorizontalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step)
1274 {
1275 addParameter(label, zone, init, min, max, step, kHSlider);
1276 }
1277
1278 virtual void addNumEntry(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step)
1279 {
1280 addParameter(label, zone, init, min, max, step, kNumEntry);
1281 }
1282
1283 // -- passive widgets
1284
1285 virtual void addHorizontalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max)
1286 {
1287 addParameter(label, zone, min, min, max, (max-min)/1000.0, kHBargraph);
1288 }
1289
1290 virtual void addVerticalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max)
1291 {
1292 addParameter(label, zone, min, min, max, (max-min)/1000.0, kVBargraph);
1293 }
1294
1295 // -- soundfiles
1296
1297 virtual void addSoundfile(const char* label, const char* filename, Soundfile** sf_zone) {}
1298
1299 // -- metadata declarations
1300
1301 virtual void declare(FAUSTFLOAT* zone, const char* key, const char* val)
1302 {
1303 // Keep metadata
1304 fCurrentMetadata[key] = val;
1305
1306 if (strcmp(key, "scale") == 0) {
1307 if (strcmp(val, "log") == 0) {
1308 fCurrentScale = kLog;
1309 } else if (strcmp(val, "exp") == 0) {
1310 fCurrentScale = kExp;
1311 } else {
1312 fCurrentScale = kLin;
1313 }
1314 } else if (strcmp(key, "unit") == 0) {
1315 fCurrentUnit = val;
1316 } else if (strcmp(key, "acc") == 0) {
1317 fCurrentAcc = val;
1318 } else if (strcmp(key, "gyr") == 0) {
1319 fCurrentGyr = val;
1320 } else if (strcmp(key, "screencolor") == 0) {
1321 fCurrentColor = val; // val = "red", "green", "blue" or "white"
1322 } else if (strcmp(key, "tooltip") == 0) {
1323 fCurrentTooltip = val;
1324 }
1325 }
1326
1327 virtual void declare(const char* key, const char* val)
1328 {}
1329
1330 //-------------------------------------------------------------------------------
1331 // Simple API part
1332 //-------------------------------------------------------------------------------
1333 int getParamsCount() { return fNumParameters; }
1334 int getParamIndex(const char* path)
1335 {
1336 if (fPathMap.find(path) != fPathMap.end()) {
1337 return fPathMap[path];
1338 } else if (fLabelMap.find(path) != fLabelMap.end()) {
1339 return fLabelMap[path];
1340 } else {
1341 return -1;
1342 }
1343 }
1344 const char* getParamAddress(int p) { return fPaths[p].c_str(); }
1345 const char* getParamLabel(int p) { return fLabels[p].c_str(); }
1346 std::map<const char*, const char*> getMetadata(int p)
1347 {
1348 std::map<const char*, const char*> res;
1349 std::map<std::string, std::string> metadata = fMetaData[p];
1350 for (auto it : metadata) {
1351 res[it.first.c_str()] = it.second.c_str();
1352 }
1353 return res;
1354 }
1355
1356 const char* getMetadata(int p, const char* key)
1357 {
1358 return (fMetaData[p].find(key) != fMetaData[p].end()) ? fMetaData[p][key].c_str() : "";
1359 }
1360 FAUSTFLOAT getParamMin(int p) { return fMin[p]; }
1361 FAUSTFLOAT getParamMax(int p) { return fMax[p]; }
1362 FAUSTFLOAT getParamStep(int p) { return fStep[p]; }
1363 FAUSTFLOAT getParamInit(int p) { return fInit[p]; }
1364
1365 FAUSTFLOAT* getParamZone(int p) { return fZone[p]; }
1366 FAUSTFLOAT getParamValue(int p) { return *fZone[p]; }
1367 void setParamValue(int p, FAUSTFLOAT v) { *fZone[p] = v; }
1368
1369 double getParamRatio(int p) { return fConversion[p]->faust2ui(*fZone[p]); }
1370 void setParamRatio(int p, double r) { *fZone[p] = fConversion[p]->ui2faust(r); }
1371
1372 double value2ratio(int p, double r) { return fConversion[p]->faust2ui(r); }
1373 double ratio2value(int p, double r) { return fConversion[p]->ui2faust(r); }
1374
1375 /**
1376 * Return the control type (kAcc, kGyr, or -1) for a given parameter
1377 *
1378 * @param p - the UI parameter index
1379 *
1380 * @return the type
1381 */
1382 Type getParamType(int p)
1383 {
1384 if (p >= 0) {
1385 if (getZoneIndex(fAcc, p, 0) != -1
1386 || getZoneIndex(fAcc, p, 1) != -1
1387 || getZoneIndex(fAcc, p, 2) != -1) {
1388 return kAcc;
1389 } else if (getZoneIndex(fGyr, p, 0) != -1
1390 || getZoneIndex(fGyr, p, 1) != -1
1391 || getZoneIndex(fGyr, p, 2) != -1) {
1392 return kGyr;
1393 }
1394 }
1395 return kNoType;
1396 }
1397
1398 /**
1399 * Return the Item type (kButton = 0, kCheckButton, kVSlider, kHSlider, kNumEntry, kHBargraph, kVBargraph) for a given parameter
1400 *
1401 * @param p - the UI parameter index
1402 *
1403 * @return the Item type
1404 */
1405 ItemType getParamItemType(int p)
1406 {
1407 return fItemType[p];
1408 }
1409
1410 /**
1411 * Set a new value coming from an accelerometer, propagate it to all relevant FAUSTFLOAT* zones.
1412 *
1413 * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer
1414 * @param value - the new value
1415 *
1416 */
1417 void propagateAcc(int acc, double value)
1418 {
1419 for (size_t i = 0; i < fAcc[acc].size(); i++) {
1420 fAcc[acc][i]->update(value);
1421 }
1422 }
1423
1424 /**
1425 * Used to edit accelerometer curves and mapping. Set curve and related mapping for a given UI parameter.
1426 *
1427 * @param p - the UI parameter index
1428 * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer (-1 means "no mapping")
1429 * @param curve - between 0 and 3
1430 * @param amin - mapping 'min' point
1431 * @param amid - mapping 'middle' point
1432 * @param amax - mapping 'max' point
1433 *
1434 */
1435 void setAccConverter(int p, int acc, int curve, double amin, double amid, double amax)
1436 {
1437 setConverter(fAcc, p, acc, curve, amin, amid, amax);
1438 }
1439
1440 /**
1441 * Used to edit gyroscope curves and mapping. Set curve and related mapping for a given UI parameter.
1442 *
1443 * @param p - the UI parameter index
1444 * @param acc - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope (-1 means "no mapping")
1445 * @param curve - between 0 and 3
1446 * @param amin - mapping 'min' point
1447 * @param amid - mapping 'middle' point
1448 * @param amax - mapping 'max' point
1449 *
1450 */
1451 void setGyrConverter(int p, int gyr, int curve, double amin, double amid, double amax)
1452 {
1453 setConverter(fGyr, p, gyr, curve, amin, amid, amax);
1454 }
1455
1456 /**
1457 * Used to edit accelerometer curves and mapping. Get curve and related mapping for a given UI parameter.
1458 *
1459 * @param p - the UI parameter index
1460 * @param acc - the acc value to be retrieved (-1 means "no mapping")
1461 * @param curve - the curve value to be retrieved
1462 * @param amin - the amin value to be retrieved
1463 * @param amid - the amid value to be retrieved
1464 * @param amax - the amax value to be retrieved
1465 *
1466 */
1467 void getAccConverter(int p, int& acc, int& curve, double& amin, double& amid, double& amax)
1468 {
1469 getConverter(fAcc, p, acc, curve, amin, amid, amax);
1470 }
1471
1472 /**
1473 * Used to edit gyroscope curves and mapping. Get curve and related mapping for a given UI parameter.
1474 *
1475 * @param p - the UI parameter index
1476 * @param gyr - the gyr value to be retrieved (-1 means "no mapping")
1477 * @param curve - the curve value to be retrieved
1478 * @param amin - the amin value to be retrieved
1479 * @param amid - the amid value to be retrieved
1480 * @param amax - the amax value to be retrieved
1481 *
1482 */
1483 void getGyrConverter(int p, int& gyr, int& curve, double& amin, double& amid, double& amax)
1484 {
1485 getConverter(fGyr, p, gyr, curve, amin, amid, amax);
1486 }
1487
1488 /**
1489 * Set a new value coming from an gyroscope, propagate it to all relevant FAUSTFLOAT* zones.
1490 *
1491 * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope
1492 * @param value - the new value
1493 *
1494 */
1495 void propagateGyr(int gyr, double value)
1496 {
1497 for (size_t i = 0; i < fGyr[gyr].size(); i++) {
1498 fGyr[gyr][i]->update(value);
1499 }
1500 }
1501
1502 /**
1503 * Get the number of FAUSTFLOAT* zones controlled with the accelerometer
1504 *
1505 * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer
1506 * @return the number of zones
1507 *
1508 */
1509 int getAccCount(int acc)
1510 {
1511 return (acc >= 0 && acc < 3) ? int(fAcc[acc].size()) : 0;
1512 }
1513
1514 /**
1515 * Get the number of FAUSTFLOAT* zones controlled with the gyroscope
1516 *
1517 * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope
1518 * @param the number of zones
1519 *
1520 */
1521 int getGyrCount(int gyr)
1522 {
1523 return (gyr >= 0 && gyr < 3) ? int(fGyr[gyr].size()) : 0;
1524 }
1525
1526 // getScreenColor() : -1 means no screen color control (no screencolor metadata found)
1527 // otherwise return 0x00RRGGBB a ready to use color
1528 int getScreenColor()
1529 {
1530 if (fHasScreenControl) {
1531 int r = (fRedReader) ? fRedReader->getValue() : 0;
1532 int g = (fGreenReader) ? fGreenReader->getValue() : 0;
1533 int b = (fBlueReader) ? fBlueReader->getValue() : 0;
1534 return (r<<16) | (g<<8) | b;
1535 } else {
1536 return -1;
1537 }
1538 }
1539
1540 };
1541
1542 #endif
1543 /************************** END APIUI.h **************************/
1544
1545 // NOTE: "faust -scn name" changes the last line above to
1546 // #include <faust/name/name.h>
1547
1548 //----------------------------------------------------------------------------
1549 // FAUST Generated Code
1550 //----------------------------------------------------------------------------
1551
1552
1553 #ifndef FAUSTFLOAT
1554 #define FAUSTFLOAT float
1555 #endif
1556
1557 #include <algorithm>
1558 #include <cmath>
1559 #include <math.h>
1560
1561
1562 #ifndef FAUSTCLASS
1563 #define FAUSTCLASS freeverbmonodsp
1564 #endif
1565
1566 #ifdef __APPLE__
1567 #define exp10f __exp10f
1568 #define exp10 __exp10
1569 #endif
1570
1571 class freeverbmonodsp : public dsp {
1572
1573 private:
1574
1575 FAUSTFLOAT fVslider0;
1576 int fSampleRate;
1577 float fConst0;
1578 float fConst1;
1579 FAUSTFLOAT fVslider1;
1580 float fConst2;
1581 FAUSTFLOAT fVslider2;
1582 float fRec9[2];
1583 int IOTA;
1584 float fVec0[8192];
1585 int iConst3;
1586 float fConst4;
1587 FAUSTFLOAT fVslider3;
1588 float fRec8[2];
1589 float fRec11[2];
1590 float fVec1[8192];
1591 int iConst5;
1592 float fRec10[2];
1593 float fRec13[2];
1594 float fVec2[8192];
1595 int iConst6;
1596 float fRec12[2];
1597 float fRec15[2];
1598 float fVec3[8192];
1599 int iConst7;
1600 float fRec14[2];
1601 float fRec17[2];
1602 float fVec4[8192];
1603 int iConst8;
1604 float fRec16[2];
1605 float fRec19[2];
1606 float fVec5[8192];
1607 int iConst9;
1608 float fRec18[2];
1609 float fRec21[2];
1610 float fVec6[8192];
1611 int iConst10;
1612 float fRec20[2];
1613 float fRec23[2];
1614 float fVec7[8192];
1615 int iConst11;
1616 float fRec22[2];
1617 float fVec8[2048];
1618 int iConst12;
1619 float fRec6[2];
1620 float fVec9[2048];
1621 int iConst13;
1622 float fRec4[2];
1623 float fVec10[2048];
1624 int iConst14;
1625 float fRec2[2];
1626 float fVec11[2048];
1627 int iConst15;
1628 float fRec0[2];
1629 float fRec33[2];
1630 float fVec12[8192];
1631 float fRec32[2];
1632 float fRec35[2];
1633 float fVec13[8192];
1634 float fRec34[2];
1635 float fRec37[2];
1636 float fVec14[8192];
1637 float fRec36[2];
1638 float fRec39[2];
1639 float fVec15[8192];
1640 float fRec38[2];
1641 float fRec41[2];
1642 float fVec16[8192];
1643 float fRec40[2];
1644 float fRec43[2];
1645 float fVec17[8192];
1646 float fRec42[2];
1647 float fRec45[2];
1648 float fVec18[8192];
1649 float fRec44[2];
1650 float fRec47[2];
1651 float fVec19[8192];
1652 float fRec46[2];
1653 float fVec20[2048];
1654 int iConst16;
1655 float fRec30[2];
1656 float fVec21[2048];
1657 int iConst17;
1658 float fRec28[2];
1659 float fVec22[2048];
1660 int iConst18;
1661 float fRec26[2];
1662 float fVec23[1024];
1663 int iConst19;
1664 float fRec24[2];
1665
1666 public:
1667
1668 void metadata(Meta* m) {
1669 m->declare("delays.lib/name", "Faust Delay Library");
1670 m->declare("delays.lib/version", "0.1");
1671 m->declare("filename", "freeverbmonodsp.dsp");
1672 m->declare("filters.lib/allpass_comb:author", "Julius O. Smith III");
1673 m->declare("filters.lib/allpass_comb:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
1674 m->declare("filters.lib/allpass_comb:license", "MIT-style STK-4.3 license");
1675 m->declare("filters.lib/lowpass0_highpass1", "MIT-style STK-4.3 license");
1676 m->declare("filters.lib/name", "Faust Filters Library");
1677 m->declare("freeverbdsp.dsp/author", "Romain Michon");
1678 m->declare("freeverbdsp.dsp/description", "Freeverb implementation in Faust, from the Faust Library's dm.freeverb_demo in demos.lib");
1679 m->declare("freeverbdsp.dsp/license", "LGPL");
1680 m->declare("freeverbdsp.dsp/name", "freeverb");
1681 m->declare("freeverbdsp.dsp/version", "0.0");
1682 m->declare("maths.lib/author", "GRAME");
1683 m->declare("maths.lib/copyright", "GRAME");
1684 m->declare("maths.lib/license", "LGPL with exception");
1685 m->declare("maths.lib/name", "Faust Math Library");
1686 m->declare("maths.lib/version", "2.3");
1687 m->declare("name", "freeverbmonodsp");
1688 m->declare("platform.lib/name", "Generic Platform Library");
1689 m->declare("platform.lib/version", "0.1");
1690 m->declare("reverbs.lib/name", "Faust Reverb Library");
1691 m->declare("reverbs.lib/version", "0.0");
1692 }
1693
1694 virtual int getNumInputs() {
1695 return 1;
1696 }
1697 virtual int getNumOutputs() {
1698 return 1;
1699 }
1700 virtual int getInputRate(int channel) {
1701 int rate;
1702 switch ((channel)) {
1703 case 0: {
1704 rate = 1;
1705 break;
1706 }
1707 default: {
1708 rate = -1;
1709 break;
1710 }
1711 }
1712 return rate;
1713 }
1714 virtual int getOutputRate(int channel) {
1715 int rate;
1716 switch ((channel)) {
1717 case 0: {
1718 rate = 1;
1719 break;
1720 }
1721 default: {
1722 rate = -1;
1723 break;
1724 }
1725 }
1726 return rate;
1727 }
1728
1729 static void classInit(int sample_rate) {
1730 }
1731
1732 virtual void instanceConstants(int sample_rate) {
1733 fSampleRate = sample_rate;
1734 fConst0 = std::min<float>(192000.0f, std::max<float>(1.0f, float(fSampleRate)));
1735 fConst1 = (12348.0f / fConst0);
1736 fConst2 = (17640.0f / fConst0);
1737 iConst3 = int((0.0253061224f * fConst0));
1738 fConst4 = (0.00104308384f * fConst0);
1739 iConst5 = int((0.0269387756f * fConst0));
1740 iConst6 = int((0.0289569162f * fConst0));
1741 iConst7 = int((0.0307482984f * fConst0));
1742 iConst8 = int((0.0322448984f * fConst0));
1743 iConst9 = int((0.033809524f * fConst0));
1744 iConst10 = int((0.0353061222f * fConst0));
1745 iConst11 = int((0.0366666652f * fConst0));
1746 iConst12 = int((0.0126077095f * fConst0));
1747 iConst13 = int((0.00999999978f * fConst0));
1748 iConst14 = int((0.00773242628f * fConst0));
1749 iConst15 = int((0.00510204071f * fConst0));
1750 iConst16 = std::min<int>(1024, std::max<int>(0, (iConst12 + -1)));
1751 iConst17 = std::min<int>(1024, std::max<int>(0, (iConst13 + -1)));
1752 iConst18 = std::min<int>(1024, std::max<int>(0, (iConst14 + -1)));
1753 iConst19 = std::min<int>(1024, std::max<int>(0, (iConst15 + -1)));
1754 }
1755
1756 virtual void instanceResetUserInterface() {
1757 fVslider0 = FAUSTFLOAT(0.10000000000000001f);
1758 fVslider1 = FAUSTFLOAT(0.10000000000000001f);
1759 fVslider2 = FAUSTFLOAT(0.5f);
1760 fVslider3 = FAUSTFLOAT(0.5f);
1761 }
1762
1763 virtual void instanceClear() {
1764 for (int l0 = 0; (l0 < 2); l0 = (l0 + 1)) {
1765 fRec9[l0] = 0.0f;
1766 }
1767 IOTA = 0;
1768 for (int l1 = 0; (l1 < 8192); l1 = (l1 + 1)) {
1769 fVec0[l1] = 0.0f;
1770 }
1771 for (int l2 = 0; (l2 < 2); l2 = (l2 + 1)) {
1772 fRec8[l2] = 0.0f;
1773 }
1774 for (int l3 = 0; (l3 < 2); l3 = (l3 + 1)) {
1775 fRec11[l3] = 0.0f;
1776 }
1777 for (int l4 = 0; (l4 < 8192); l4 = (l4 + 1)) {
1778 fVec1[l4] = 0.0f;
1779 }
1780 for (int l5 = 0; (l5 < 2); l5 = (l5 + 1)) {
1781 fRec10[l5] = 0.0f;
1782 }
1783 for (int l6 = 0; (l6 < 2); l6 = (l6 + 1)) {
1784 fRec13[l6] = 0.0f;
1785 }
1786 for (int l7 = 0; (l7 < 8192); l7 = (l7 + 1)) {
1787 fVec2[l7] = 0.0f;
1788 }
1789 for (int l8 = 0; (l8 < 2); l8 = (l8 + 1)) {
1790 fRec12[l8] = 0.0f;
1791 }
1792 for (int l9 = 0; (l9 < 2); l9 = (l9 + 1)) {
1793 fRec15[l9] = 0.0f;
1794 }
1795 for (int l10 = 0; (l10 < 8192); l10 = (l10 + 1)) {
1796 fVec3[l10] = 0.0f;
1797 }
1798 for (int l11 = 0; (l11 < 2); l11 = (l11 + 1)) {
1799 fRec14[l11] = 0.0f;
1800 }
1801 for (int l12 = 0; (l12 < 2); l12 = (l12 + 1)) {
1802 fRec17[l12] = 0.0f;
1803 }
1804 for (int l13 = 0; (l13 < 8192); l13 = (l13 + 1)) {
1805 fVec4[l13] = 0.0f;
1806 }
1807 for (int l14 = 0; (l14 < 2); l14 = (l14 + 1)) {
1808 fRec16[l14] = 0.0f;
1809 }
1810 for (int l15 = 0; (l15 < 2); l15 = (l15 + 1)) {
1811 fRec19[l15] = 0.0f;
1812 }
1813 for (int l16 = 0; (l16 < 8192); l16 = (l16 + 1)) {
1814 fVec5[l16] = 0.0f;
1815 }
1816 for (int l17 = 0; (l17 < 2); l17 = (l17 + 1)) {
1817 fRec18[l17] = 0.0f;
1818 }
1819 for (int l18 = 0; (l18 < 2); l18 = (l18 + 1)) {
1820 fRec21[l18] = 0.0f;
1821 }
1822 for (int l19 = 0; (l19 < 8192); l19 = (l19 + 1)) {
1823 fVec6[l19] = 0.0f;
1824 }
1825 for (int l20 = 0; (l20 < 2); l20 = (l20 + 1)) {
1826 fRec20[l20] = 0.0f;
1827 }
1828 for (int l21 = 0; (l21 < 2); l21 = (l21 + 1)) {
1829 fRec23[l21] = 0.0f;
1830 }
1831 for (int l22 = 0; (l22 < 8192); l22 = (l22 + 1)) {
1832 fVec7[l22] = 0.0f;
1833 }
1834 for (int l23 = 0; (l23 < 2); l23 = (l23 + 1)) {
1835 fRec22[l23] = 0.0f;
1836 }
1837 for (int l24 = 0; (l24 < 2048); l24 = (l24 + 1)) {
1838 fVec8[l24] = 0.0f;
1839 }
1840 for (int l25 = 0; (l25 < 2); l25 = (l25 + 1)) {
1841 fRec6[l25] = 0.0f;
1842 }
1843 for (int l26 = 0; (l26 < 2048); l26 = (l26 + 1)) {
1844 fVec9[l26] = 0.0f;
1845 }
1846 for (int l27 = 0; (l27 < 2); l27 = (l27 + 1)) {
1847 fRec4[l27] = 0.0f;
1848 }
1849 for (int l28 = 0; (l28 < 2048); l28 = (l28 + 1)) {
1850 fVec10[l28] = 0.0f;
1851 }
1852 for (int l29 = 0; (l29 < 2); l29 = (l29 + 1)) {
1853 fRec2[l29] = 0.0f;
1854 }
1855 for (int l30 = 0; (l30 < 2048); l30 = (l30 + 1)) {
1856 fVec11[l30] = 0.0f;
1857 }
1858 for (int l31 = 0; (l31 < 2); l31 = (l31 + 1)) {
1859 fRec0[l31] = 0.0f;
1860 }
1861 for (int l32 = 0; (l32 < 2); l32 = (l32 + 1)) {
1862 fRec33[l32] = 0.0f;
1863 }
1864 for (int l33 = 0; (l33 < 8192); l33 = (l33 + 1)) {
1865 fVec12[l33] = 0.0f;
1866 }
1867 for (int l34 = 0; (l34 < 2); l34 = (l34 + 1)) {
1868 fRec32[l34] = 0.0f;
1869 }
1870 for (int l35 = 0; (l35 < 2); l35 = (l35 + 1)) {
1871 fRec35[l35] = 0.0f;
1872 }
1873 for (int l36 = 0; (l36 < 8192); l36 = (l36 + 1)) {
1874 fVec13[l36] = 0.0f;
1875 }
1876 for (int l37 = 0; (l37 < 2); l37 = (l37 + 1)) {
1877 fRec34[l37] = 0.0f;
1878 }
1879 for (int l38 = 0; (l38 < 2); l38 = (l38 + 1)) {
1880 fRec37[l38] = 0.0f;
1881 }
1882 for (int l39 = 0; (l39 < 8192); l39 = (l39 + 1)) {
1883 fVec14[l39] = 0.0f;
1884 }
1885 for (int l40 = 0; (l40 < 2); l40 = (l40 + 1)) {
1886 fRec36[l40] = 0.0f;
1887 }
1888 for (int l41 = 0; (l41 < 2); l41 = (l41 + 1)) {
1889 fRec39[l41] = 0.0f;
1890 }
1891 for (int l42 = 0; (l42 < 8192); l42 = (l42 + 1)) {
1892 fVec15[l42] = 0.0f;
1893 }
1894 for (int l43 = 0; (l43 < 2); l43 = (l43 + 1)) {
1895 fRec38[l43] = 0.0f;
1896 }
1897 for (int l44 = 0; (l44 < 2); l44 = (l44 + 1)) {
1898 fRec41[l44] = 0.0f;
1899 }
1900 for (int l45 = 0; (l45 < 8192); l45 = (l45 + 1)) {
1901 fVec16[l45] = 0.0f;
1902 }
1903 for (int l46 = 0; (l46 < 2); l46 = (l46 + 1)) {
1904 fRec40[l46] = 0.0f;
1905 }
1906 for (int l47 = 0; (l47 < 2); l47 = (l47 + 1)) {
1907 fRec43[l47] = 0.0f;
1908 }
1909 for (int l48 = 0; (l48 < 8192); l48 = (l48 + 1)) {
1910 fVec17[l48] = 0.0f;
1911 }
1912 for (int l49 = 0; (l49 < 2); l49 = (l49 + 1)) {
1913 fRec42[l49] = 0.0f;
1914 }
1915 for (int l50 = 0; (l50 < 2); l50 = (l50 + 1)) {
1916 fRec45[l50] = 0.0f;
1917 }
1918 for (int l51 = 0; (l51 < 8192); l51 = (l51 + 1)) {
1919 fVec18[l51] = 0.0f;
1920 }
1921 for (int l52 = 0; (l52 < 2); l52 = (l52 + 1)) {
1922 fRec44[l52] = 0.0f;
1923 }
1924 for (int l53 = 0; (l53 < 2); l53 = (l53 + 1)) {
1925 fRec47[l53] = 0.0f;
1926 }
1927 for (int l54 = 0; (l54 < 8192); l54 = (l54 + 1)) {
1928 fVec19[l54] = 0.0f;
1929 }
1930 for (int l55 = 0; (l55 < 2); l55 = (l55 + 1)) {
1931 fRec46[l55] = 0.0f;
1932 }
1933 for (int l56 = 0; (l56 < 2048); l56 = (l56 + 1)) {
1934 fVec20[l56] = 0.0f;
1935 }
1936 for (int l57 = 0; (l57 < 2); l57 = (l57 + 1)) {
1937 fRec30[l57] = 0.0f;
1938 }
1939 for (int l58 = 0; (l58 < 2048); l58 = (l58 + 1)) {
1940 fVec21[l58] = 0.0f;
1941 }
1942 for (int l59 = 0; (l59 < 2); l59 = (l59 + 1)) {
1943 fRec28[l59] = 0.0f;
1944 }
1945 for (int l60 = 0; (l60 < 2048); l60 = (l60 + 1)) {
1946 fVec22[l60] = 0.0f;
1947 }
1948 for (int l61 = 0; (l61 < 2); l61 = (l61 + 1)) {
1949 fRec26[l61] = 0.0f;
1950 }
1951 for (int l62 = 0; (l62 < 1024); l62 = (l62 + 1)) {
1952 fVec23[l62] = 0.0f;
1953 }
1954 for (int l63 = 0; (l63 < 2); l63 = (l63 + 1)) {
1955 fRec24[l63] = 0.0f;
1956 }
1957 }
1958
1959 virtual void init(int sample_rate) {
1960 classInit(sample_rate);
1961 instanceInit(sample_rate);
1962 }
1963 virtual void instanceInit(int sample_rate) {
1964 instanceConstants(sample_rate);
1965 instanceResetUserInterface();
1966 instanceClear();
1967 }
1968
1969 virtual freeverbmonodsp* clone() {
1970 return new freeverbmonodsp();
1971 }
1972
1973 virtual int getSampleRate() {
1974 return fSampleRate;
1975 }
1976
1977 virtual void buildUserInterface(UI* ui_interface) {
1978 ui_interface->openHorizontalBox("Freeverb");
1979 ui_interface->declare(0, "0", "");
1980 ui_interface->openVerticalBox("0x00");
1981 ui_interface->declare(&fVslider2, "0", "");
1982 ui_interface->declare(&fVslider2, "style", "knob");
1983 ui_interface->declare(&fVslider2, "tooltip", "Somehow control the density of the reverb.");
1984 ui_interface->addVerticalSlider("Damp", &fVslider2, 0.5f, 0.0f, 1.0f, 0.0250000004f);
1985 ui_interface->declare(&fVslider1, "1", "");
1986 ui_interface->declare(&fVslider1, "style", "knob");
1987 ui_interface->declare(&fVslider1, "tooltip", "The room size between 0 and 1 with 1 for the largest room.");
1988 ui_interface->addVerticalSlider("RoomSize", &fVslider1, 0.100000001f, 0.0f, 1.0f, 0.0250000004f);
1989 ui_interface->declare(&fVslider3, "2", "");
1990 ui_interface->declare(&fVslider3, "style", "knob");
1991 ui_interface->declare(&fVslider3, "tooltip", "Spatial spread between 0 and 1 with 1 for maximum spread.");
1992 ui_interface->addVerticalSlider("Stereo Spread", &fVslider3, 0.5f, 0.0f, 1.0f, 0.00999999978f);
1993 ui_interface->closeBox();
1994 ui_interface->declare(&fVslider0, "1", "");
1995 ui_interface->declare(&fVslider0, "tooltip", "The amount of reverb applied to the signal between 0 and 1 with 1 for the maximum amount of reverb.");
1996 ui_interface->addVerticalSlider("Wet", &fVslider0, 0.100000001f, 0.0f, 1.0f, 0.0250000004f);
1997 ui_interface->closeBox();
1998 }
1999
2000 virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) {
2001 FAUSTFLOAT* input0 = inputs[0];
2002 FAUSTFLOAT* output0 = outputs[0];
2003 float fSlow0 = float(fVslider0);
2004 float fSlow1 = (0.200000003f * fSlow0);
2005 float fSlow2 = ((fConst1 * float(fVslider1)) + 0.699999988f);
2006 float fSlow3 = (fConst2 * float(fVslider2));
2007 float fSlow4 = (1.0f - fSlow3);
2008 int iSlow5 = int((fConst4 * float(fVslider3)));
2009 int iSlow6 = (iConst3 + iSlow5);
2010 int iSlow7 = (iConst5 + iSlow5);
2011 int iSlow8 = (iConst6 + iSlow5);
2012 int iSlow9 = (iConst7 + iSlow5);
2013 int iSlow10 = (iConst8 + iSlow5);
2014 int iSlow11 = (iConst9 + iSlow5);
2015 int iSlow12 = (iConst10 + iSlow5);
2016 int iSlow13 = (iConst11 + iSlow5);
2017 int iSlow14 = (iSlow5 + -1);
2018 int iSlow15 = std::min<int>(1024, std::max<int>(0, (iConst12 + iSlow14)));
2019 int iSlow16 = std::min<int>(1024, std::max<int>(0, (iConst13 + iSlow14)));
2020 int iSlow17 = std::min<int>(1024, std::max<int>(0, (iConst14 + iSlow14)));
2021 int iSlow18 = std::min<int>(1024, std::max<int>(0, (iConst15 + iSlow14)));
2022 float fSlow19 = (2.0f * (1.0f - fSlow0));
2023 for (int i = 0; (i < count); i = (i + 1)) {
2024 float fTemp0 = float(input0[i]);
2025 float fTemp1 = (fSlow1 * fTemp0);
2026 fRec9[0] = ((fSlow3 * fRec9[1]) + (fSlow4 * fRec8[1]));
2027 fVec0[(IOTA & 8191)] = (fTemp1 + (fSlow2 * fRec9[0]));
2028 fRec8[0] = fVec0[((IOTA - iSlow6) & 8191)];
2029 fRec11[0] = ((fSlow3 * fRec11[1]) + (fSlow4 * fRec10[1]));
2030 fVec1[(IOTA & 8191)] = (fTemp1 + (fSlow2 * fRec11[0]));
2031 fRec10[0] = fVec1[((IOTA - iSlow7) & 8191)];
2032 fRec13[0] = ((fSlow3 * fRec13[1]) + (fSlow4 * fRec12[1]));
2033 fVec2[(IOTA & 8191)] = (fTemp1 + (fSlow2 * fRec13[0]));
2034 fRec12[0] = fVec2[((IOTA - iSlow8) & 8191)];
2035 fRec15[0] = ((fSlow3 * fRec15[1]) + (fSlow4 * fRec14[1]));
2036 fVec3[(IOTA & 8191)] = (fTemp1 + (fSlow2 * fRec15[0]));
2037 fRec14[0] = fVec3[((IOTA - iSlow9) & 8191)];
2038 fRec17[0] = ((fSlow3 * fRec17[1]) + (fSlow4 * fRec16[1]));
2039 fVec4[(IOTA & 8191)] = (fTemp1 + (fSlow2 * fRec17[0]));
2040 fRec16[0] = fVec4[((IOTA - iSlow10) & 8191)];
2041 fRec19[0] = ((fSlow3 * fRec19[1]) + (fSlow4 * fRec18[1]));
2042 fVec5[(IOTA & 8191)] = (fTemp1 + (fSlow2 * fRec19[0]));
2043 fRec18[0] = fVec5[((IOTA - iSlow11) & 8191)];
2044 fRec21[0] = ((fSlow3 * fRec21[1]) + (fSlow4 * fRec20[1]));
2045 fVec6[(IOTA & 8191)] = (fTemp1 + (fSlow2 * fRec21[0]));
2046 fRec20[0] = fVec6[((IOTA - iSlow12) & 8191)];
2047 fRec23[0] = ((fSlow3 * fRec23[1]) + (fSlow4 * fRec22[1]));
2048 fVec7[(IOTA & 8191)] = (fTemp1 + (fSlow2 * fRec23[0]));
2049 fRec22[0] = fVec7[((IOTA - iSlow13) & 8191)];
2050 float fTemp2 = ((((((((fRec8[0] + fRec10[0]) + fRec12[0]) + fRec14[0]) + fRec16[0]) + fRec18[0]) + fRec20[0]) + fRec22[0]) + (0.5f * fRec6[1]));
2051 fVec8[(IOTA & 2047)] = fTemp2;
2052 fRec6[0] = fVec8[((IOTA - iSlow15) & 2047)];
2053 float fRec7 = (0.0f - (0.5f * fTemp2));
2054 float fTemp3 = (fRec6[1] + (fRec7 + (0.5f * fRec4[1])));
2055 fVec9[(IOTA & 2047)] = fTemp3;
2056 fRec4[0] = fVec9[((IOTA - iSlow16) & 2047)];
2057 float fRec5 = (0.0f - (0.5f * fTemp3));
2058 float fTemp4 = (fRec4[1] + (fRec5 + (0.5f * fRec2[1])));
2059 fVec10[(IOTA & 2047)] = fTemp4;
2060 fRec2[0] = fVec10[((IOTA - iSlow17) & 2047)];
2061 float fRec3 = (0.0f - (0.5f * fTemp4));
2062 float fTemp5 = (fRec2[1] + (fRec3 + (0.5f * fRec0[1])));
2063 fVec11[(IOTA & 2047)] = fTemp5;
2064 fRec0[0] = fVec11[((IOTA - iSlow18) & 2047)];
2065 float fRec1 = (0.0f - (0.5f * fTemp5));
2066 fRec33[0] = ((fSlow3 * fRec33[1]) + (fSlow4 * fRec32[1]));
2067 fVec12[(IOTA & 8191)] = ((fSlow2 * fRec33[0]) + fTemp1);
2068 fRec32[0] = fVec12[((IOTA - iConst3) & 8191)];
2069 fRec35[0] = ((fSlow3 * fRec35[1]) + (fSlow4 * fRec34[1]));
2070 fVec13[(IOTA & 8191)] = (fTemp1 + (fSlow2 * fRec35[0]));
2071 fRec34[0] = fVec13[((IOTA - iConst5) & 8191)];
2072 fRec37[0] = ((fSlow3 * fRec37[1]) + (fSlow4 * fRec36[1]));
2073 fVec14[(IOTA & 8191)] = (fTemp1 + (fSlow2 * fRec37[0]));
2074 fRec36[0] = fVec14[((IOTA - iConst6) & 8191)];
2075 fRec39[0] = ((fSlow3 * fRec39[1]) + (fSlow4 * fRec38[1]));
2076 fVec15[(IOTA & 8191)] = (fTemp1 + (fSlow2 * fRec39[0]));
2077 fRec38[0] = fVec15[((IOTA - iConst7) & 8191)];
2078 fRec41[0] = ((fSlow3 * fRec41[1]) + (fSlow4 * fRec40[1]));
2079 fVec16[(IOTA & 8191)] = (fTemp1 + (fSlow2 * fRec41[0]));
2080 fRec40[0] = fVec16[((IOTA - iConst8) & 8191)];
2081 fRec43[0] = ((fSlow3 * fRec43[1]) + (fSlow4 * fRec42[1]));
2082 fVec17[(IOTA & 8191)] = (fTemp1 + (fSlow2 * fRec43[0]));
2083 fRec42[0] = fVec17[((IOTA - iConst9) & 8191)];
2084 fRec45[0] = ((fSlow3 * fRec45[1]) + (fSlow4 * fRec44[1]));
2085 fVec18[(IOTA & 8191)] = (fTemp1 + (fSlow2 * fRec45[0]));
2086 fRec44[0] = fVec18[((IOTA - iConst10) & 8191)];
2087 fRec47[0] = ((fSlow3 * fRec47[1]) + (fSlow4 * fRec46[1]));
2088 fVec19[(IOTA & 8191)] = (fTemp1 + (fSlow2 * fRec47[0]));
2089 fRec46[0] = fVec19[((IOTA - iConst11) & 8191)];
2090 float fTemp6 = ((((((((fRec32[0] + fRec34[0]) + fRec36[0]) + fRec38[0]) + fRec40[0]) + fRec42[0]) + fRec44[0]) + fRec46[0]) + (0.5f * fRec30[1]));
2091 fVec20[(IOTA & 2047)] = fTemp6;
2092 fRec30[0] = fVec20[((IOTA - iConst16) & 2047)];
2093 float fRec31 = (0.0f - (0.5f * fTemp6));
2094 float fTemp7 = (fRec30[1] + (fRec31 + (0.5f * fRec28[1])));
2095 fVec21[(IOTA & 2047)] = fTemp7;
2096 fRec28[0] = fVec21[((IOTA - iConst17) & 2047)];
2097 float fRec29 = (0.0f - (0.5f * fTemp7));
2098 float fTemp8 = (fRec28[1] + (fRec29 + (0.5f * fRec26[1])));
2099 fVec22[(IOTA & 2047)] = fTemp8;
2100 fRec26[0] = fVec22[((IOTA - iConst18) & 2047)];
2101 float fRec27 = (0.0f - (0.5f * fTemp8));
2102 float fTemp9 = (fRec26[1] + (fRec27 + (0.5f * fRec24[1])));
2103 fVec23[(IOTA & 1023)] = fTemp9;
2104 fRec24[0] = fVec23[((IOTA - iConst19) & 1023)];
2105 float fRec25 = (0.0f - (0.5f * fTemp9));
2106 output0[i] = FAUSTFLOAT((fRec0[1] + ((fRec24[1] + (fRec25 + fRec1)) + (fSlow19 * fTemp0))));
2107 fRec9[1] = fRec9[0];
2108 IOTA = (IOTA + 1);
2109 fRec8[1] = fRec8[0];
2110 fRec11[1] = fRec11[0];
2111 fRec10[1] = fRec10[0];
2112 fRec13[1] = fRec13[0];
2113 fRec12[1] = fRec12[0];
2114 fRec15[1] = fRec15[0];
2115 fRec14[1] = fRec14[0];
2116 fRec17[1] = fRec17[0];
2117 fRec16[1] = fRec16[0];
2118 fRec19[1] = fRec19[0];
2119 fRec18[1] = fRec18[0];
2120 fRec21[1] = fRec21[0];
2121 fRec20[1] = fRec20[0];
2122 fRec23[1] = fRec23[0];
2123 fRec22[1] = fRec22[0];
2124 fRec6[1] = fRec6[0];
2125 fRec4[1] = fRec4[0];
2126 fRec2[1] = fRec2[0];
2127 fRec0[1] = fRec0[0];
2128 fRec33[1] = fRec33[0];
2129 fRec32[1] = fRec32[0];
2130 fRec35[1] = fRec35[0];
2131 fRec34[1] = fRec34[0];
2132 fRec37[1] = fRec37[0];
2133 fRec36[1] = fRec36[0];
2134 fRec39[1] = fRec39[0];
2135 fRec38[1] = fRec38[0];
2136 fRec41[1] = fRec41[0];
2137 fRec40[1] = fRec40[0];
2138 fRec43[1] = fRec43[0];
2139 fRec42[1] = fRec42[0];
2140 fRec45[1] = fRec45[0];
2141 fRec44[1] = fRec44[0];
2142 fRec47[1] = fRec47[0];
2143 fRec46[1] = fRec46[0];
2144 fRec30[1] = fRec30[0];
2145 fRec28[1] = fRec28[0];
2146 fRec26[1] = fRec26[0];
2147 fRec24[1] = fRec24[0];
2148 }
2149 }
2150
2151 };
2152
2153 #endif
109109
110110 DESTDIR = .
111111 QMAKE_CLEAN += -r ./jacktrip ./jacktrip_debug ./release ./debug
112 target.path = /usr/bin
112
113 # isEmpty(PREFIX) will allow path to be changed during the command line
114 # call to qmake, e.g. qmake PREFIX=/usr
115 isEmpty(PREFIX) {
116 PREFIX = /usr/local
117 }
118 target.path = $$PREFIX/bin/
113119 INSTALLS += target
114120
115121 # for plugins
119125 HEADERS += DataProtocol.h \
120126 JMess.h \
121127 JackTrip.h \
128 Effects.h \
129 Compressor.h \
130 CompressorPresets.h \
131 Limiter.h \
132 Reverb.h \
133 AudioTester.h \
122134 jacktrip_globals.h \
123135 jacktrip_types.h \
124136 JackTripThread.h \
125137 JackTripWorker.h \
126138 JackTripWorkerMessages.h \
139 JitterBuffer.h \
127140 LoopBack.h \
128141 NetKS.h \
129142 PacketHeader.h \
135148 ThreadPoolTest.h \
136149 UdpDataProtocol.h \
137150 UdpHubListener.h \
138 AudioInterface.h
151 AudioInterface.h \
152 compressordsp.h \
153 limiterdsp.h \
154 freeverbdsp.h
139155
140156 !nojack {
141157 HEADERS += JackAudioInterface.h
143159 SOURCES += DataProtocol.cpp \
144160 JMess.cpp \
145161 JackTrip.cpp \
162 Compressor.cpp \
163 Limiter.cpp \
164 Reverb.cpp \
165 AudioTester.cpp \
146166 jacktrip_globals.cpp \
147167 jacktrip_main.cpp \
148168 jacktrip_tests.cpp \
149169 JackTripThread.cpp \
150170 JackTripWorker.cpp \
171 JitterBuffer.cpp \
151172 LoopBack.cpp \
152173 PacketHeader.cpp \
153174 ProcessPlugin.cpp \
161182 SOURCES += JackAudioInterface.cpp
162183 }
163184
164 # RtAduio Input
185 # RtAudio Input
165186 win32 {
166187 INCLUDEPATH += ../externals/rtaudio-4.1.1/include
167188 DEPENDPATH += ../externals/rtaudio-4.1.1/include
150150 #ifdef __UBUNTU__
151151 priority = 95; // anything higher is silently ignored by Ubuntu 18.04
152152 #endif
153 priority = 3;
153154
154155 struct sched_param sp = { .sched_priority = priority };
155156
4343 /// \todo Add this namespace
4444 //namespace JackTrip
4545
46 const char* const gVersion = "1.2.2"; ///< JackTrip version
46 const char* const gVersion = "1.3.0"; ///< JackTrip version
4747
4848 //*******************************************************************************
4949 /// \name Default Values
125125 //@{
126126 const int gJackBitResolution = 32; ///< Audio Bit Resolution of the Jack Server
127127 const QString gJackDefaultClientName = "JackTrip";
128 const int gMaxRemoteNameLength = 64;
128129 //@}
129130
130131
3737 #include <iostream>
3838
3939 #include <QCoreApplication>
40 #include <QDebug>
40 #include <QScopedPointer>
41 #include <iostream>
42 #include <signal.h>
43 #include "jacktrip_globals.h"
44 #include "Settings.h"
45 #include "UdpHubListener.h"
4146 #include <QLoggingCategory>
4247
43 #include "JackAudioInterface.h"
44 #include "UdpDataProtocol.h"
45 #include "RingBuffer.h"
46 #include "JackTrip.h"
47 #include "Settings.h"
48 //#include "TestRingBuffer.h"
49 #include "LoopBack.h"
50 #include "PacketHeader.h"
51 //#include "JackTripThread.h"
52 #ifdef __RT_AUDIO__
53 #include "RtAudioInterface.h"
54 #endif
55 #include "jacktrip_tests.cpp"
56 #include "jacktrip_globals.h"
57
58
59 void qtMessageHandler(QtMsgType /*type*/, const QMessageLogContext& /*context*/, const QString& msg)
48 void qtMessageHandler(__attribute__((unused)) QtMsgType type, __attribute__((unused)) const QMessageLogContext &context, const QString &msg)
6049 {
6150 std::cerr << msg.toStdString() << std::endl;
6251 }
6352
64 int main(int argc, char** argv)
53 #if defined (__LINUX__) || (__MAC_OSX__)
54 static int setupUnixSignalHandler(void (*handler)(int))
55 {
56 //Setup our SIGINT handler.
57 struct sigaction sigInt;
58 sigInt.sa_handler = handler;
59 sigemptyset(&sigInt.sa_mask);
60 sigInt.sa_flags = 0;
61 sigInt.sa_flags |= SA_RESTART;
62
63 int result = 0;
64 if (sigaction(SIGINT, &sigInt, 0)) {
65 std::cout << "Unable to register SIGINT handler" << std::endl;
66 result |= 1;
67 }
68 if (sigaction(SIGTERM, &sigInt, 0)) {
69 std::cout << "Unable to register SIGTERM handler" << std::endl;
70 result |= 2;
71 }
72 return result;
73 }
74 #else
75 bool isHubServer = false;
76
77 BOOL WINAPI windowsCtrlHandler(DWORD fdwCtrlType)
78 {
79 switch (fdwCtrlType) {
80 case CTRL_C_EVENT:
81 if (isHubServer) {
82 UdpHubListener::sigIntHandler(0);
83 } else {
84 JackTrip::sigIntHandler(0);
85 }
86 return true;
87 default:
88 return false;
89 }
90 }
91 #endif
92
93 int main(int argc, char *argv[])
6594 {
6695 QCoreApplication app(argc, argv);
96 QScopedPointer<JackTrip> jackTrip;
97 QScopedPointer<UdpHubListener> udpHub;
98
6799 QLoggingCategory::setFilterRules(QStringLiteral("*.debug=true"));
68100 qInstallMessageHandler(qtMessageHandler);
69101
70 bool testing = false;
71 if ( argc > 1 ) {
72 if ( !strcmp(argv[1], "test") ) {
73 testing = true;
102 try {
103 Settings settings;
104 settings.parseInput(argc, argv);
105
106 //Either start our hub server or our jacktrip process as appropriate.
107 if (settings.isHubServer()) {
108 udpHub.reset(settings.getConfiguredHubServer());
109 if (gVerboseFlag) std::cout << "Settings:startJackTrip before udphub->start" << std::endl;
110 QObject::connect(udpHub.data(), &UdpHubListener::signalStopped, &app,
111 &QCoreApplication::quit, Qt::QueuedConnection);
112 QObject::connect(udpHub.data(), &UdpHubListener::signalError, &app,
113 &QCoreApplication::quit, Qt::QueuedConnection);
114 #if defined (__LINUX__) || (__MAC_OSX__)
115 setupUnixSignalHandler(UdpHubListener::sigIntHandler);
116 #else
117 isHubServer = true;
118 SetConsoleCtrlHandler(windowsCtrlHandler, true);
119 #endif
120 udpHub->start();
121 } else {
122 jackTrip.reset(settings.getConfiguredJackTrip());
123 if (gVerboseFlag) std::cout << "Settings:startJackTrip before mJackTrip->startProcess" << std::endl;
124 QObject::connect(jackTrip.data(), &JackTrip::signalProcessesStopped, &app,
125 &QCoreApplication::quit, Qt::QueuedConnection);
126 QObject::connect(jackTrip.data(), &JackTrip::signalError, &app,
127 &QCoreApplication::quit, Qt::QueuedConnection);
128 #if defined (__LINUX__) || (__MAC_OSX__)
129 setupUnixSignalHandler(JackTrip::sigIntHandler);
130 #else
131 std::cout << SetConsoleCtrlHandler(windowsCtrlHandler, true) << std::endl;
132 #endif
133 #ifdef WAIRTOHUB // WAIR
134 jackTrip->startProcess(0); // for WAIR compatibility, ID in jack client name
135 #else
136 jackTrip->startProcess();
137 #endif // endwhere
74138 }
139
140 if (gVerboseFlag) std::cout << "step 6" << std::endl;
141 if (gVerboseFlag) std::cout << "jmain before app->exec()" << std::endl;
142 } catch (const std::exception &e) {
143 std::cerr << "ERROR:" << std::endl;
144 std::cerr << e.what() << std::endl;
145 std::cerr << "Exiting JackTrip..." << std::endl;
146 std::cerr << gPrintSeparator << std::endl;
147 return -1;
75148 }
76
77 if ( testing ) {
78 std::cout << "=========TESTING=========" << std::endl;
79 //main_tests(argc, argv); // test functions
80 JackTrip jacktrip;
81 //RtAudioInterface rtaudio(&jacktrip);
82 //rtaudio.setup();
83 //rtaudio.listAllInterfaces();
84 //rtaudio.printDeviceInfo(0);
85
86 //while (true) sleep(9999);
87 }
88 else {
89 // catch all potential exeptions
90 try
91 {
92 // Get Settings from user
93 // ----------------------
94 Settings* settings = new Settings;
95 settings->parseInput(argc, argv);
96 settings->startJackTrip();
97 }
98 catch ( const std::exception & e )
99 {
100 std::cerr << "ERROR:" << std::endl;
101 std::cerr << e.what() << std::endl;
102 std::cerr << "Exiting JackTrip..." << std::endl;
103 std::cerr << gPrintSeparator << std::endl;
104 return -1;
105 }
106 }
107 if (gVerboseFlag) std::cout << "step 6" << std::endl;
108 if (gVerboseFlag) std::cout << "jacktrip_main before app.exec()" << std::endl;
109
149
110150 return app.exec();
111151 }
0 typedef float sample_t;
1 typedef unsigned char uint8_t;
2 typedef unsigned short int uint16_t;
3 typedef unsigned int uint32_t;
4 typedef signed char int8_t;
5 typedef short int int16_t;
6 typedef int int32_t;
0 /* ------------------------------------------------------------
1 name: "limiterdsp"
2 Code generated with Faust 2.28.6 (https://faust.grame.fr)
3 Compilation options: -lang cpp -inpl -scal -ftz 0
4 ------------------------------------------------------------ */
5
6 #ifndef __limiterdsp_H__
7 #define __limiterdsp_H__
8
9 // NOTE: ANY INCLUDE-GUARD HERE MUST BE DERIVED FROM THE CLASS NAME
10 //
11 // faust2header.cpp - FAUST Architecture File
12 // This is a simple variation of matlabplot.cpp in the Faust distribution
13 // aimed at creating a simple C++ header file (.h) containing a Faust DSP.
14 // See the Makefile for how to use it.
15
16 /************************** BEGIN dsp.h **************************/
17 /************************************************************************
18 FAUST Architecture File
19 Copyright (C) 2003-2017 GRAME, Centre National de Creation Musicale
20 ---------------------------------------------------------------------
21 This Architecture section is free software; you can redistribute it
22 and/or modify it under the terms of the GNU General Public License
23 as published by the Free Software Foundation; either version 3 of
24 the License, or (at your option) any later version.
25
26 This program is distributed in the hope that it will be useful,
27 but WITHOUT ANY WARRANTY; without even the implied warranty of
28 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 GNU General Public License for more details.
30
31 You should have received a copy of the GNU General Public License
32 along with this program; If not, see <http://www.gnu.org/licenses/>.
33
34 EXCEPTION : As a special exception, you may create a larger work
35 that contains this FAUST architecture section and distribute
36 that work under terms of your choice, so long as this FAUST
37 architecture section is not modified.
38 ************************************************************************/
39
40 #ifndef __dsp__
41 #define __dsp__
42
43 #include <string>
44 #include <vector>
45
46 #ifndef FAUSTFLOAT
47 #define FAUSTFLOAT float
48 #endif
49
50 struct UI;
51 struct Meta;
52
53 /**
54 * DSP memory manager.
55 */
56
57 struct dsp_memory_manager {
58
59 virtual ~dsp_memory_manager() {}
60
61 virtual void* allocate(size_t size) = 0;
62 virtual void destroy(void* ptr) = 0;
63
64 };
65
66 /**
67 * Signal processor definition.
68 */
69
70 class dsp {
71
72 public:
73
74 dsp() {}
75 virtual ~dsp() {}
76
77 /* Return instance number of audio inputs */
78 virtual int getNumInputs() = 0;
79
80 /* Return instance number of audio outputs */
81 virtual int getNumOutputs() = 0;
82
83 /**
84 * Trigger the ui_interface parameter with instance specific calls
85 * to 'openTabBox', 'addButton', 'addVerticalSlider'... in order to build the UI.
86 *
87 * @param ui_interface - the user interface builder
88 */
89 virtual void buildUserInterface(UI* ui_interface) = 0;
90
91 /* Returns the sample rate currently used by the instance */
92 virtual int getSampleRate() = 0;
93
94 /**
95 * Global init, calls the following methods:
96 * - static class 'classInit': static tables initialization
97 * - 'instanceInit': constants and instance state initialization
98 *
99 * @param sample_rate - the sampling rate in Hertz
100 */
101 virtual void init(int sample_rate) = 0;
102
103 /**
104 * Init instance state
105 *
106 * @param sample_rate - the sampling rate in Hertz
107 */
108 virtual void instanceInit(int sample_rate) = 0;
109
110 /**
111 * Init instance constant state
112 *
113 * @param sample_rate - the sampling rate in Hertz
114 */
115 virtual void instanceConstants(int sample_rate) = 0;
116
117 /* Init default control parameters values */
118 virtual void instanceResetUserInterface() = 0;
119
120 /* Init instance state (delay lines...) */
121 virtual void instanceClear() = 0;
122
123 /**
124 * Return a clone of the instance.
125 *
126 * @return a copy of the instance on success, otherwise a null pointer.
127 */
128 virtual dsp* clone() = 0;
129
130 /**
131 * Trigger the Meta* parameter with instance specific calls to 'declare' (key, value) metadata.
132 *
133 * @param m - the Meta* meta user
134 */
135 virtual void metadata(Meta* m) = 0;
136
137 /**
138 * DSP instance computation, to be called with successive in/out audio buffers.
139 *
140 * @param count - the number of frames to compute
141 * @param inputs - the input audio buffers as an array of non-interleaved FAUSTFLOAT samples (eiher float, double or quad)
142 * @param outputs - the output audio buffers as an array of non-interleaved FAUSTFLOAT samples (eiher float, double or quad)
143 *
144 */
145 virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) = 0;
146
147 /**
148 * DSP instance computation: alternative method to be used by subclasses.
149 *
150 * @param date_usec - the timestamp in microsec given by audio driver.
151 * @param count - the number of frames to compute
152 * @param inputs - the input audio buffers as an array of non-interleaved FAUSTFLOAT samples (either float, double or quad)
153 * @param outputs - the output audio buffers as an array of non-interleaved FAUSTFLOAT samples (either float, double or quad)
154 *
155 */
156 virtual void compute(double /*date_usec*/, int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { compute(count, inputs, outputs); }
157
158 };
159
160 /**
161 * Generic DSP decorator.
162 */
163
164 class decorator_dsp : public dsp {
165
166 protected:
167
168 dsp* fDSP;
169
170 public:
171
172 decorator_dsp(dsp* dsp = nullptr):fDSP(dsp) {}
173 virtual ~decorator_dsp() { delete fDSP; }
174
175 virtual int getNumInputs() { return fDSP->getNumInputs(); }
176 virtual int getNumOutputs() { return fDSP->getNumOutputs(); }
177 virtual void buildUserInterface(UI* ui_interface) { fDSP->buildUserInterface(ui_interface); }
178 virtual int getSampleRate() { return fDSP->getSampleRate(); }
179 virtual void init(int sample_rate) { fDSP->init(sample_rate); }
180 virtual void instanceInit(int sample_rate) { fDSP->instanceInit(sample_rate); }
181 virtual void instanceConstants(int sample_rate) { fDSP->instanceConstants(sample_rate); }
182 virtual void instanceResetUserInterface() { fDSP->instanceResetUserInterface(); }
183 virtual void instanceClear() { fDSP->instanceClear(); }
184 virtual decorator_dsp* clone() { return new decorator_dsp(fDSP->clone()); }
185 virtual void metadata(Meta* m) { fDSP->metadata(m); }
186 // Beware: subclasses usually have to overload the two 'compute' methods
187 virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { fDSP->compute(count, inputs, outputs); }
188 virtual void compute(double date_usec, int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { fDSP->compute(date_usec, count, inputs, outputs); }
189
190 };
191
192 /**
193 * DSP factory class.
194 */
195
196 class dsp_factory {
197
198 protected:
199
200 // So that to force sub-classes to use deleteDSPFactory(dsp_factory* factory);
201 virtual ~dsp_factory() {}
202
203 public:
204
205 virtual std::string getName() = 0;
206 virtual std::string getSHAKey() = 0;
207 virtual std::string getDSPCode() = 0;
208 virtual std::string getCompileOptions() = 0;
209 virtual std::vector<std::string> getLibraryList() = 0;
210 virtual std::vector<std::string> getIncludePathnames() = 0;
211
212 virtual dsp* createDSPInstance() = 0;
213
214 virtual void setMemoryManager(dsp_memory_manager* manager) = 0;
215 virtual dsp_memory_manager* getMemoryManager() = 0;
216
217 };
218
219 /**
220 * On Intel set FZ (Flush to Zero) and DAZ (Denormals Are Zero)
221 * flags to avoid costly denormals.
222 */
223
224 #ifdef __SSE__
225 #include <xmmintrin.h>
226 #ifdef __SSE2__
227 #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8040)
228 #else
229 #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8000)
230 #endif
231 #else
232 #define AVOIDDENORMALS
233 #endif
234
235 #endif
236 /************************** END dsp.h **************************/
237
238 /************************** BEGIN APIUI.h **************************/
239 /************************************************************************
240 FAUST Architecture File
241 Copyright (C) 2003-2017 GRAME, Centre National de Creation Musicale
242 ---------------------------------------------------------------------
243 This Architecture section is free software; you can redistribute it
244 and/or modify it under the terms of the GNU General Public License
245 as published by the Free Software Foundation; either version 3 of
246 the License, or (at your option) any later version.
247
248 This program is distributed in the hope that it will be useful,
249 but WITHOUT ANY WARRANTY; without even the implied warranty of
250 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
251 GNU General Public License for more details.
252
253 You should have received a copy of the GNU General Public License
254 along with this program; If not, see <http://www.gnu.org/licenses/>.
255
256 EXCEPTION : As a special exception, you may create a larger work
257 that contains this FAUST architecture section and distribute
258 that work under terms of your choice, so long as this FAUST
259 architecture section is not modified.
260 ************************************************************************/
261
262 #ifndef API_UI_H
263 #define API_UI_H
264
265 #include <sstream>
266 #include <string>
267 #include <vector>
268 #include <iostream>
269 #include <map>
270
271 /************************** BEGIN meta.h **************************/
272 /************************************************************************
273 FAUST Architecture File
274 Copyright (C) 2003-2017 GRAME, Centre National de Creation Musicale
275 ---------------------------------------------------------------------
276 This Architecture section is free software; you can redistribute it
277 and/or modify it under the terms of the GNU General Public License
278 as published by the Free Software Foundation; either version 3 of
279 the License, or (at your option) any later version.
280
281 This program is distributed in the hope that it will be useful,
282 but WITHOUT ANY WARRANTY; without even the implied warranty of
283 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
284 GNU General Public License for more details.
285
286 You should have received a copy of the GNU General Public License
287 along with this program; If not, see <http://www.gnu.org/licenses/>.
288
289 EXCEPTION : As a special exception, you may create a larger work
290 that contains this FAUST architecture section and distribute
291 that work under terms of your choice, so long as this FAUST
292 architecture section is not modified.
293 ************************************************************************/
294
295 #ifndef __meta__
296 #define __meta__
297
298 struct Meta
299 {
300 virtual ~Meta() {};
301 virtual void declare(const char* key, const char* value) = 0;
302
303 };
304
305 #endif
306 /************************** END meta.h **************************/
307 /************************** BEGIN UI.h **************************/
308 /************************************************************************
309 FAUST Architecture File
310 Copyright (C) 2003-2020 GRAME, Centre National de Creation Musicale
311 ---------------------------------------------------------------------
312 This Architecture section is free software; you can redistribute it
313 and/or modify it under the terms of the GNU General Public License
314 as published by the Free Software Foundation; either version 3 of
315 the License, or (at your option) any later version.
316
317 This program is distributed in the hope that it will be useful,
318 but WITHOUT ANY WARRANTY; without even the implied warranty of
319 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
320 GNU General Public License for more details.
321
322 You should have received a copy of the GNU General Public License
323 along with this program; If not, see <http://www.gnu.org/licenses/>.
324
325 EXCEPTION : As a special exception, you may create a larger work
326 that contains this FAUST architecture section and distribute
327 that work under terms of your choice, so long as this FAUST
328 architecture section is not modified.
329 ************************************************************************/
330
331 #ifndef __UI_H__
332 #define __UI_H__
333
334 #ifndef FAUSTFLOAT
335 #define FAUSTFLOAT float
336 #endif
337
338 /*******************************************************************************
339 * UI : Faust DSP User Interface
340 * User Interface as expected by the buildUserInterface() method of a DSP.
341 * This abstract class contains only the method that the Faust compiler can
342 * generate to describe a DSP user interface.
343 ******************************************************************************/
344
345 struct Soundfile;
346
347 template <typename REAL>
348 struct UIReal
349 {
350 UIReal() {}
351 virtual ~UIReal() {}
352
353 // -- widget's layouts
354
355 virtual void openTabBox(const char* label) = 0;
356 virtual void openHorizontalBox(const char* label) = 0;
357 virtual void openVerticalBox(const char* label) = 0;
358 virtual void closeBox() = 0;
359
360 // -- active widgets
361
362 virtual void addButton(const char* label, REAL* zone) = 0;
363 virtual void addCheckButton(const char* label, REAL* zone) = 0;
364 virtual void addVerticalSlider(const char* label, REAL* zone, REAL init, REAL min, REAL max, REAL step) = 0;
365 virtual void addHorizontalSlider(const char* label, REAL* zone, REAL init, REAL min, REAL max, REAL step) = 0;
366 virtual void addNumEntry(const char* label, REAL* zone, REAL init, REAL min, REAL max, REAL step) = 0;
367
368 // -- passive widgets
369
370 virtual void addHorizontalBargraph(const char* label, REAL* zone, REAL min, REAL max) = 0;
371 virtual void addVerticalBargraph(const char* label, REAL* zone, REAL min, REAL max) = 0;
372
373 // -- soundfiles
374
375 virtual void addSoundfile(const char* label, const char* filename, Soundfile** sf_zone) = 0;
376
377 // -- metadata declarations
378
379 virtual void declare(REAL* zone, const char* key, const char* val) {}
380 };
381
382 struct UI : public UIReal<FAUSTFLOAT>
383 {
384 UI() {}
385 virtual ~UI() {}
386 };
387
388 #endif
389 /************************** END UI.h **************************/
390 /************************** BEGIN PathBuilder.h **************************/
391 /************************************************************************
392 FAUST Architecture File
393 Copyright (C) 2003-2017 GRAME, Centre National de Creation Musicale
394 ---------------------------------------------------------------------
395 This Architecture section is free software; you can redistribute it
396 and/or modify it under the terms of the GNU General Public License
397 as published by the Free Software Foundation; either version 3 of
398 the License, or (at your option) any later version.
399
400 This program is distributed in the hope that it will be useful,
401 but WITHOUT ANY WARRANTY; without even the implied warranty of
402 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
403 GNU General Public License for more details.
404
405 You should have received a copy of the GNU General Public License
406 along with this program; If not, see <http://www.gnu.org/licenses/>.
407
408 EXCEPTION : As a special exception, you may create a larger work
409 that contains this FAUST architecture section and distribute
410 that work under terms of your choice, so long as this FAUST
411 architecture section is not modified.
412 ************************************************************************/
413
414 #ifndef FAUST_PATHBUILDER_H
415 #define FAUST_PATHBUILDER_H
416
417 #include <vector>
418 #include <string>
419 #include <algorithm>
420
421 /*******************************************************************************
422 * PathBuilder : Faust User Interface
423 * Helper class to build complete hierarchical path for UI items.
424 ******************************************************************************/
425
426 class PathBuilder
427 {
428
429 protected:
430
431 std::vector<std::string> fControlsLevel;
432
433 public:
434
435 PathBuilder() {}
436 virtual ~PathBuilder() {}
437
438 std::string buildPath(const std::string& label)
439 {
440 std::string res = "/";
441 for (size_t i = 0; i < fControlsLevel.size(); i++) {
442 res += fControlsLevel[i];
443 res += "/";
444 }
445 res += label;
446 std::replace(res.begin(), res.end(), ' ', '_');
447 return res;
448 }
449
450 std::string buildLabel(std::string label)
451 {
452 std::replace(label.begin(), label.end(), ' ', '_');
453 return label;
454 }
455
456 void pushLabel(const std::string& label) { fControlsLevel.push_back(label); }
457 void popLabel() { fControlsLevel.pop_back(); }
458
459 };
460
461 #endif // FAUST_PATHBUILDER_H
462 /************************** END PathBuilder.h **************************/
463 /************************** BEGIN ValueConverter.h **************************/
464 /************************************************************************
465 FAUST Architecture File
466 Copyright (C) 2003-2017 GRAME, Centre National de Creation Musicale
467 ---------------------------------------------------------------------
468 This Architecture section is free software; you can redistribute it
469 and/or modify it under the terms of the GNU General Public License
470 as published by the Free Software Foundation; either version 3 of
471 the License, or (at your option) any later version.
472
473 This program is distributed in the hope that it will be useful,
474 but WITHOUT ANY WARRANTY; without even the implied warranty of
475 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
476 GNU General Public License for more details.
477
478 You should have received a copy of the GNU General Public License
479 along with this program; If not, see <http://www.gnu.org/licenses/>.
480
481 EXCEPTION : As a special exception, you may create a larger work
482 that contains this FAUST architecture section and distribute
483 that work under terms of your choice, so long as this FAUST
484 architecture section is not modified.
485 ************************************************************************/
486
487 #ifndef __ValueConverter__
488 #define __ValueConverter__
489
490 /***************************************************************************************
491 ValueConverter.h
492 (GRAME, Copyright 2015-2019)
493
494 Set of conversion objects used to map user interface values (for example a gui slider
495 delivering values between 0 and 1) to faust values (for example a vslider between
496 20 and 20000) using a log scale.
497
498 -- Utilities
499
500 Range(lo,hi) : clip a value x between lo and hi
501 Interpolator(lo,hi,v1,v2) : Maps a value x between lo and hi to a value y between v1 and v2
502 Interpolator3pt(lo,mi,hi,v1,vm,v2) : Map values between lo mid hi to values between v1 vm v2
503
504 -- Value Converters
505
506 ValueConverter::ui2faust(x)
507 ValueConverter::faust2ui(x)
508
509 -- ValueConverters used for sliders depending of the scale
510
511 LinearValueConverter(umin, umax, fmin, fmax)
512 LinearValueConverter2(lo, mi, hi, v1, vm, v2) using 2 segments
513 LogValueConverter(umin, umax, fmin, fmax)
514 ExpValueConverter(umin, umax, fmin, fmax)
515
516 -- ValueConverters used for accelerometers based on 3 points
517
518 AccUpConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 0
519 AccDownConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 1
520 AccUpDownConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 2
521 AccDownUpConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 3
522
523 -- lists of ZoneControl are used to implement accelerometers metadata for each axes
524
525 ZoneControl(zone, valueConverter) : a zone with an accelerometer data converter
526
527 -- ZoneReader are used to implement screencolor metadata
528
529 ZoneReader(zone, valueConverter) : a zone with a data converter
530
531 ****************************************************************************************/
532
533 #include <float.h>
534 #include <algorithm> // std::max
535 #include <cmath>
536 #include <vector>
537 #include <assert.h>
538
539 //--------------------------------------------------------------------------------------
540 // Interpolator(lo,hi,v1,v2)
541 // Maps a value x between lo and hi to a value y between v1 and v2
542 // y = v1 + (x-lo)/(hi-lo)*(v2-v1)
543 // y = v1 + (x-lo) * coef with coef = (v2-v1)/(hi-lo)
544 // y = v1 + x*coef - lo*coef
545 // y = v1 - lo*coef + x*coef
546 // y = offset + x*coef with offset = v1 - lo*coef
547 //--------------------------------------------------------------------------------------
548 class Interpolator
549 {
550 private:
551
552 //--------------------------------------------------------------------------------------
553 // Range(lo,hi) clip a value between lo and hi
554 //--------------------------------------------------------------------------------------
555 struct Range
556 {
557 double fLo;
558 double fHi;
559
560 Range(double x, double y) : fLo(std::min<double>(x,y)), fHi(std::max<double>(x,y)) {}
561 double operator()(double x) { return (x<fLo) ? fLo : (x>fHi) ? fHi : x; }
562 };
563
564
565 Range fRange;
566 double fCoef;
567 double fOffset;
568
569 public:
570
571 Interpolator(double lo, double hi, double v1, double v2) : fRange(lo,hi)
572 {
573 if (hi != lo) {
574 // regular case
575 fCoef = (v2-v1)/(hi-lo);
576 fOffset = v1 - lo*fCoef;
577 } else {
578 // degenerate case, avoids division by zero
579 fCoef = 0;
580 fOffset = (v1+v2)/2;
581 }
582 }
583 double operator()(double v)
584 {
585 double x = fRange(v);
586 return fOffset + x*fCoef;
587 }
588
589 void getLowHigh(double& amin, double& amax)
590 {
591 amin = fRange.fLo;
592 amax = fRange.fHi;
593 }
594 };
595
596 //--------------------------------------------------------------------------------------
597 // Interpolator3pt(lo,mi,hi,v1,vm,v2)
598 // Map values between lo mid hi to values between v1 vm v2
599 //--------------------------------------------------------------------------------------
600 class Interpolator3pt
601 {
602
603 private:
604
605 Interpolator fSegment1;
606 Interpolator fSegment2;
607 double fMid;
608
609 public:
610
611 Interpolator3pt(double lo, double mi, double hi, double v1, double vm, double v2) :
612 fSegment1(lo, mi, v1, vm),
613 fSegment2(mi, hi, vm, v2),
614 fMid(mi) {}
615 double operator()(double x) { return (x < fMid) ? fSegment1(x) : fSegment2(x); }
616
617 void getMappingValues(double& amin, double& amid, double& amax)
618 {
619 fSegment1.getLowHigh(amin, amid);
620 fSegment2.getLowHigh(amid, amax);
621 }
622 };
623
624 //--------------------------------------------------------------------------------------
625 // Abstract ValueConverter class. Converts values between UI and Faust representations
626 //--------------------------------------------------------------------------------------
627 class ValueConverter
628 {
629
630 public:
631
632 virtual ~ValueConverter() {}
633 virtual double ui2faust(double x) = 0;
634 virtual double faust2ui(double x) = 0;
635 };
636
637 //--------------------------------------------------------------------------------------
638 // A converter than can be updated
639 //--------------------------------------------------------------------------------------
640
641 class UpdatableValueConverter : public ValueConverter {
642
643 protected:
644
645 bool fActive;
646
647 public:
648
649 UpdatableValueConverter():fActive(true)
650 {}
651 virtual ~UpdatableValueConverter()
652 {}
653
654 virtual void setMappingValues(double amin, double amid, double amax, double min, double init, double max) = 0;
655 virtual void getMappingValues(double& amin, double& amid, double& amax) = 0;
656
657 void setActive(bool on_off) { fActive = on_off; }
658 bool getActive() { return fActive; }
659
660 };
661
662
663 //--------------------------------------------------------------------------------------
664 // Linear conversion between ui and Faust values
665 //--------------------------------------------------------------------------------------
666 class LinearValueConverter : public ValueConverter
667 {
668
669 private:
670
671 Interpolator fUI2F;
672 Interpolator fF2UI;
673
674 public:
675
676 LinearValueConverter(double umin, double umax, double fmin, double fmax) :
677 fUI2F(umin,umax,fmin,fmax), fF2UI(fmin,fmax,umin,umax)
678 {}
679
680 LinearValueConverter() : fUI2F(0.,0.,0.,0.), fF2UI(0.,0.,0.,0.)
681 {}
682 virtual double ui2faust(double x) { return fUI2F(x); }
683 virtual double faust2ui(double x) { return fF2UI(x); }
684
685 };
686
687 //--------------------------------------------------------------------------------------
688 // Two segments linear conversion between ui and Faust values
689 //--------------------------------------------------------------------------------------
690 class LinearValueConverter2 : public UpdatableValueConverter
691 {
692
693 private:
694
695 Interpolator3pt fUI2F;
696 Interpolator3pt fF2UI;
697
698 public:
699
700 LinearValueConverter2(double amin, double amid, double amax, double min, double init, double max) :
701 fUI2F(amin, amid, amax, min, init, max), fF2UI(min, init, max, amin, amid, amax)
702 {}
703
704 LinearValueConverter2() : fUI2F(0.,0.,0.,0.,0.,0.), fF2UI(0.,0.,0.,0.,0.,0.)
705 {}
706
707 virtual double ui2faust(double x) { return fUI2F(x); }
708 virtual double faust2ui(double x) { return fF2UI(x); }
709
710 virtual void setMappingValues(double amin, double amid, double amax, double min, double init, double max)
711 {
712 fUI2F = Interpolator3pt(amin, amid, amax, min, init, max);
713 fF2UI = Interpolator3pt(min, init, max, amin, amid, amax);
714 }
715
716 virtual void getMappingValues(double& amin, double& amid, double& amax)
717 {
718 fUI2F.getMappingValues(amin, amid, amax);
719 }
720
721 };
722
723 //--------------------------------------------------------------------------------------
724 // Logarithmic conversion between ui and Faust values
725 //--------------------------------------------------------------------------------------
726 class LogValueConverter : public LinearValueConverter
727 {
728
729 public:
730
731 LogValueConverter(double umin, double umax, double fmin, double fmax) :
732 LinearValueConverter(umin, umax, std::log(std::max<double>(DBL_MIN, fmin)), std::log(std::max<double>(DBL_MIN, fmax)))
733 {}
734
735 virtual double ui2faust(double x) { return std::exp(LinearValueConverter::ui2faust(x)); }
736 virtual double faust2ui(double x) { return LinearValueConverter::faust2ui(std::log(std::max<double>(x, DBL_MIN))); }
737
738 };
739
740 //--------------------------------------------------------------------------------------
741 // Exponential conversion between ui and Faust values
742 //--------------------------------------------------------------------------------------
743 class ExpValueConverter : public LinearValueConverter
744 {
745
746 public:
747
748 ExpValueConverter(double umin, double umax, double fmin, double fmax) :
749 LinearValueConverter(umin, umax, std::min<double>(DBL_MAX, std::exp(fmin)), std::min<double>(DBL_MAX, std::exp(fmax)))
750 {}
751
752 virtual double ui2faust(double x) { return std::log(LinearValueConverter::ui2faust(x)); }
753 virtual double faust2ui(double x) { return LinearValueConverter::faust2ui(std::min<double>(DBL_MAX, std::exp(x))); }
754
755 };
756
757 //--------------------------------------------------------------------------------------
758 // Convert accelerometer or gyroscope values to Faust values
759 // Using an Up curve (curve 0)
760 //--------------------------------------------------------------------------------------
761 class AccUpConverter : public UpdatableValueConverter
762 {
763
764 private:
765
766 Interpolator3pt fA2F;
767 Interpolator3pt fF2A;
768
769 public:
770
771 AccUpConverter(double amin, double amid, double amax, double fmin, double fmid, double fmax) :
772 fA2F(amin,amid,amax,fmin,fmid,fmax),
773 fF2A(fmin,fmid,fmax,amin,amid,amax)
774 {}
775
776 virtual double ui2faust(double x) { return fA2F(x); }
777 virtual double faust2ui(double x) { return fF2A(x); }
778
779 virtual void setMappingValues(double amin, double amid, double amax, double fmin, double fmid, double fmax)
780 {
781 //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccUpConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax);
782 fA2F = Interpolator3pt(amin, amid, amax, fmin, fmid, fmax);
783 fF2A = Interpolator3pt(fmin, fmid, fmax, amin, amid, amax);
784 }
785
786 virtual void getMappingValues(double& amin, double& amid, double& amax)
787 {
788 fA2F.getMappingValues(amin, amid, amax);
789 }
790
791 };
792
793 //--------------------------------------------------------------------------------------
794 // Convert accelerometer or gyroscope values to Faust values
795 // Using a Down curve (curve 1)
796 //--------------------------------------------------------------------------------------
797 class AccDownConverter : public UpdatableValueConverter
798 {
799
800 private:
801
802 Interpolator3pt fA2F;
803 Interpolator3pt fF2A;
804
805 public:
806
807 AccDownConverter(double amin, double amid, double amax, double fmin, double fmid, double fmax) :
808 fA2F(amin,amid,amax,fmax,fmid,fmin),
809 fF2A(fmin,fmid,fmax,amax,amid,amin)
810 {}
811
812 virtual double ui2faust(double x) { return fA2F(x); }
813 virtual double faust2ui(double x) { return fF2A(x); }
814
815 virtual void setMappingValues(double amin, double amid, double amax, double fmin, double fmid, double fmax)
816 {
817 //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccDownConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax);
818 fA2F = Interpolator3pt(amin, amid, amax, fmax, fmid, fmin);
819 fF2A = Interpolator3pt(fmin, fmid, fmax, amax, amid, amin);
820 }
821
822 virtual void getMappingValues(double& amin, double& amid, double& amax)
823 {
824 fA2F.getMappingValues(amin, amid, amax);
825 }
826 };
827
828 //--------------------------------------------------------------------------------------
829 // Convert accelerometer or gyroscope values to Faust values
830 // Using an Up-Down curve (curve 2)
831 //--------------------------------------------------------------------------------------
832 class AccUpDownConverter : public UpdatableValueConverter
833 {
834
835 private:
836
837 Interpolator3pt fA2F;
838 Interpolator fF2A;
839
840 public:
841
842 AccUpDownConverter(double amin, double amid, double amax, double fmin, double fmid, double fmax) :
843 fA2F(amin,amid,amax,fmin,fmax,fmin),
844 fF2A(fmin,fmax,amin,amax) // Special, pseudo inverse of a non monotonic function
845 {}
846
847 virtual double ui2faust(double x) { return fA2F(x); }
848 virtual double faust2ui(double x) { return fF2A(x); }
849
850 virtual void setMappingValues(double amin, double amid, double amax, double fmin, double fmid, double fmax)
851 {
852 //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccUpDownConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax);
853 fA2F = Interpolator3pt(amin, amid, amax, fmin, fmax, fmin);
854 fF2A = Interpolator(fmin, fmax, amin, amax);
855 }
856
857 virtual void getMappingValues(double& amin, double& amid, double& amax)
858 {
859 fA2F.getMappingValues(amin, amid, amax);
860 }
861 };
862
863 //--------------------------------------------------------------------------------------
864 // Convert accelerometer or gyroscope values to Faust values
865 // Using a Down-Up curve (curve 3)
866 //--------------------------------------------------------------------------------------
867 class AccDownUpConverter : public UpdatableValueConverter
868 {
869
870 private:
871
872 Interpolator3pt fA2F;
873 Interpolator fF2A;
874
875 public:
876
877 AccDownUpConverter(double amin, double amid, double amax, double fmin, double fmid, double fmax) :
878 fA2F(amin,amid,amax,fmax,fmin,fmax),
879 fF2A(fmin,fmax,amin,amax) // Special, pseudo inverse of a non monotonic function
880 {}
881
882 virtual double ui2faust(double x) { return fA2F(x); }
883 virtual double faust2ui(double x) { return fF2A(x); }
884
885 virtual void setMappingValues(double amin, double amid, double amax, double fmin, double fmid, double fmax)
886 {
887 //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccDownUpConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax);
888 fA2F = Interpolator3pt(amin, amid, amax, fmax, fmin, fmax);
889 fF2A = Interpolator(fmin, fmax, amin, amax);
890 }
891
892 virtual void getMappingValues(double& amin, double& amid, double& amax)
893 {
894 fA2F.getMappingValues(amin, amid, amax);
895 }
896 };
897
898 //--------------------------------------------------------------------------------------
899 // Base class for ZoneControl
900 //--------------------------------------------------------------------------------------
901 class ZoneControl
902 {
903
904 protected:
905
906 FAUSTFLOAT* fZone;
907
908 public:
909
910 ZoneControl(FAUSTFLOAT* zone) : fZone(zone) {}
911 virtual ~ZoneControl() {}
912
913 virtual void update(double v) const {}
914
915 virtual void setMappingValues(int curve, double amin, double amid, double amax, double min, double init, double max) {}
916 virtual void getMappingValues(double& amin, double& amid, double& amax) {}
917
918 FAUSTFLOAT* getZone() { return fZone; }
919
920 virtual void setActive(bool on_off) {}
921 virtual bool getActive() { return false; }
922
923 virtual int getCurve() { return -1; }
924
925 };
926
927 //--------------------------------------------------------------------------------------
928 // Useful to implement accelerometers metadata as a list of ZoneControl for each axes
929 //--------------------------------------------------------------------------------------
930 class ConverterZoneControl : public ZoneControl
931 {
932
933 protected:
934
935 ValueConverter* fValueConverter;
936
937 public:
938
939 ConverterZoneControl(FAUSTFLOAT* zone, ValueConverter* converter) : ZoneControl(zone), fValueConverter(converter) {}
940 virtual ~ConverterZoneControl() { delete fValueConverter; } // Assuming fValueConverter is not kept elsewhere...
941
942 virtual void update(double v) const { *fZone = fValueConverter->ui2faust(v); }
943
944 ValueConverter* getConverter() { return fValueConverter; }
945
946 };
947
948 //--------------------------------------------------------------------------------------
949 // Association of a zone and a four value converter, each one for each possible curve.
950 // Useful to implement accelerometers metadata as a list of ZoneControl for each axes
951 //--------------------------------------------------------------------------------------
952 class CurveZoneControl : public ZoneControl
953 {
954
955 private:
956
957 std::vector<UpdatableValueConverter*> fValueConverters;
958 int fCurve;
959
960 public:
961
962 CurveZoneControl(FAUSTFLOAT* zone, int curve, double amin, double amid, double amax, double min, double init, double max) : ZoneControl(zone), fCurve(0)
963 {
964 assert(curve >= 0 && curve <= 3);
965 fValueConverters.push_back(new AccUpConverter(amin, amid, amax, min, init, max));
966 fValueConverters.push_back(new AccDownConverter(amin, amid, amax, min, init, max));
967 fValueConverters.push_back(new AccUpDownConverter(amin, amid, amax, min, init, max));
968 fValueConverters.push_back(new AccDownUpConverter(amin, amid, amax, min, init, max));
969 fCurve = curve;
970 }
971 virtual ~CurveZoneControl()
972 {
973 std::vector<UpdatableValueConverter*>::iterator it;
974 for (it = fValueConverters.begin(); it != fValueConverters.end(); it++) {
975 delete(*it);
976 }
977 }
978 void update(double v) const { if (fValueConverters[fCurve]->getActive()) *fZone = fValueConverters[fCurve]->ui2faust(v); }
979
980 void setMappingValues(int curve, double amin, double amid, double amax, double min, double init, double max)
981 {
982 fValueConverters[curve]->setMappingValues(amin, amid, amax, min, init, max);
983 fCurve = curve;
984 }
985
986 void getMappingValues(double& amin, double& amid, double& amax)
987 {
988 fValueConverters[fCurve]->getMappingValues(amin, amid, amax);
989 }
990
991 void setActive(bool on_off)
992 {
993 std::vector<UpdatableValueConverter*>::iterator it;
994 for (it = fValueConverters.begin(); it != fValueConverters.end(); it++) {
995 (*it)->setActive(on_off);
996 }
997 }
998
999 int getCurve() { return fCurve; }
1000 };
1001
1002 class ZoneReader
1003 {
1004
1005 private:
1006
1007 FAUSTFLOAT* fZone;
1008 Interpolator fInterpolator;
1009
1010 public:
1011
1012 ZoneReader(FAUSTFLOAT* zone, double lo, double hi) : fZone(zone), fInterpolator(lo, hi, 0, 255) {}
1013
1014 virtual ~ZoneReader() {}
1015
1016 int getValue()
1017 {
1018 return (fZone != nullptr) ? int(fInterpolator(*fZone)) : 127;
1019 }
1020
1021 };
1022
1023 #endif
1024 /************************** END ValueConverter.h **************************/
1025
1026 class APIUI : public PathBuilder, public Meta, public UI
1027 {
1028 public:
1029
1030 enum ItemType { kButton = 0, kCheckButton, kVSlider, kHSlider, kNumEntry, kHBargraph, kVBargraph };
1031
1032 protected:
1033
1034 enum { kLin = 0, kLog = 1, kExp = 2 };
1035
1036 int fNumParameters;
1037 std::vector<std::string> fPaths;
1038 std::vector<std::string> fLabels;
1039 std::map<std::string, int> fPathMap;
1040 std::map<std::string, int> fLabelMap;
1041 std::vector<ValueConverter*> fConversion;
1042 std::vector<FAUSTFLOAT*> fZone;
1043 std::vector<FAUSTFLOAT> fInit;
1044 std::vector<FAUSTFLOAT> fMin;
1045 std::vector<FAUSTFLOAT> fMax;
1046 std::vector<FAUSTFLOAT> fStep;
1047 std::vector<ItemType> fItemType;
1048 std::vector<std::map<std::string, std::string> > fMetaData;
1049 std::vector<ZoneControl*> fAcc[3];
1050 std::vector<ZoneControl*> fGyr[3];
1051
1052 // Screen color control
1053 // "...[screencolor:red]..." etc.
1054 bool fHasScreenControl; // true if control screen color metadata
1055 ZoneReader* fRedReader;
1056 ZoneReader* fGreenReader;
1057 ZoneReader* fBlueReader;
1058
1059 // Current values controlled by metadata
1060 std::string fCurrentUnit;
1061 int fCurrentScale;
1062 std::string fCurrentAcc;
1063 std::string fCurrentGyr;
1064 std::string fCurrentColor;
1065 std::string fCurrentTooltip;
1066 std::map<std::string, std::string> fCurrentMetadata;
1067
1068 // Add a generic parameter
1069 virtual void addParameter(const char* label,
1070 FAUSTFLOAT* zone,
1071 FAUSTFLOAT init,
1072 FAUSTFLOAT min,
1073 FAUSTFLOAT max,
1074 FAUSTFLOAT step,
1075 ItemType type)
1076 {
1077 std::string path = buildPath(label);
1078 fPathMap[path] = fLabelMap[label] = fNumParameters++;
1079 fPaths.push_back(path);
1080 fLabels.push_back(label);
1081 fZone.push_back(zone);
1082 fInit.push_back(init);
1083 fMin.push_back(min);
1084 fMax.push_back(max);
1085 fStep.push_back(step);
1086 fItemType.push_back(type);
1087
1088 // handle scale metadata
1089 switch (fCurrentScale) {
1090 case kLin:
1091 fConversion.push_back(new LinearValueConverter(0, 1, min, max));
1092 break;
1093 case kLog:
1094 fConversion.push_back(new LogValueConverter(0, 1, min, max));
1095 break;
1096 case kExp: fConversion.push_back(new ExpValueConverter(0, 1, min, max));
1097 break;
1098 }
1099 fCurrentScale = kLin;
1100
1101 if (fCurrentAcc.size() > 0 && fCurrentGyr.size() > 0) {
1102 std::cerr << "warning : 'acc' and 'gyr' metadata used for the same " << label << " parameter !!\n";
1103 }
1104
1105 // handle acc metadata "...[acc : <axe> <curve> <amin> <amid> <amax>]..."
1106 if (fCurrentAcc.size() > 0) {
1107 std::istringstream iss(fCurrentAcc);
1108 int axe, curve;
1109 double amin, amid, amax;
1110 iss >> axe >> curve >> amin >> amid >> amax;
1111
1112 if ((0 <= axe) && (axe < 3) &&
1113 (0 <= curve) && (curve < 4) &&
1114 (amin < amax) && (amin <= amid) && (amid <= amax))
1115 {
1116 fAcc[axe].push_back(new CurveZoneControl(zone, curve, amin, amid, amax, min, init, max));
1117 } else {
1118 std::cerr << "incorrect acc metadata : " << fCurrentAcc << std::endl;
1119 }
1120 fCurrentAcc = "";
1121 }
1122
1123 // handle gyr metadata "...[gyr : <axe> <curve> <amin> <amid> <amax>]..."
1124 if (fCurrentGyr.size() > 0) {
1125 std::istringstream iss(fCurrentGyr);
1126 int axe, curve;
1127 double amin, amid, amax;
1128 iss >> axe >> curve >> amin >> amid >> amax;
1129
1130 if ((0 <= axe) && (axe < 3) &&
1131 (0 <= curve) && (curve < 4) &&
1132 (amin < amax) && (amin <= amid) && (amid <= amax))
1133 {
1134 fGyr[axe].push_back(new CurveZoneControl(zone, curve, amin, amid, amax, min, init, max));
1135 } else {
1136 std::cerr << "incorrect gyr metadata : " << fCurrentGyr << std::endl;
1137 }
1138 fCurrentGyr = "";
1139 }
1140
1141 // handle screencolor metadata "...[screencolor:red|green|blue|white]..."
1142 if (fCurrentColor.size() > 0) {
1143 if ((fCurrentColor == "red") && (fRedReader == 0)) {
1144 fRedReader = new ZoneReader(zone, min, max);
1145 fHasScreenControl = true;
1146 } else if ((fCurrentColor == "green") && (fGreenReader == 0)) {
1147 fGreenReader = new ZoneReader(zone, min, max);
1148 fHasScreenControl = true;
1149 } else if ((fCurrentColor == "blue") && (fBlueReader == 0)) {
1150 fBlueReader = new ZoneReader(zone, min, max);
1151 fHasScreenControl = true;
1152 } else if ((fCurrentColor == "white") && (fRedReader == 0) && (fGreenReader == 0) && (fBlueReader == 0)) {
1153 fRedReader = new ZoneReader(zone, min, max);
1154 fGreenReader = new ZoneReader(zone, min, max);
1155 fBlueReader = new ZoneReader(zone, min, max);
1156 fHasScreenControl = true;
1157 } else {
1158 std::cerr << "incorrect screencolor metadata : " << fCurrentColor << std::endl;
1159 }
1160 }
1161 fCurrentColor = "";
1162
1163 fMetaData.push_back(fCurrentMetadata);
1164 fCurrentMetadata.clear();
1165 }
1166
1167 int getZoneIndex(std::vector<ZoneControl*>* table, int p, int val)
1168 {
1169 FAUSTFLOAT* zone = fZone[p];
1170 for (size_t i = 0; i < table[val].size(); i++) {
1171 if (zone == table[val][i]->getZone()) return int(i);
1172 }
1173 return -1;
1174 }
1175
1176 void setConverter(std::vector<ZoneControl*>* table, int p, int val, int curve, double amin, double amid, double amax)
1177 {
1178 int id1 = getZoneIndex(table, p, 0);
1179 int id2 = getZoneIndex(table, p, 1);
1180 int id3 = getZoneIndex(table, p, 2);
1181
1182 // Deactivates everywhere..
1183 if (id1 != -1) table[0][id1]->setActive(false);
1184 if (id2 != -1) table[1][id2]->setActive(false);
1185 if (id3 != -1) table[2][id3]->setActive(false);
1186
1187 if (val == -1) { // Means: no more mapping...
1188 // So stay all deactivated...
1189 } else {
1190 int id4 = getZoneIndex(table, p, val);
1191 if (id4 != -1) {
1192 // Reactivate the one we edit...
1193 table[val][id4]->setMappingValues(curve, amin, amid, amax, fMin[p], fInit[p], fMax[p]);
1194 table[val][id4]->setActive(true);
1195 } else {
1196 // Allocate a new CurveZoneControl which is 'active' by default
1197 FAUSTFLOAT* zone = fZone[p];
1198 table[val].push_back(new CurveZoneControl(zone, curve, amin, amid, amax, fMin[p], fInit[p], fMax[p]));
1199 }
1200 }
1201 }
1202
1203 void getConverter(std::vector<ZoneControl*>* table, int p, int& val, int& curve, double& amin, double& amid, double& amax)
1204 {
1205 int id1 = getZoneIndex(table, p, 0);
1206 int id2 = getZoneIndex(table, p, 1);
1207 int id3 = getZoneIndex(table, p, 2);
1208
1209 if (id1 != -1) {
1210 val = 0;
1211 curve = table[val][id1]->getCurve();
1212 table[val][id1]->getMappingValues(amin, amid, amax);
1213 } else if (id2 != -1) {
1214 val = 1;
1215 curve = table[val][id2]->getCurve();
1216 table[val][id2]->getMappingValues(amin, amid, amax);
1217 } else if (id3 != -1) {
1218 val = 2;
1219 curve = table[val][id3]->getCurve();
1220 table[val][id3]->getMappingValues(amin, amid, amax);
1221 } else {
1222 val = -1; // No mapping
1223 curve = 0;
1224 amin = -100.;
1225 amid = 0.;
1226 amax = 100.;
1227 }
1228 }
1229
1230 public:
1231
1232 enum Type { kAcc = 0, kGyr = 1, kNoType };
1233
1234 APIUI() : fNumParameters(0), fHasScreenControl(false), fRedReader(0), fGreenReader(0), fBlueReader(0), fCurrentScale(kLin)
1235 {}
1236
1237 virtual ~APIUI()
1238 {
1239 for (auto& it : fConversion) delete it;
1240 for (int i = 0; i < 3; i++) {
1241 for (auto& it : fAcc[i]) delete it;
1242 for (auto& it : fGyr[i]) delete it;
1243 }
1244 delete fRedReader;
1245 delete fGreenReader;
1246 delete fBlueReader;
1247 }
1248
1249 // -- widget's layouts
1250
1251 virtual void openTabBox(const char* label) { pushLabel(label); }
1252 virtual void openHorizontalBox(const char* label) { pushLabel(label); }
1253 virtual void openVerticalBox(const char* label) { pushLabel(label); }
1254 virtual void closeBox() { popLabel(); }
1255
1256 // -- active widgets
1257
1258 virtual void addButton(const char* label, FAUSTFLOAT* zone)
1259 {
1260 addParameter(label, zone, 0, 0, 1, 1, kButton);
1261 }
1262
1263 virtual void addCheckButton(const char* label, FAUSTFLOAT* zone)
1264 {
1265 addParameter(label, zone, 0, 0, 1, 1, kCheckButton);
1266 }
1267
1268 virtual void addVerticalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step)
1269 {
1270 addParameter(label, zone, init, min, max, step, kVSlider);
1271 }
1272
1273 virtual void addHorizontalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step)
1274 {
1275 addParameter(label, zone, init, min, max, step, kHSlider);
1276 }
1277
1278 virtual void addNumEntry(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step)
1279 {
1280 addParameter(label, zone, init, min, max, step, kNumEntry);
1281 }
1282
1283 // -- passive widgets
1284
1285 virtual void addHorizontalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max)
1286 {
1287 addParameter(label, zone, min, min, max, (max-min)/1000.0, kHBargraph);
1288 }
1289
1290 virtual void addVerticalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max)
1291 {
1292 addParameter(label, zone, min, min, max, (max-min)/1000.0, kVBargraph);
1293 }
1294
1295 // -- soundfiles
1296
1297 virtual void addSoundfile(const char* label, const char* filename, Soundfile** sf_zone) {}
1298
1299 // -- metadata declarations
1300
1301 virtual void declare(FAUSTFLOAT* zone, const char* key, const char* val)
1302 {
1303 // Keep metadata
1304 fCurrentMetadata[key] = val;
1305
1306 if (strcmp(key, "scale") == 0) {
1307 if (strcmp(val, "log") == 0) {
1308 fCurrentScale = kLog;
1309 } else if (strcmp(val, "exp") == 0) {
1310 fCurrentScale = kExp;
1311 } else {
1312 fCurrentScale = kLin;
1313 }
1314 } else if (strcmp(key, "unit") == 0) {
1315 fCurrentUnit = val;
1316 } else if (strcmp(key, "acc") == 0) {
1317 fCurrentAcc = val;
1318 } else if (strcmp(key, "gyr") == 0) {
1319 fCurrentGyr = val;
1320 } else if (strcmp(key, "screencolor") == 0) {
1321 fCurrentColor = val; // val = "red", "green", "blue" or "white"
1322 } else if (strcmp(key, "tooltip") == 0) {
1323 fCurrentTooltip = val;
1324 }
1325 }
1326
1327 virtual void declare(const char* key, const char* val)
1328 {}
1329
1330 //-------------------------------------------------------------------------------
1331 // Simple API part
1332 //-------------------------------------------------------------------------------
1333 int getParamsCount() { return fNumParameters; }
1334 int getParamIndex(const char* path)
1335 {
1336 if (fPathMap.find(path) != fPathMap.end()) {
1337 return fPathMap[path];
1338 } else if (fLabelMap.find(path) != fLabelMap.end()) {
1339 return fLabelMap[path];
1340 } else {
1341 return -1;
1342 }
1343 }
1344 const char* getParamAddress(int p) { return fPaths[p].c_str(); }
1345 const char* getParamLabel(int p) { return fLabels[p].c_str(); }
1346 std::map<const char*, const char*> getMetadata(int p)
1347 {
1348 std::map<const char*, const char*> res;
1349 std::map<std::string, std::string> metadata = fMetaData[p];
1350 for (auto it : metadata) {
1351 res[it.first.c_str()] = it.second.c_str();
1352 }
1353 return res;
1354 }
1355
1356 const char* getMetadata(int p, const char* key)
1357 {
1358 return (fMetaData[p].find(key) != fMetaData[p].end()) ? fMetaData[p][key].c_str() : "";
1359 }
1360 FAUSTFLOAT getParamMin(int p) { return fMin[p]; }
1361 FAUSTFLOAT getParamMax(int p) { return fMax[p]; }
1362 FAUSTFLOAT getParamStep(int p) { return fStep[p]; }
1363 FAUSTFLOAT getParamInit(int p) { return fInit[p]; }
1364
1365 FAUSTFLOAT* getParamZone(int p) { return fZone[p]; }
1366 FAUSTFLOAT getParamValue(int p) { return *fZone[p]; }
1367 void setParamValue(int p, FAUSTFLOAT v) { *fZone[p] = v; }
1368
1369 double getParamRatio(int p) { return fConversion[p]->faust2ui(*fZone[p]); }
1370 void setParamRatio(int p, double r) { *fZone[p] = fConversion[p]->ui2faust(r); }
1371
1372 double value2ratio(int p, double r) { return fConversion[p]->faust2ui(r); }
1373 double ratio2value(int p, double r) { return fConversion[p]->ui2faust(r); }
1374
1375 /**
1376 * Return the control type (kAcc, kGyr, or -1) for a given parameter
1377 *
1378 * @param p - the UI parameter index
1379 *
1380 * @return the type
1381 */
1382 Type getParamType(int p)
1383 {
1384 if (p >= 0) {
1385 if (getZoneIndex(fAcc, p, 0) != -1
1386 || getZoneIndex(fAcc, p, 1) != -1
1387 || getZoneIndex(fAcc, p, 2) != -1) {
1388 return kAcc;
1389 } else if (getZoneIndex(fGyr, p, 0) != -1
1390 || getZoneIndex(fGyr, p, 1) != -1
1391 || getZoneIndex(fGyr, p, 2) != -1) {
1392 return kGyr;
1393 }
1394 }
1395 return kNoType;
1396 }
1397
1398 /**
1399 * Return the Item type (kButton = 0, kCheckButton, kVSlider, kHSlider, kNumEntry, kHBargraph, kVBargraph) for a given parameter
1400 *
1401 * @param p - the UI parameter index
1402 *
1403 * @return the Item type
1404 */
1405 ItemType getParamItemType(int p)
1406 {
1407 return fItemType[p];
1408 }
1409
1410 /**
1411 * Set a new value coming from an accelerometer, propagate it to all relevant FAUSTFLOAT* zones.
1412 *
1413 * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer
1414 * @param value - the new value
1415 *
1416 */
1417 void propagateAcc(int acc, double value)
1418 {
1419 for (size_t i = 0; i < fAcc[acc].size(); i++) {
1420 fAcc[acc][i]->update(value);
1421 }
1422 }
1423
1424 /**
1425 * Used to edit accelerometer curves and mapping. Set curve and related mapping for a given UI parameter.
1426 *
1427 * @param p - the UI parameter index
1428 * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer (-1 means "no mapping")
1429 * @param curve - between 0 and 3
1430 * @param amin - mapping 'min' point
1431 * @param amid - mapping 'middle' point
1432 * @param amax - mapping 'max' point
1433 *
1434 */
1435 void setAccConverter(int p, int acc, int curve, double amin, double amid, double amax)
1436 {
1437 setConverter(fAcc, p, acc, curve, amin, amid, amax);
1438 }
1439
1440 /**
1441 * Used to edit gyroscope curves and mapping. Set curve and related mapping for a given UI parameter.
1442 *
1443 * @param p - the UI parameter index
1444 * @param acc - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope (-1 means "no mapping")
1445 * @param curve - between 0 and 3
1446 * @param amin - mapping 'min' point
1447 * @param amid - mapping 'middle' point
1448 * @param amax - mapping 'max' point
1449 *
1450 */
1451 void setGyrConverter(int p, int gyr, int curve, double amin, double amid, double amax)
1452 {
1453 setConverter(fGyr, p, gyr, curve, amin, amid, amax);
1454 }
1455
1456 /**
1457 * Used to edit accelerometer curves and mapping. Get curve and related mapping for a given UI parameter.
1458 *
1459 * @param p - the UI parameter index
1460 * @param acc - the acc value to be retrieved (-1 means "no mapping")
1461 * @param curve - the curve value to be retrieved
1462 * @param amin - the amin value to be retrieved
1463 * @param amid - the amid value to be retrieved
1464 * @param amax - the amax value to be retrieved
1465 *
1466 */
1467 void getAccConverter(int p, int& acc, int& curve, double& amin, double& amid, double& amax)
1468 {
1469 getConverter(fAcc, p, acc, curve, amin, amid, amax);
1470 }
1471
1472 /**
1473 * Used to edit gyroscope curves and mapping. Get curve and related mapping for a given UI parameter.
1474 *
1475 * @param p - the UI parameter index
1476 * @param gyr - the gyr value to be retrieved (-1 means "no mapping")
1477 * @param curve - the curve value to be retrieved
1478 * @param amin - the amin value to be retrieved
1479 * @param amid - the amid value to be retrieved
1480 * @param amax - the amax value to be retrieved
1481 *
1482 */
1483 void getGyrConverter(int p, int& gyr, int& curve, double& amin, double& amid, double& amax)
1484 {
1485 getConverter(fGyr, p, gyr, curve, amin, amid, amax);
1486 }
1487
1488 /**
1489 * Set a new value coming from an gyroscope, propagate it to all relevant FAUSTFLOAT* zones.
1490 *
1491 * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope
1492 * @param value - the new value
1493 *
1494 */
1495 void propagateGyr(int gyr, double value)
1496 {
1497 for (size_t i = 0; i < fGyr[gyr].size(); i++) {
1498 fGyr[gyr][i]->update(value);
1499 }
1500 }
1501
1502 /**
1503 * Get the number of FAUSTFLOAT* zones controlled with the accelerometer
1504 *
1505 * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer
1506 * @return the number of zones
1507 *
1508 */
1509 int getAccCount(int acc)
1510 {
1511 return (acc >= 0 && acc < 3) ? int(fAcc[acc].size()) : 0;
1512 }
1513
1514 /**
1515 * Get the number of FAUSTFLOAT* zones controlled with the gyroscope
1516 *
1517 * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope
1518 * @param the number of zones
1519 *
1520 */
1521 int getGyrCount(int gyr)
1522 {
1523 return (gyr >= 0 && gyr < 3) ? int(fGyr[gyr].size()) : 0;
1524 }
1525
1526 // getScreenColor() : -1 means no screen color control (no screencolor metadata found)
1527 // otherwise return 0x00RRGGBB a ready to use color
1528 int getScreenColor()
1529 {
1530 if (fHasScreenControl) {
1531 int r = (fRedReader) ? fRedReader->getValue() : 0;
1532 int g = (fGreenReader) ? fGreenReader->getValue() : 0;
1533 int b = (fBlueReader) ? fBlueReader->getValue() : 0;
1534 return (r<<16) | (g<<8) | b;
1535 } else {
1536 return -1;
1537 }
1538 }
1539
1540 };
1541
1542 #endif
1543 /************************** END APIUI.h **************************/
1544
1545 // NOTE: "faust -scn name" changes the last line above to
1546 // #include <faust/name/name.h>
1547
1548 //----------------------------------------------------------------------------
1549 // FAUST Generated Code
1550 //----------------------------------------------------------------------------
1551
1552
1553 #ifndef FAUSTFLOAT
1554 #define FAUSTFLOAT float
1555 #endif
1556
1557 #include <algorithm>
1558 #include <cmath>
1559 #include <math.h>
1560
1561
1562 #ifndef FAUSTCLASS
1563 #define FAUSTCLASS limiterdsp
1564 #endif
1565
1566 #ifdef __APPLE__
1567 #define exp10f __exp10f
1568 #define exp10 __exp10
1569 #endif
1570
1571 class limiterdsp : public dsp {
1572
1573 private:
1574
1575 int fSampleRate;
1576 float fConst0;
1577 float fConst1;
1578 float fConst2;
1579 float fConst3;
1580 int iRec5[2];
1581 FAUSTFLOAT fHslider0;
1582 int IOTA;
1583 float fVec0[32];
1584 float fRec4[2];
1585 int iRec2[2];
1586 float fRec1[2];
1587 float fConst4;
1588 float fConst5;
1589 float fRec0[2];
1590 int iConst6;
1591
1592 public:
1593
1594 void metadata(Meta* m) {
1595 m->declare("analyzers.lib/name", "Faust Analyzer Library");
1596 m->declare("analyzers.lib/version", "0.1");
1597 m->declare("basics.lib/name", "Faust Basic Element Library");
1598 m->declare("basics.lib/version", "0.1");
1599 m->declare("compressors.lib/limiter_lad_N:author", "Dario Sanfilippo");
1600 m->declare("compressors.lib/limiter_lad_N:copyright", "Copyright (C) 2020 Dario Sanfilippo <sanfilippo.dario@gmail.com>");
1601 m->declare("compressors.lib/limiter_lad_N:license", "GPLv3 license");
1602 m->declare("compressors.lib/limiter_lad_mono:author", "Dario Sanfilippo");
1603 m->declare("compressors.lib/limiter_lad_mono:copyright", "Copyright (C) 2020 Dario Sanfilippo <sanfilippo.dario@gmail.com>");
1604 m->declare("compressors.lib/limiter_lad_mono:license", "GPLv3 license");
1605 m->declare("compressors.lib/name", "Faust Compressor Effect Library");
1606 m->declare("compressors.lib/version", "0.0");
1607 m->declare("filename", "limiterdsp.dsp");
1608 m->declare("maths.lib/author", "GRAME");
1609 m->declare("maths.lib/copyright", "GRAME");
1610 m->declare("maths.lib/license", "LGPL with exception");
1611 m->declare("maths.lib/name", "Faust Math Library");
1612 m->declare("maths.lib/version", "2.3");
1613 m->declare("name", "limiterdsp");
1614 m->declare("platform.lib/name", "Generic Platform Library");
1615 m->declare("platform.lib/version", "0.1");
1616 m->declare("routes.lib/name", "Faust Signal Routing Library");
1617 m->declare("routes.lib/version", "0.2");
1618 m->declare("signals.lib/name", "Faust Signal Routing Library");
1619 m->declare("signals.lib/version", "0.0");
1620 }
1621
1622 virtual int getNumInputs() {
1623 return 1;
1624 }
1625 virtual int getNumOutputs() {
1626 return 1;
1627 }
1628 virtual int getInputRate(int channel) {
1629 int rate;
1630 switch ((channel)) {
1631 case 0: {
1632 rate = 1;
1633 break;
1634 }
1635 default: {
1636 rate = -1;
1637 break;
1638 }
1639 }
1640 return rate;
1641 }
1642 virtual int getOutputRate(int channel) {
1643 int rate;
1644 switch ((channel)) {
1645 case 0: {
1646 rate = 1;
1647 break;
1648 }
1649 default: {
1650 rate = -1;
1651 break;
1652 }
1653 }
1654 return rate;
1655 }
1656
1657 static void classInit(int sample_rate) {
1658 }
1659
1660 virtual void instanceConstants(int sample_rate) {
1661 fSampleRate = sample_rate;
1662 fConst0 = std::min<float>(192000.0f, std::max<float>(1.0f, float(fSampleRate)));
1663 fConst1 = std::exp((0.0f - (100000.0f / fConst0)));
1664 fConst2 = (1.0f - fConst1);
1665 fConst3 = (0.100000001f * fConst0);
1666 fConst4 = std::exp((0.0f - (4.0f / fConst0)));
1667 fConst5 = (1.0f - fConst4);
1668 iConst6 = int((9.99999975e-05f * fConst0));
1669 }
1670
1671 virtual void instanceResetUserInterface() {
1672 fHslider0 = FAUSTFLOAT(2.0f);
1673 }
1674
1675 virtual void instanceClear() {
1676 for (int l0 = 0; (l0 < 2); l0 = (l0 + 1)) {
1677 iRec5[l0] = 0;
1678 }
1679 IOTA = 0;
1680 for (int l1 = 0; (l1 < 32); l1 = (l1 + 1)) {
1681 fVec0[l1] = 0.0f;
1682 }
1683 for (int l2 = 0; (l2 < 2); l2 = (l2 + 1)) {
1684 fRec4[l2] = 0.0f;
1685 }
1686 for (int l3 = 0; (l3 < 2); l3 = (l3 + 1)) {
1687 iRec2[l3] = 0;
1688 }
1689 for (int l4 = 0; (l4 < 2); l4 = (l4 + 1)) {
1690 fRec1[l4] = 0.0f;
1691 }
1692 for (int l5 = 0; (l5 < 2); l5 = (l5 + 1)) {
1693 fRec0[l5] = 0.0f;
1694 }
1695 }
1696
1697 virtual void init(int sample_rate) {
1698 classInit(sample_rate);
1699 instanceInit(sample_rate);
1700 }
1701 virtual void instanceInit(int sample_rate) {
1702 instanceConstants(sample_rate);
1703 instanceResetUserInterface();
1704 instanceClear();
1705 }
1706
1707 virtual limiterdsp* clone() {
1708 return new limiterdsp();
1709 }
1710
1711 virtual int getSampleRate() {
1712 return fSampleRate;
1713 }
1714
1715 virtual void buildUserInterface(UI* ui_interface) {
1716 ui_interface->openVerticalBox("limiterdsp");
1717 ui_interface->declare(&fHslider0, "0", "");
1718 ui_interface->addHorizontalSlider("NumClientsAssumed", &fHslider0, 2.0f, 1.0f, 64.0f, 1.0f);
1719 ui_interface->closeBox();
1720 }
1721
1722 virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) {
1723 FAUSTFLOAT* input0 = inputs[0];
1724 FAUSTFLOAT* output0 = outputs[0];
1725 float fSlow0 = (1.0f / std::sqrt(float(fHslider0)));
1726 for (int i = 0; (i < count); i = (i + 1)) {
1727 float fTemp0 = float(input0[i]);
1728 iRec5[0] = ((iRec5[1] + 1) % int(std::max<float>(1.0f, (fConst3 * float(iRec2[1])))));
1729 float fTemp1 = (fSlow0 * fTemp0);
1730 fVec0[(IOTA & 31)] = fTemp1;
1731 float fTemp2 = std::fabs(fTemp1);
1732 fRec4[0] = std::max<float>((float((iRec5[0] > 0)) * fRec4[1]), fTemp2);
1733 iRec2[0] = (fRec4[0] >= fTemp2);
1734 float fRec3 = fRec4[0];
1735 fRec1[0] = ((fConst1 * fRec1[1]) + (fConst2 * fRec3));
1736 float fTemp3 = std::fabs(fRec1[0]);
1737 fRec0[0] = std::max<float>(fTemp3, ((fConst4 * fRec0[1]) + (fConst5 * fTemp3)));
1738 output0[i] = FAUSTFLOAT((std::min<float>(1.0f, (0.5f / std::max<float>(fRec0[0], 1.1920929e-07f))) * fVec0[((IOTA - iConst6) & 31)]));
1739 iRec5[1] = iRec5[0];
1740 IOTA = (IOTA + 1);
1741 fRec4[1] = fRec4[0];
1742 iRec2[1] = iRec2[0];
1743 fRec1[1] = fRec1[0];
1744 fRec0[1] = fRec0[0];
1745 }
1746 }
1747
1748 };
1749
1750 #endif
0 qmake -spec macx-xcode jacktrip.pro
0 /* ------------------------------------------------------------
1 name: "zitarevdsp"
2 Code generated with Faust 2.28.6 (https://faust.grame.fr)
3 Compilation options: -lang cpp -inpl -scal -ftz 0
4 ------------------------------------------------------------ */
5
6 #ifndef __zitarevdsp_H__
7 #define __zitarevdsp_H__
8
9 // NOTE: ANY INCLUDE-GUARD HERE MUST BE DERIVED FROM THE CLASS NAME
10 //
11 // faust2header.cpp - FAUST Architecture File
12 // This is a simple variation of matlabplot.cpp in the Faust distribution
13 // aimed at creating a simple C++ header file (.h) containing a Faust DSP.
14 // See the Makefile for how to use it.
15
16 /************************** BEGIN dsp.h **************************/
17 /************************************************************************
18 FAUST Architecture File
19 Copyright (C) 2003-2017 GRAME, Centre National de Creation Musicale
20 ---------------------------------------------------------------------
21 This Architecture section is free software; you can redistribute it
22 and/or modify it under the terms of the GNU General Public License
23 as published by the Free Software Foundation; either version 3 of
24 the License, or (at your option) any later version.
25
26 This program is distributed in the hope that it will be useful,
27 but WITHOUT ANY WARRANTY; without even the implied warranty of
28 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 GNU General Public License for more details.
30
31 You should have received a copy of the GNU General Public License
32 along with this program; If not, see <http://www.gnu.org/licenses/>.
33
34 EXCEPTION : As a special exception, you may create a larger work
35 that contains this FAUST architecture section and distribute
36 that work under terms of your choice, so long as this FAUST
37 architecture section is not modified.
38 ************************************************************************/
39
40 #ifndef __dsp__
41 #define __dsp__
42
43 #include <string>
44 #include <vector>
45
46 #ifndef FAUSTFLOAT
47 #define FAUSTFLOAT float
48 #endif
49
50 struct UI;
51 struct Meta;
52
53 /**
54 * DSP memory manager.
55 */
56
57 struct dsp_memory_manager {
58
59 virtual ~dsp_memory_manager() {}
60
61 virtual void* allocate(size_t size) = 0;
62 virtual void destroy(void* ptr) = 0;
63
64 };
65
66 /**
67 * Signal processor definition.
68 */
69
70 class dsp {
71
72 public:
73
74 dsp() {}
75 virtual ~dsp() {}
76
77 /* Return instance number of audio inputs */
78 virtual int getNumInputs() = 0;
79
80 /* Return instance number of audio outputs */
81 virtual int getNumOutputs() = 0;
82
83 /**
84 * Trigger the ui_interface parameter with instance specific calls
85 * to 'openTabBox', 'addButton', 'addVerticalSlider'... in order to build the UI.
86 *
87 * @param ui_interface - the user interface builder
88 */
89 virtual void buildUserInterface(UI* ui_interface) = 0;
90
91 /* Returns the sample rate currently used by the instance */
92 virtual int getSampleRate() = 0;
93
94 /**
95 * Global init, calls the following methods:
96 * - static class 'classInit': static tables initialization
97 * - 'instanceInit': constants and instance state initialization
98 *
99 * @param sample_rate - the sampling rate in Hertz
100 */
101 virtual void init(int sample_rate) = 0;
102
103 /**
104 * Init instance state
105 *
106 * @param sample_rate - the sampling rate in Hertz
107 */
108 virtual void instanceInit(int sample_rate) = 0;
109
110 /**
111 * Init instance constant state
112 *
113 * @param sample_rate - the sampling rate in Hertz
114 */
115 virtual void instanceConstants(int sample_rate) = 0;
116
117 /* Init default control parameters values */
118 virtual void instanceResetUserInterface() = 0;
119
120 /* Init instance state (delay lines...) */
121 virtual void instanceClear() = 0;
122
123 /**
124 * Return a clone of the instance.
125 *
126 * @return a copy of the instance on success, otherwise a null pointer.
127 */
128 virtual dsp* clone() = 0;
129
130 /**
131 * Trigger the Meta* parameter with instance specific calls to 'declare' (key, value) metadata.
132 *
133 * @param m - the Meta* meta user
134 */
135 virtual void metadata(Meta* m) = 0;
136
137 /**
138 * DSP instance computation, to be called with successive in/out audio buffers.
139 *
140 * @param count - the number of frames to compute
141 * @param inputs - the input audio buffers as an array of non-interleaved FAUSTFLOAT samples (eiher float, double or quad)
142 * @param outputs - the output audio buffers as an array of non-interleaved FAUSTFLOAT samples (eiher float, double or quad)
143 *
144 */
145 virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) = 0;
146
147 /**
148 * DSP instance computation: alternative method to be used by subclasses.
149 *
150 * @param date_usec - the timestamp in microsec given by audio driver.
151 * @param count - the number of frames to compute
152 * @param inputs - the input audio buffers as an array of non-interleaved FAUSTFLOAT samples (either float, double or quad)
153 * @param outputs - the output audio buffers as an array of non-interleaved FAUSTFLOAT samples (either float, double or quad)
154 *
155 */
156 virtual void compute(double /*date_usec*/, int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { compute(count, inputs, outputs); }
157
158 };
159
160 /**
161 * Generic DSP decorator.
162 */
163
164 class decorator_dsp : public dsp {
165
166 protected:
167
168 dsp* fDSP;
169
170 public:
171
172 decorator_dsp(dsp* dsp = nullptr):fDSP(dsp) {}
173 virtual ~decorator_dsp() { delete fDSP; }
174
175 virtual int getNumInputs() { return fDSP->getNumInputs(); }
176 virtual int getNumOutputs() { return fDSP->getNumOutputs(); }
177 virtual void buildUserInterface(UI* ui_interface) { fDSP->buildUserInterface(ui_interface); }
178 virtual int getSampleRate() { return fDSP->getSampleRate(); }
179 virtual void init(int sample_rate) { fDSP->init(sample_rate); }
180 virtual void instanceInit(int sample_rate) { fDSP->instanceInit(sample_rate); }
181 virtual void instanceConstants(int sample_rate) { fDSP->instanceConstants(sample_rate); }
182 virtual void instanceResetUserInterface() { fDSP->instanceResetUserInterface(); }
183 virtual void instanceClear() { fDSP->instanceClear(); }
184 virtual decorator_dsp* clone() { return new decorator_dsp(fDSP->clone()); }
185 virtual void metadata(Meta* m) { fDSP->metadata(m); }
186 // Beware: subclasses usually have to overload the two 'compute' methods
187 virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { fDSP->compute(count, inputs, outputs); }
188 virtual void compute(double date_usec, int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { fDSP->compute(date_usec, count, inputs, outputs); }
189
190 };
191
192 /**
193 * DSP factory class.
194 */
195
196 class dsp_factory {
197
198 protected:
199
200 // So that to force sub-classes to use deleteDSPFactory(dsp_factory* factory);
201 virtual ~dsp_factory() {}
202
203 public:
204
205 virtual std::string getName() = 0;
206 virtual std::string getSHAKey() = 0;
207 virtual std::string getDSPCode() = 0;
208 virtual std::string getCompileOptions() = 0;
209 virtual std::vector<std::string> getLibraryList() = 0;
210 virtual std::vector<std::string> getIncludePathnames() = 0;
211
212 virtual dsp* createDSPInstance() = 0;
213
214 virtual void setMemoryManager(dsp_memory_manager* manager) = 0;
215 virtual dsp_memory_manager* getMemoryManager() = 0;
216
217 };
218
219 /**
220 * On Intel set FZ (Flush to Zero) and DAZ (Denormals Are Zero)
221 * flags to avoid costly denormals.
222 */
223
224 #ifdef __SSE__
225 #include <xmmintrin.h>
226 #ifdef __SSE2__
227 #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8040)
228 #else
229 #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8000)
230 #endif
231 #else
232 #define AVOIDDENORMALS
233 #endif
234
235 #endif
236 /************************** END dsp.h **************************/
237
238 /************************** BEGIN APIUI.h **************************/
239 /************************************************************************
240 FAUST Architecture File
241 Copyright (C) 2003-2017 GRAME, Centre National de Creation Musicale
242 ---------------------------------------------------------------------
243 This Architecture section is free software; you can redistribute it
244 and/or modify it under the terms of the GNU General Public License
245 as published by the Free Software Foundation; either version 3 of
246 the License, or (at your option) any later version.
247
248 This program is distributed in the hope that it will be useful,
249 but WITHOUT ANY WARRANTY; without even the implied warranty of
250 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
251 GNU General Public License for more details.
252
253 You should have received a copy of the GNU General Public License
254 along with this program; If not, see <http://www.gnu.org/licenses/>.
255
256 EXCEPTION : As a special exception, you may create a larger work
257 that contains this FAUST architecture section and distribute
258 that work under terms of your choice, so long as this FAUST
259 architecture section is not modified.
260 ************************************************************************/
261
262 #ifndef API_UI_H
263 #define API_UI_H
264
265 #include <sstream>
266 #include <string>
267 #include <vector>
268 #include <iostream>
269 #include <map>
270
271 /************************** BEGIN meta.h **************************/
272 /************************************************************************
273 FAUST Architecture File
274 Copyright (C) 2003-2017 GRAME, Centre National de Creation Musicale
275 ---------------------------------------------------------------------
276 This Architecture section is free software; you can redistribute it
277 and/or modify it under the terms of the GNU General Public License
278 as published by the Free Software Foundation; either version 3 of
279 the License, or (at your option) any later version.
280
281 This program is distributed in the hope that it will be useful,
282 but WITHOUT ANY WARRANTY; without even the implied warranty of
283 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
284 GNU General Public License for more details.
285
286 You should have received a copy of the GNU General Public License
287 along with this program; If not, see <http://www.gnu.org/licenses/>.
288
289 EXCEPTION : As a special exception, you may create a larger work
290 that contains this FAUST architecture section and distribute
291 that work under terms of your choice, so long as this FAUST
292 architecture section is not modified.
293 ************************************************************************/
294
295 #ifndef __meta__
296 #define __meta__
297
298 struct Meta
299 {
300 virtual ~Meta() {};
301 virtual void declare(const char* key, const char* value) = 0;
302
303 };
304
305 #endif
306 /************************** END meta.h **************************/
307 /************************** BEGIN UI.h **************************/
308 /************************************************************************
309 FAUST Architecture File
310 Copyright (C) 2003-2020 GRAME, Centre National de Creation Musicale
311 ---------------------------------------------------------------------
312 This Architecture section is free software; you can redistribute it
313 and/or modify it under the terms of the GNU General Public License
314 as published by the Free Software Foundation; either version 3 of
315 the License, or (at your option) any later version.
316
317 This program is distributed in the hope that it will be useful,
318 but WITHOUT ANY WARRANTY; without even the implied warranty of
319 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
320 GNU General Public License for more details.
321
322 You should have received a copy of the GNU General Public License
323 along with this program; If not, see <http://www.gnu.org/licenses/>.
324
325 EXCEPTION : As a special exception, you may create a larger work
326 that contains this FAUST architecture section and distribute
327 that work under terms of your choice, so long as this FAUST
328 architecture section is not modified.
329 ************************************************************************/
330
331 #ifndef __UI_H__
332 #define __UI_H__
333
334 #ifndef FAUSTFLOAT
335 #define FAUSTFLOAT float
336 #endif
337
338 /*******************************************************************************
339 * UI : Faust DSP User Interface
340 * User Interface as expected by the buildUserInterface() method of a DSP.
341 * This abstract class contains only the method that the Faust compiler can
342 * generate to describe a DSP user interface.
343 ******************************************************************************/
344
345 struct Soundfile;
346
347 template <typename REAL>
348 struct UIReal
349 {
350 UIReal() {}
351 virtual ~UIReal() {}
352
353 // -- widget's layouts
354
355 virtual void openTabBox(const char* label) = 0;
356 virtual void openHorizontalBox(const char* label) = 0;
357 virtual void openVerticalBox(const char* label) = 0;
358 virtual void closeBox() = 0;
359
360 // -- active widgets
361
362 virtual void addButton(const char* label, REAL* zone) = 0;
363 virtual void addCheckButton(const char* label, REAL* zone) = 0;
364 virtual void addVerticalSlider(const char* label, REAL* zone, REAL init, REAL min, REAL max, REAL step) = 0;
365 virtual void addHorizontalSlider(const char* label, REAL* zone, REAL init, REAL min, REAL max, REAL step) = 0;
366 virtual void addNumEntry(const char* label, REAL* zone, REAL init, REAL min, REAL max, REAL step) = 0;
367
368 // -- passive widgets
369
370 virtual void addHorizontalBargraph(const char* label, REAL* zone, REAL min, REAL max) = 0;
371 virtual void addVerticalBargraph(const char* label, REAL* zone, REAL min, REAL max) = 0;
372
373 // -- soundfiles
374
375 virtual void addSoundfile(const char* label, const char* filename, Soundfile** sf_zone) = 0;
376
377 // -- metadata declarations
378
379 virtual void declare(REAL* zone, const char* key, const char* val) {}
380 };
381
382 struct UI : public UIReal<FAUSTFLOAT>
383 {
384 UI() {}
385 virtual ~UI() {}
386 };
387
388 #endif
389 /************************** END UI.h **************************/
390 /************************** BEGIN PathBuilder.h **************************/
391 /************************************************************************
392 FAUST Architecture File
393 Copyright (C) 2003-2017 GRAME, Centre National de Creation Musicale
394 ---------------------------------------------------------------------
395 This Architecture section is free software; you can redistribute it
396 and/or modify it under the terms of the GNU General Public License
397 as published by the Free Software Foundation; either version 3 of
398 the License, or (at your option) any later version.
399
400 This program is distributed in the hope that it will be useful,
401 but WITHOUT ANY WARRANTY; without even the implied warranty of
402 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
403 GNU General Public License for more details.
404
405 You should have received a copy of the GNU General Public License
406 along with this program; If not, see <http://www.gnu.org/licenses/>.
407
408 EXCEPTION : As a special exception, you may create a larger work
409 that contains this FAUST architecture section and distribute
410 that work under terms of your choice, so long as this FAUST
411 architecture section is not modified.
412 ************************************************************************/
413
414 #ifndef FAUST_PATHBUILDER_H
415 #define FAUST_PATHBUILDER_H
416
417 #include <vector>
418 #include <string>
419 #include <algorithm>
420
421 /*******************************************************************************
422 * PathBuilder : Faust User Interface
423 * Helper class to build complete hierarchical path for UI items.
424 ******************************************************************************/
425
426 class PathBuilder
427 {
428
429 protected:
430
431 std::vector<std::string> fControlsLevel;
432
433 public:
434
435 PathBuilder() {}
436 virtual ~PathBuilder() {}
437
438 std::string buildPath(const std::string& label)
439 {
440 std::string res = "/";
441 for (size_t i = 0; i < fControlsLevel.size(); i++) {
442 res += fControlsLevel[i];
443 res += "/";
444 }
445 res += label;
446 std::replace(res.begin(), res.end(), ' ', '_');
447 return res;
448 }
449
450 std::string buildLabel(std::string label)
451 {
452 std::replace(label.begin(), label.end(), ' ', '_');
453 return label;
454 }
455
456 void pushLabel(const std::string& label) { fControlsLevel.push_back(label); }
457 void popLabel() { fControlsLevel.pop_back(); }
458
459 };
460
461 #endif // FAUST_PATHBUILDER_H
462 /************************** END PathBuilder.h **************************/
463 /************************** BEGIN ValueConverter.h **************************/
464 /************************************************************************
465 FAUST Architecture File
466 Copyright (C) 2003-2017 GRAME, Centre National de Creation Musicale
467 ---------------------------------------------------------------------
468 This Architecture section is free software; you can redistribute it
469 and/or modify it under the terms of the GNU General Public License
470 as published by the Free Software Foundation; either version 3 of
471 the License, or (at your option) any later version.
472
473 This program is distributed in the hope that it will be useful,
474 but WITHOUT ANY WARRANTY; without even the implied warranty of
475 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
476 GNU General Public License for more details.
477
478 You should have received a copy of the GNU General Public License
479 along with this program; If not, see <http://www.gnu.org/licenses/>.
480
481 EXCEPTION : As a special exception, you may create a larger work
482 that contains this FAUST architecture section and distribute
483 that work under terms of your choice, so long as this FAUST
484 architecture section is not modified.
485 ************************************************************************/
486
487 #ifndef __ValueConverter__
488 #define __ValueConverter__
489
490 /***************************************************************************************
491 ValueConverter.h
492 (GRAME, Copyright 2015-2019)
493
494 Set of conversion objects used to map user interface values (for example a gui slider
495 delivering values between 0 and 1) to faust values (for example a vslider between
496 20 and 20000) using a log scale.
497
498 -- Utilities
499
500 Range(lo,hi) : clip a value x between lo and hi
501 Interpolator(lo,hi,v1,v2) : Maps a value x between lo and hi to a value y between v1 and v2
502 Interpolator3pt(lo,mi,hi,v1,vm,v2) : Map values between lo mid hi to values between v1 vm v2
503
504 -- Value Converters
505
506 ValueConverter::ui2faust(x)
507 ValueConverter::faust2ui(x)
508
509 -- ValueConverters used for sliders depending of the scale
510
511 LinearValueConverter(umin, umax, fmin, fmax)
512 LinearValueConverter2(lo, mi, hi, v1, vm, v2) using 2 segments
513 LogValueConverter(umin, umax, fmin, fmax)
514 ExpValueConverter(umin, umax, fmin, fmax)
515
516 -- ValueConverters used for accelerometers based on 3 points
517
518 AccUpConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 0
519 AccDownConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 1
520 AccUpDownConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 2
521 AccDownUpConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 3
522
523 -- lists of ZoneControl are used to implement accelerometers metadata for each axes
524
525 ZoneControl(zone, valueConverter) : a zone with an accelerometer data converter
526
527 -- ZoneReader are used to implement screencolor metadata
528
529 ZoneReader(zone, valueConverter) : a zone with a data converter
530
531 ****************************************************************************************/
532
533 #include <float.h>
534 #include <algorithm> // std::max
535 #include <cmath>
536 #include <vector>
537 #include <assert.h>
538
539 //--------------------------------------------------------------------------------------
540 // Interpolator(lo,hi,v1,v2)
541 // Maps a value x between lo and hi to a value y between v1 and v2
542 // y = v1 + (x-lo)/(hi-lo)*(v2-v1)
543 // y = v1 + (x-lo) * coef with coef = (v2-v1)/(hi-lo)
544 // y = v1 + x*coef - lo*coef
545 // y = v1 - lo*coef + x*coef
546 // y = offset + x*coef with offset = v1 - lo*coef
547 //--------------------------------------------------------------------------------------
548 class Interpolator
549 {
550 private:
551
552 //--------------------------------------------------------------------------------------
553 // Range(lo,hi) clip a value between lo and hi
554 //--------------------------------------------------------------------------------------
555 struct Range
556 {
557 double fLo;
558 double fHi;
559
560 Range(double x, double y) : fLo(std::min<double>(x,y)), fHi(std::max<double>(x,y)) {}
561 double operator()(double x) { return (x<fLo) ? fLo : (x>fHi) ? fHi : x; }
562 };
563
564
565 Range fRange;
566 double fCoef;
567 double fOffset;
568
569 public:
570
571 Interpolator(double lo, double hi, double v1, double v2) : fRange(lo,hi)
572 {
573 if (hi != lo) {
574 // regular case
575 fCoef = (v2-v1)/(hi-lo);
576 fOffset = v1 - lo*fCoef;
577 } else {
578 // degenerate case, avoids division by zero
579 fCoef = 0;
580 fOffset = (v1+v2)/2;
581 }
582 }
583 double operator()(double v)
584 {
585 double x = fRange(v);
586 return fOffset + x*fCoef;
587 }
588
589 void getLowHigh(double& amin, double& amax)
590 {
591 amin = fRange.fLo;
592 amax = fRange.fHi;
593 }
594 };
595
596 //--------------------------------------------------------------------------------------
597 // Interpolator3pt(lo,mi,hi,v1,vm,v2)
598 // Map values between lo mid hi to values between v1 vm v2
599 //--------------------------------------------------------------------------------------
600 class Interpolator3pt
601 {
602
603 private:
604
605 Interpolator fSegment1;
606 Interpolator fSegment2;
607 double fMid;
608
609 public:
610
611 Interpolator3pt(double lo, double mi, double hi, double v1, double vm, double v2) :
612 fSegment1(lo, mi, v1, vm),
613 fSegment2(mi, hi, vm, v2),
614 fMid(mi) {}
615 double operator()(double x) { return (x < fMid) ? fSegment1(x) : fSegment2(x); }
616
617 void getMappingValues(double& amin, double& amid, double& amax)
618 {
619 fSegment1.getLowHigh(amin, amid);
620 fSegment2.getLowHigh(amid, amax);
621 }
622 };
623
624 //--------------------------------------------------------------------------------------
625 // Abstract ValueConverter class. Converts values between UI and Faust representations
626 //--------------------------------------------------------------------------------------
627 class ValueConverter
628 {
629
630 public:
631
632 virtual ~ValueConverter() {}
633 virtual double ui2faust(double x) = 0;
634 virtual double faust2ui(double x) = 0;
635 };
636
637 //--------------------------------------------------------------------------------------
638 // A converter than can be updated
639 //--------------------------------------------------------------------------------------
640
641 class UpdatableValueConverter : public ValueConverter {
642
643 protected:
644
645 bool fActive;
646
647 public:
648
649 UpdatableValueConverter():fActive(true)
650 {}
651 virtual ~UpdatableValueConverter()
652 {}
653
654 virtual void setMappingValues(double amin, double amid, double amax, double min, double init, double max) = 0;
655 virtual void getMappingValues(double& amin, double& amid, double& amax) = 0;
656
657 void setActive(bool on_off) { fActive = on_off; }
658 bool getActive() { return fActive; }
659
660 };
661
662
663 //--------------------------------------------------------------------------------------
664 // Linear conversion between ui and Faust values
665 //--------------------------------------------------------------------------------------
666 class LinearValueConverter : public ValueConverter
667 {
668
669 private:
670
671 Interpolator fUI2F;
672 Interpolator fF2UI;
673
674 public:
675
676 LinearValueConverter(double umin, double umax, double fmin, double fmax) :
677 fUI2F(umin,umax,fmin,fmax), fF2UI(fmin,fmax,umin,umax)
678 {}
679
680 LinearValueConverter() : fUI2F(0.,0.,0.,0.), fF2UI(0.,0.,0.,0.)
681 {}
682 virtual double ui2faust(double x) { return fUI2F(x); }
683 virtual double faust2ui(double x) { return fF2UI(x); }
684
685 };
686
687 //--------------------------------------------------------------------------------------
688 // Two segments linear conversion between ui and Faust values
689 //--------------------------------------------------------------------------------------
690 class LinearValueConverter2 : public UpdatableValueConverter
691 {
692
693 private:
694
695 Interpolator3pt fUI2F;
696 Interpolator3pt fF2UI;
697
698 public:
699
700 LinearValueConverter2(double amin, double amid, double amax, double min, double init, double max) :
701 fUI2F(amin, amid, amax, min, init, max), fF2UI(min, init, max, amin, amid, amax)
702 {}
703
704 LinearValueConverter2() : fUI2F(0.,0.,0.,0.,0.,0.), fF2UI(0.,0.,0.,0.,0.,0.)
705 {}
706
707 virtual double ui2faust(double x) { return fUI2F(x); }
708 virtual double faust2ui(double x) { return fF2UI(x); }
709
710 virtual void setMappingValues(double amin, double amid, double amax, double min, double init, double max)
711 {
712 fUI2F = Interpolator3pt(amin, amid, amax, min, init, max);
713 fF2UI = Interpolator3pt(min, init, max, amin, amid, amax);
714 }
715
716 virtual void getMappingValues(double& amin, double& amid, double& amax)
717 {
718 fUI2F.getMappingValues(amin, amid, amax);
719 }
720
721 };
722
723 //--------------------------------------------------------------------------------------
724 // Logarithmic conversion between ui and Faust values
725 //--------------------------------------------------------------------------------------
726 class LogValueConverter : public LinearValueConverter
727 {
728
729 public:
730
731 LogValueConverter(double umin, double umax, double fmin, double fmax) :
732 LinearValueConverter(umin, umax, std::log(std::max<double>(DBL_MIN, fmin)), std::log(std::max<double>(DBL_MIN, fmax)))
733 {}
734
735 virtual double ui2faust(double x) { return std::exp(LinearValueConverter::ui2faust(x)); }
736 virtual double faust2ui(double x) { return LinearValueConverter::faust2ui(std::log(std::max<double>(x, DBL_MIN))); }
737
738 };
739
740 //--------------------------------------------------------------------------------------
741 // Exponential conversion between ui and Faust values
742 //--------------------------------------------------------------------------------------
743 class ExpValueConverter : public LinearValueConverter
744 {
745
746 public:
747
748 ExpValueConverter(double umin, double umax, double fmin, double fmax) :
749 LinearValueConverter(umin, umax, std::min<double>(DBL_MAX, std::exp(fmin)), std::min<double>(DBL_MAX, std::exp(fmax)))
750 {}
751
752 virtual double ui2faust(double x) { return std::log(LinearValueConverter::ui2faust(x)); }
753 virtual double faust2ui(double x) { return LinearValueConverter::faust2ui(std::min<double>(DBL_MAX, std::exp(x))); }
754
755 };
756
757 //--------------------------------------------------------------------------------------
758 // Convert accelerometer or gyroscope values to Faust values
759 // Using an Up curve (curve 0)
760 //--------------------------------------------------------------------------------------
761 class AccUpConverter : public UpdatableValueConverter
762 {
763
764 private:
765
766 Interpolator3pt fA2F;
767 Interpolator3pt fF2A;
768
769 public:
770
771 AccUpConverter(double amin, double amid, double amax, double fmin, double fmid, double fmax) :
772 fA2F(amin,amid,amax,fmin,fmid,fmax),
773 fF2A(fmin,fmid,fmax,amin,amid,amax)
774 {}
775
776 virtual double ui2faust(double x) { return fA2F(x); }
777 virtual double faust2ui(double x) { return fF2A(x); }
778
779 virtual void setMappingValues(double amin, double amid, double amax, double fmin, double fmid, double fmax)
780 {
781 //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccUpConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax);
782 fA2F = Interpolator3pt(amin, amid, amax, fmin, fmid, fmax);
783 fF2A = Interpolator3pt(fmin, fmid, fmax, amin, amid, amax);
784 }
785
786 virtual void getMappingValues(double& amin, double& amid, double& amax)
787 {
788 fA2F.getMappingValues(amin, amid, amax);
789 }
790
791 };
792
793 //--------------------------------------------------------------------------------------
794 // Convert accelerometer or gyroscope values to Faust values
795 // Using a Down curve (curve 1)
796 //--------------------------------------------------------------------------------------
797 class AccDownConverter : public UpdatableValueConverter
798 {
799
800 private:
801
802 Interpolator3pt fA2F;
803 Interpolator3pt fF2A;
804
805 public:
806
807 AccDownConverter(double amin, double amid, double amax, double fmin, double fmid, double fmax) :
808 fA2F(amin,amid,amax,fmax,fmid,fmin),
809 fF2A(fmin,fmid,fmax,amax,amid,amin)
810 {}
811
812 virtual double ui2faust(double x) { return fA2F(x); }
813 virtual double faust2ui(double x) { return fF2A(x); }
814
815 virtual void setMappingValues(double amin, double amid, double amax, double fmin, double fmid, double fmax)
816 {
817 //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccDownConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax);
818 fA2F = Interpolator3pt(amin, amid, amax, fmax, fmid, fmin);
819 fF2A = Interpolator3pt(fmin, fmid, fmax, amax, amid, amin);
820 }
821
822 virtual void getMappingValues(double& amin, double& amid, double& amax)
823 {
824 fA2F.getMappingValues(amin, amid, amax);
825 }
826 };
827
828 //--------------------------------------------------------------------------------------
829 // Convert accelerometer or gyroscope values to Faust values
830 // Using an Up-Down curve (curve 2)
831 //--------------------------------------------------------------------------------------
832 class AccUpDownConverter : public UpdatableValueConverter
833 {
834
835 private:
836
837 Interpolator3pt fA2F;
838 Interpolator fF2A;
839
840 public:
841
842 AccUpDownConverter(double amin, double amid, double amax, double fmin, double fmid, double fmax) :
843 fA2F(amin,amid,amax,fmin,fmax,fmin),
844 fF2A(fmin,fmax,amin,amax) // Special, pseudo inverse of a non monotonic function
845 {}
846
847 virtual double ui2faust(double x) { return fA2F(x); }
848 virtual double faust2ui(double x) { return fF2A(x); }
849
850 virtual void setMappingValues(double amin, double amid, double amax, double fmin, double fmid, double fmax)
851 {
852 //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccUpDownConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax);
853 fA2F = Interpolator3pt(amin, amid, amax, fmin, fmax, fmin);
854 fF2A = Interpolator(fmin, fmax, amin, amax);
855 }
856
857 virtual void getMappingValues(double& amin, double& amid, double& amax)
858 {
859 fA2F.getMappingValues(amin, amid, amax);
860 }
861 };
862
863 //--------------------------------------------------------------------------------------
864 // Convert accelerometer or gyroscope values to Faust values
865 // Using a Down-Up curve (curve 3)
866 //--------------------------------------------------------------------------------------
867 class AccDownUpConverter : public UpdatableValueConverter
868 {
869
870 private:
871
872 Interpolator3pt fA2F;
873 Interpolator fF2A;
874
875 public:
876
877 AccDownUpConverter(double amin, double amid, double amax, double fmin, double fmid, double fmax) :
878 fA2F(amin,amid,amax,fmax,fmin,fmax),
879 fF2A(fmin,fmax,amin,amax) // Special, pseudo inverse of a non monotonic function
880 {}
881
882 virtual double ui2faust(double x) { return fA2F(x); }
883 virtual double faust2ui(double x) { return fF2A(x); }
884
885 virtual void setMappingValues(double amin, double amid, double amax, double fmin, double fmid, double fmax)
886 {
887 //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccDownUpConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax);
888 fA2F = Interpolator3pt(amin, amid, amax, fmax, fmin, fmax);
889 fF2A = Interpolator(fmin, fmax, amin, amax);
890 }
891
892 virtual void getMappingValues(double& amin, double& amid, double& amax)
893 {
894 fA2F.getMappingValues(amin, amid, amax);
895 }
896 };
897
898 //--------------------------------------------------------------------------------------
899 // Base class for ZoneControl
900 //--------------------------------------------------------------------------------------
901 class ZoneControl
902 {
903
904 protected:
905
906 FAUSTFLOAT* fZone;
907
908 public:
909
910 ZoneControl(FAUSTFLOAT* zone) : fZone(zone) {}
911 virtual ~ZoneControl() {}
912
913 virtual void update(double v) const {}
914
915 virtual void setMappingValues(int curve, double amin, double amid, double amax, double min, double init, double max) {}
916 virtual void getMappingValues(double& amin, double& amid, double& amax) {}
917
918 FAUSTFLOAT* getZone() { return fZone; }
919
920 virtual void setActive(bool on_off) {}
921 virtual bool getActive() { return false; }
922
923 virtual int getCurve() { return -1; }
924
925 };
926
927 //--------------------------------------------------------------------------------------
928 // Useful to implement accelerometers metadata as a list of ZoneControl for each axes
929 //--------------------------------------------------------------------------------------
930 class ConverterZoneControl : public ZoneControl
931 {
932
933 protected:
934
935 ValueConverter* fValueConverter;
936
937 public:
938
939 ConverterZoneControl(FAUSTFLOAT* zone, ValueConverter* converter) : ZoneControl(zone), fValueConverter(converter) {}
940 virtual ~ConverterZoneControl() { delete fValueConverter; } // Assuming fValueConverter is not kept elsewhere...
941
942 virtual void update(double v) const { *fZone = fValueConverter->ui2faust(v); }
943
944 ValueConverter* getConverter() { return fValueConverter; }
945
946 };
947
948 //--------------------------------------------------------------------------------------
949 // Association of a zone and a four value converter, each one for each possible curve.
950 // Useful to implement accelerometers metadata as a list of ZoneControl for each axes
951 //--------------------------------------------------------------------------------------
952 class CurveZoneControl : public ZoneControl
953 {
954
955 private:
956
957 std::vector<UpdatableValueConverter*> fValueConverters;
958 int fCurve;
959
960 public:
961
962 CurveZoneControl(FAUSTFLOAT* zone, int curve, double amin, double amid, double amax, double min, double init, double max) : ZoneControl(zone), fCurve(0)
963 {
964 assert(curve >= 0 && curve <= 3);
965 fValueConverters.push_back(new AccUpConverter(amin, amid, amax, min, init, max));
966 fValueConverters.push_back(new AccDownConverter(amin, amid, amax, min, init, max));
967 fValueConverters.push_back(new AccUpDownConverter(amin, amid, amax, min, init, max));
968 fValueConverters.push_back(new AccDownUpConverter(amin, amid, amax, min, init, max));
969 fCurve = curve;
970 }
971 virtual ~CurveZoneControl()
972 {
973 std::vector<UpdatableValueConverter*>::iterator it;
974 for (it = fValueConverters.begin(); it != fValueConverters.end(); it++) {
975 delete(*it);
976 }
977 }
978 void update(double v) const { if (fValueConverters[fCurve]->getActive()) *fZone = fValueConverters[fCurve]->ui2faust(v); }
979
980 void setMappingValues(int curve, double amin, double amid, double amax, double min, double init, double max)
981 {
982 fValueConverters[curve]->setMappingValues(amin, amid, amax, min, init, max);
983 fCurve = curve;
984 }
985
986 void getMappingValues(double& amin, double& amid, double& amax)
987 {
988 fValueConverters[fCurve]->getMappingValues(amin, amid, amax);
989 }
990
991 void setActive(bool on_off)
992 {
993 std::vector<UpdatableValueConverter*>::iterator it;
994 for (it = fValueConverters.begin(); it != fValueConverters.end(); it++) {
995 (*it)->setActive(on_off);
996 }
997 }
998
999 int getCurve() { return fCurve; }
1000 };
1001
1002 class ZoneReader
1003 {
1004
1005 private:
1006
1007 FAUSTFLOAT* fZone;
1008 Interpolator fInterpolator;
1009
1010 public:
1011
1012 ZoneReader(FAUSTFLOAT* zone, double lo, double hi) : fZone(zone), fInterpolator(lo, hi, 0, 255) {}
1013
1014 virtual ~ZoneReader() {}
1015
1016 int getValue()
1017 {
1018 return (fZone != nullptr) ? int(fInterpolator(*fZone)) : 127;
1019 }
1020
1021 };
1022
1023 #endif
1024 /************************** END ValueConverter.h **************************/
1025
1026 class APIUI : public PathBuilder, public Meta, public UI
1027 {
1028 public:
1029
1030 enum ItemType { kButton = 0, kCheckButton, kVSlider, kHSlider, kNumEntry, kHBargraph, kVBargraph };
1031
1032 protected:
1033
1034 enum { kLin = 0, kLog = 1, kExp = 2 };
1035
1036 int fNumParameters;
1037 std::vector<std::string> fPaths;
1038 std::vector<std::string> fLabels;
1039 std::map<std::string, int> fPathMap;
1040 std::map<std::string, int> fLabelMap;
1041 std::vector<ValueConverter*> fConversion;
1042 std::vector<FAUSTFLOAT*> fZone;
1043 std::vector<FAUSTFLOAT> fInit;
1044 std::vector<FAUSTFLOAT> fMin;
1045 std::vector<FAUSTFLOAT> fMax;
1046 std::vector<FAUSTFLOAT> fStep;
1047 std::vector<ItemType> fItemType;
1048 std::vector<std::map<std::string, std::string> > fMetaData;
1049 std::vector<ZoneControl*> fAcc[3];
1050 std::vector<ZoneControl*> fGyr[3];
1051
1052 // Screen color control
1053 // "...[screencolor:red]..." etc.
1054 bool fHasScreenControl; // true if control screen color metadata
1055 ZoneReader* fRedReader;
1056 ZoneReader* fGreenReader;
1057 ZoneReader* fBlueReader;
1058
1059 // Current values controlled by metadata
1060 std::string fCurrentUnit;
1061 int fCurrentScale;
1062 std::string fCurrentAcc;
1063 std::string fCurrentGyr;
1064 std::string fCurrentColor;
1065 std::string fCurrentTooltip;
1066 std::map<std::string, std::string> fCurrentMetadata;
1067
1068 // Add a generic parameter
1069 virtual void addParameter(const char* label,
1070 FAUSTFLOAT* zone,
1071 FAUSTFLOAT init,
1072 FAUSTFLOAT min,
1073 FAUSTFLOAT max,
1074 FAUSTFLOAT step,
1075 ItemType type)
1076 {
1077 std::string path = buildPath(label);
1078 fPathMap[path] = fLabelMap[label] = fNumParameters++;
1079 fPaths.push_back(path);
1080 fLabels.push_back(label);
1081 fZone.push_back(zone);
1082 fInit.push_back(init);
1083 fMin.push_back(min);
1084 fMax.push_back(max);
1085 fStep.push_back(step);
1086 fItemType.push_back(type);
1087
1088 // handle scale metadata
1089 switch (fCurrentScale) {
1090 case kLin:
1091 fConversion.push_back(new LinearValueConverter(0, 1, min, max));
1092 break;
1093 case kLog:
1094 fConversion.push_back(new LogValueConverter(0, 1, min, max));
1095 break;
1096 case kExp: fConversion.push_back(new ExpValueConverter(0, 1, min, max));
1097 break;
1098 }
1099 fCurrentScale = kLin;
1100
1101 if (fCurrentAcc.size() > 0 && fCurrentGyr.size() > 0) {
1102 std::cerr << "warning : 'acc' and 'gyr' metadata used for the same " << label << " parameter !!\n";
1103 }
1104
1105 // handle acc metadata "...[acc : <axe> <curve> <amin> <amid> <amax>]..."
1106 if (fCurrentAcc.size() > 0) {
1107 std::istringstream iss(fCurrentAcc);
1108 int axe, curve;
1109 double amin, amid, amax;
1110 iss >> axe >> curve >> amin >> amid >> amax;
1111
1112 if ((0 <= axe) && (axe < 3) &&
1113 (0 <= curve) && (curve < 4) &&
1114 (amin < amax) && (amin <= amid) && (amid <= amax))
1115 {
1116 fAcc[axe].push_back(new CurveZoneControl(zone, curve, amin, amid, amax, min, init, max));
1117 } else {
1118 std::cerr << "incorrect acc metadata : " << fCurrentAcc << std::endl;
1119 }
1120 fCurrentAcc = "";
1121 }
1122
1123 // handle gyr metadata "...[gyr : <axe> <curve> <amin> <amid> <amax>]..."
1124 if (fCurrentGyr.size() > 0) {
1125 std::istringstream iss(fCurrentGyr);
1126 int axe, curve;
1127 double amin, amid, amax;
1128 iss >> axe >> curve >> amin >> amid >> amax;
1129
1130 if ((0 <= axe) && (axe < 3) &&
1131 (0 <= curve) && (curve < 4) &&
1132 (amin < amax) && (amin <= amid) && (amid <= amax))
1133 {
1134 fGyr[axe].push_back(new CurveZoneControl(zone, curve, amin, amid, amax, min, init, max));
1135 } else {
1136 std::cerr << "incorrect gyr metadata : " << fCurrentGyr << std::endl;
1137 }
1138 fCurrentGyr = "";
1139 }
1140
1141 // handle screencolor metadata "...[screencolor:red|green|blue|white]..."
1142 if (fCurrentColor.size() > 0) {
1143 if ((fCurrentColor == "red") && (fRedReader == 0)) {
1144 fRedReader = new ZoneReader(zone, min, max);
1145 fHasScreenControl = true;
1146 } else if ((fCurrentColor == "green") && (fGreenReader == 0)) {
1147 fGreenReader = new ZoneReader(zone, min, max);
1148 fHasScreenControl = true;
1149 } else if ((fCurrentColor == "blue") && (fBlueReader == 0)) {
1150 fBlueReader = new ZoneReader(zone, min, max);
1151 fHasScreenControl = true;
1152 } else if ((fCurrentColor == "white") && (fRedReader == 0) && (fGreenReader == 0) && (fBlueReader == 0)) {
1153 fRedReader = new ZoneReader(zone, min, max);
1154 fGreenReader = new ZoneReader(zone, min, max);
1155 fBlueReader = new ZoneReader(zone, min, max);
1156 fHasScreenControl = true;
1157 } else {
1158 std::cerr << "incorrect screencolor metadata : " << fCurrentColor << std::endl;
1159 }
1160 }
1161 fCurrentColor = "";
1162
1163 fMetaData.push_back(fCurrentMetadata);
1164 fCurrentMetadata.clear();
1165 }
1166
1167 int getZoneIndex(std::vector<ZoneControl*>* table, int p, int val)
1168 {
1169 FAUSTFLOAT* zone = fZone[p];
1170 for (size_t i = 0; i < table[val].size(); i++) {
1171 if (zone == table[val][i]->getZone()) return int(i);
1172 }
1173 return -1;
1174 }
1175
1176 void setConverter(std::vector<ZoneControl*>* table, int p, int val, int curve, double amin, double amid, double amax)
1177 {
1178 int id1 = getZoneIndex(table, p, 0);
1179 int id2 = getZoneIndex(table, p, 1);
1180 int id3 = getZoneIndex(table, p, 2);
1181
1182 // Deactivates everywhere..
1183 if (id1 != -1) table[0][id1]->setActive(false);
1184 if (id2 != -1) table[1][id2]->setActive(false);
1185 if (id3 != -1) table[2][id3]->setActive(false);
1186
1187 if (val == -1) { // Means: no more mapping...
1188 // So stay all deactivated...
1189 } else {
1190 int id4 = getZoneIndex(table, p, val);
1191 if (id4 != -1) {
1192 // Reactivate the one we edit...
1193 table[val][id4]->setMappingValues(curve, amin, amid, amax, fMin[p], fInit[p], fMax[p]);
1194 table[val][id4]->setActive(true);
1195 } else {
1196 // Allocate a new CurveZoneControl which is 'active' by default
1197 FAUSTFLOAT* zone = fZone[p];
1198 table[val].push_back(new CurveZoneControl(zone, curve, amin, amid, amax, fMin[p], fInit[p], fMax[p]));
1199 }
1200 }
1201 }
1202
1203 void getConverter(std::vector<ZoneControl*>* table, int p, int& val, int& curve, double& amin, double& amid, double& amax)
1204 {
1205 int id1 = getZoneIndex(table, p, 0);
1206 int id2 = getZoneIndex(table, p, 1);
1207 int id3 = getZoneIndex(table, p, 2);
1208
1209 if (id1 != -1) {
1210 val = 0;
1211 curve = table[val][id1]->getCurve();
1212 table[val][id1]->getMappingValues(amin, amid, amax);
1213 } else if (id2 != -1) {
1214 val = 1;
1215 curve = table[val][id2]->getCurve();
1216 table[val][id2]->getMappingValues(amin, amid, amax);
1217 } else if (id3 != -1) {
1218 val = 2;
1219 curve = table[val][id3]->getCurve();
1220 table[val][id3]->getMappingValues(amin, amid, amax);
1221 } else {
1222 val = -1; // No mapping
1223 curve = 0;
1224 amin = -100.;
1225 amid = 0.;
1226 amax = 100.;
1227 }
1228 }
1229
1230 public:
1231
1232 enum Type { kAcc = 0, kGyr = 1, kNoType };
1233
1234 APIUI() : fNumParameters(0), fHasScreenControl(false), fRedReader(0), fGreenReader(0), fBlueReader(0), fCurrentScale(kLin)
1235 {}
1236
1237 virtual ~APIUI()
1238 {
1239 for (auto& it : fConversion) delete it;
1240 for (int i = 0; i < 3; i++) {
1241 for (auto& it : fAcc[i]) delete it;
1242 for (auto& it : fGyr[i]) delete it;
1243 }
1244 delete fRedReader;
1245 delete fGreenReader;
1246 delete fBlueReader;
1247 }
1248
1249 // -- widget's layouts
1250
1251 virtual void openTabBox(const char* label) { pushLabel(label); }
1252 virtual void openHorizontalBox(const char* label) { pushLabel(label); }
1253 virtual void openVerticalBox(const char* label) { pushLabel(label); }
1254 virtual void closeBox() { popLabel(); }
1255
1256 // -- active widgets
1257
1258 virtual void addButton(const char* label, FAUSTFLOAT* zone)
1259 {
1260 addParameter(label, zone, 0, 0, 1, 1, kButton);
1261 }
1262
1263 virtual void addCheckButton(const char* label, FAUSTFLOAT* zone)
1264 {
1265 addParameter(label, zone, 0, 0, 1, 1, kCheckButton);
1266 }
1267
1268 virtual void addVerticalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step)
1269 {
1270 addParameter(label, zone, init, min, max, step, kVSlider);
1271 }
1272
1273 virtual void addHorizontalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step)
1274 {
1275 addParameter(label, zone, init, min, max, step, kHSlider);
1276 }
1277
1278 virtual void addNumEntry(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step)
1279 {
1280 addParameter(label, zone, init, min, max, step, kNumEntry);
1281 }
1282
1283 // -- passive widgets
1284
1285 virtual void addHorizontalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max)
1286 {
1287 addParameter(label, zone, min, min, max, (max-min)/1000.0, kHBargraph);
1288 }
1289
1290 virtual void addVerticalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max)
1291 {
1292 addParameter(label, zone, min, min, max, (max-min)/1000.0, kVBargraph);
1293 }
1294
1295 // -- soundfiles
1296
1297 virtual void addSoundfile(const char* label, const char* filename, Soundfile** sf_zone) {}
1298
1299 // -- metadata declarations
1300
1301 virtual void declare(FAUSTFLOAT* zone, const char* key, const char* val)
1302 {
1303 // Keep metadata
1304 fCurrentMetadata[key] = val;
1305
1306 if (strcmp(key, "scale") == 0) {
1307 if (strcmp(val, "log") == 0) {
1308 fCurrentScale = kLog;
1309 } else if (strcmp(val, "exp") == 0) {
1310 fCurrentScale = kExp;
1311 } else {
1312 fCurrentScale = kLin;
1313 }
1314 } else if (strcmp(key, "unit") == 0) {
1315 fCurrentUnit = val;
1316 } else if (strcmp(key, "acc") == 0) {
1317 fCurrentAcc = val;
1318 } else if (strcmp(key, "gyr") == 0) {
1319 fCurrentGyr = val;
1320 } else if (strcmp(key, "screencolor") == 0) {
1321 fCurrentColor = val; // val = "red", "green", "blue" or "white"
1322 } else if (strcmp(key, "tooltip") == 0) {
1323 fCurrentTooltip = val;
1324 }
1325 }
1326
1327 virtual void declare(const char* key, const char* val)
1328 {}
1329
1330 //-------------------------------------------------------------------------------
1331 // Simple API part
1332 //-------------------------------------------------------------------------------
1333 int getParamsCount() { return fNumParameters; }
1334 int getParamIndex(const char* path)
1335 {
1336 if (fPathMap.find(path) != fPathMap.end()) {
1337 return fPathMap[path];
1338 } else if (fLabelMap.find(path) != fLabelMap.end()) {
1339 return fLabelMap[path];
1340 } else {
1341 return -1;
1342 }
1343 }
1344 const char* getParamAddress(int p) { return fPaths[p].c_str(); }
1345 const char* getParamLabel(int p) { return fLabels[p].c_str(); }
1346 std::map<const char*, const char*> getMetadata(int p)
1347 {
1348 std::map<const char*, const char*> res;
1349 std::map<std::string, std::string> metadata = fMetaData[p];
1350 for (auto it : metadata) {
1351 res[it.first.c_str()] = it.second.c_str();
1352 }
1353 return res;
1354 }
1355
1356 const char* getMetadata(int p, const char* key)
1357 {
1358 return (fMetaData[p].find(key) != fMetaData[p].end()) ? fMetaData[p][key].c_str() : "";
1359 }
1360 FAUSTFLOAT getParamMin(int p) { return fMin[p]; }
1361 FAUSTFLOAT getParamMax(int p) { return fMax[p]; }
1362 FAUSTFLOAT getParamStep(int p) { return fStep[p]; }
1363 FAUSTFLOAT getParamInit(int p) { return fInit[p]; }
1364
1365 FAUSTFLOAT* getParamZone(int p) { return fZone[p]; }
1366 FAUSTFLOAT getParamValue(int p) { return *fZone[p]; }
1367 void setParamValue(int p, FAUSTFLOAT v) { *fZone[p] = v; }
1368
1369 double getParamRatio(int p) { return fConversion[p]->faust2ui(*fZone[p]); }
1370 void setParamRatio(int p, double r) { *fZone[p] = fConversion[p]->ui2faust(r); }
1371
1372 double value2ratio(int p, double r) { return fConversion[p]->faust2ui(r); }
1373 double ratio2value(int p, double r) { return fConversion[p]->ui2faust(r); }
1374
1375 /**
1376 * Return the control type (kAcc, kGyr, or -1) for a given parameter
1377 *
1378 * @param p - the UI parameter index
1379 *
1380 * @return the type
1381 */
1382 Type getParamType(int p)
1383 {
1384 if (p >= 0) {
1385 if (getZoneIndex(fAcc, p, 0) != -1
1386 || getZoneIndex(fAcc, p, 1) != -1
1387 || getZoneIndex(fAcc, p, 2) != -1) {
1388 return kAcc;
1389 } else if (getZoneIndex(fGyr, p, 0) != -1
1390 || getZoneIndex(fGyr, p, 1) != -1
1391 || getZoneIndex(fGyr, p, 2) != -1) {
1392 return kGyr;
1393 }
1394 }
1395 return kNoType;
1396 }
1397
1398 /**
1399 * Return the Item type (kButton = 0, kCheckButton, kVSlider, kHSlider, kNumEntry, kHBargraph, kVBargraph) for a given parameter
1400 *
1401 * @param p - the UI parameter index
1402 *
1403 * @return the Item type
1404 */
1405 ItemType getParamItemType(int p)
1406 {
1407 return fItemType[p];
1408 }
1409
1410 /**
1411 * Set a new value coming from an accelerometer, propagate it to all relevant FAUSTFLOAT* zones.
1412 *
1413 * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer
1414 * @param value - the new value
1415 *
1416 */
1417 void propagateAcc(int acc, double value)
1418 {
1419 for (size_t i = 0; i < fAcc[acc].size(); i++) {
1420 fAcc[acc][i]->update(value);
1421 }
1422 }
1423
1424 /**
1425 * Used to edit accelerometer curves and mapping. Set curve and related mapping for a given UI parameter.
1426 *
1427 * @param p - the UI parameter index
1428 * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer (-1 means "no mapping")
1429 * @param curve - between 0 and 3
1430 * @param amin - mapping 'min' point
1431 * @param amid - mapping 'middle' point
1432 * @param amax - mapping 'max' point
1433 *
1434 */
1435 void setAccConverter(int p, int acc, int curve, double amin, double amid, double amax)
1436 {
1437 setConverter(fAcc, p, acc, curve, amin, amid, amax);
1438 }
1439
1440 /**
1441 * Used to edit gyroscope curves and mapping. Set curve and related mapping for a given UI parameter.
1442 *
1443 * @param p - the UI parameter index
1444 * @param acc - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope (-1 means "no mapping")
1445 * @param curve - between 0 and 3
1446 * @param amin - mapping 'min' point
1447 * @param amid - mapping 'middle' point
1448 * @param amax - mapping 'max' point
1449 *
1450 */
1451 void setGyrConverter(int p, int gyr, int curve, double amin, double amid, double amax)
1452 {
1453 setConverter(fGyr, p, gyr, curve, amin, amid, amax);
1454 }
1455
1456 /**
1457 * Used to edit accelerometer curves and mapping. Get curve and related mapping for a given UI parameter.
1458 *
1459 * @param p - the UI parameter index
1460 * @param acc - the acc value to be retrieved (-1 means "no mapping")
1461 * @param curve - the curve value to be retrieved
1462 * @param amin - the amin value to be retrieved
1463 * @param amid - the amid value to be retrieved
1464 * @param amax - the amax value to be retrieved
1465 *
1466 */
1467 void getAccConverter(int p, int& acc, int& curve, double& amin, double& amid, double& amax)
1468 {
1469 getConverter(fAcc, p, acc, curve, amin, amid, amax);
1470 }
1471
1472 /**
1473 * Used to edit gyroscope curves and mapping. Get curve and related mapping for a given UI parameter.
1474 *
1475 * @param p - the UI parameter index
1476 * @param gyr - the gyr value to be retrieved (-1 means "no mapping")
1477 * @param curve - the curve value to be retrieved
1478 * @param amin - the amin value to be retrieved
1479 * @param amid - the amid value to be retrieved
1480 * @param amax - the amax value to be retrieved
1481 *
1482 */
1483 void getGyrConverter(int p, int& gyr, int& curve, double& amin, double& amid, double& amax)
1484 {
1485 getConverter(fGyr, p, gyr, curve, amin, amid, amax);
1486 }
1487
1488 /**
1489 * Set a new value coming from an gyroscope, propagate it to all relevant FAUSTFLOAT* zones.
1490 *
1491 * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope
1492 * @param value - the new value
1493 *
1494 */
1495 void propagateGyr(int gyr, double value)
1496 {
1497 for (size_t i = 0; i < fGyr[gyr].size(); i++) {
1498 fGyr[gyr][i]->update(value);
1499 }
1500 }
1501
1502 /**
1503 * Get the number of FAUSTFLOAT* zones controlled with the accelerometer
1504 *
1505 * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer
1506 * @return the number of zones
1507 *
1508 */
1509 int getAccCount(int acc)
1510 {
1511 return (acc >= 0 && acc < 3) ? int(fAcc[acc].size()) : 0;
1512 }
1513
1514 /**
1515 * Get the number of FAUSTFLOAT* zones controlled with the gyroscope
1516 *
1517 * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope
1518 * @param the number of zones
1519 *
1520 */
1521 int getGyrCount(int gyr)
1522 {
1523 return (gyr >= 0 && gyr < 3) ? int(fGyr[gyr].size()) : 0;
1524 }
1525
1526 // getScreenColor() : -1 means no screen color control (no screencolor metadata found)
1527 // otherwise return 0x00RRGGBB a ready to use color
1528 int getScreenColor()
1529 {
1530 if (fHasScreenControl) {
1531 int r = (fRedReader) ? fRedReader->getValue() : 0;
1532 int g = (fGreenReader) ? fGreenReader->getValue() : 0;
1533 int b = (fBlueReader) ? fBlueReader->getValue() : 0;
1534 return (r<<16) | (g<<8) | b;
1535 } else {
1536 return -1;
1537 }
1538 }
1539
1540 };
1541
1542 #endif
1543 /************************** END APIUI.h **************************/
1544
1545 // NOTE: "faust -scn name" changes the last line above to
1546 // #include <faust/name/name.h>
1547
1548 //----------------------------------------------------------------------------
1549 // FAUST Generated Code
1550 //----------------------------------------------------------------------------
1551
1552
1553 #ifndef FAUSTFLOAT
1554 #define FAUSTFLOAT float
1555 #endif
1556
1557 #include <algorithm>
1558 #include <cmath>
1559 #include <math.h>
1560
1561 static float zitarevdsp_faustpower2_f(float value) {
1562 return (value * value);
1563 }
1564
1565 #ifndef FAUSTCLASS
1566 #define FAUSTCLASS zitarevdsp
1567 #endif
1568
1569 #ifdef __APPLE__
1570 #define exp10f __exp10f
1571 #define exp10 __exp10
1572 #endif
1573
1574 class zitarevdsp : public dsp {
1575
1576 private:
1577
1578 int IOTA;
1579 float fVec0[16384];
1580 float fVec1[16384];
1581 FAUSTFLOAT fVslider0;
1582 float fRec0[2];
1583 FAUSTFLOAT fVslider1;
1584 float fRec1[2];
1585 int fSampleRate;
1586 float fConst0;
1587 float fConst1;
1588 FAUSTFLOAT fVslider2;
1589 FAUSTFLOAT fVslider3;
1590 FAUSTFLOAT fVslider4;
1591 FAUSTFLOAT fVslider5;
1592 float fConst2;
1593 float fConst3;
1594 FAUSTFLOAT fVslider6;
1595 FAUSTFLOAT fVslider7;
1596 FAUSTFLOAT fVslider8;
1597 float fConst4;
1598 FAUSTFLOAT fVslider9;
1599 float fRec15[2];
1600 float fRec14[2];
1601 float fVec2[32768];
1602 float fConst5;
1603 int iConst6;
1604 float fConst7;
1605 FAUSTFLOAT fVslider10;
1606 float fVec3[2048];
1607 int iConst8;
1608 float fRec12[2];
1609 float fConst9;
1610 float fConst10;
1611 float fRec19[2];
1612 float fRec18[2];
1613 float fVec4[32768];
1614 float fConst11;
1615 int iConst12;
1616 float fVec5[4096];
1617 int iConst13;
1618 float fRec16[2];
1619 float fConst14;
1620 float fConst15;
1621 float fRec23[2];
1622 float fRec22[2];
1623 float fVec6[16384];
1624 float fConst16;
1625 int iConst17;
1626 float fVec7[4096];
1627 int iConst18;
1628 float fRec20[2];
1629 float fConst19;
1630 float fConst20;
1631 float fRec27[2];
1632 float fRec26[2];
1633 float fVec8[32768];
1634 float fConst21;
1635 int iConst22;
1636 float fVec9[4096];
1637 int iConst23;
1638 float fRec24[2];
1639 float fConst24;
1640 float fConst25;
1641 float fRec31[2];
1642 float fRec30[2];
1643 float fVec10[16384];
1644 float fConst26;
1645 int iConst27;
1646 float fVec11[2048];
1647 int iConst28;
1648 float fRec28[2];
1649 float fConst29;
1650 float fConst30;
1651 float fRec35[2];
1652 float fRec34[2];
1653 float fVec12[16384];
1654 float fConst31;
1655 int iConst32;
1656 float fVec13[4096];
1657 int iConst33;
1658 float fRec32[2];
1659 float fConst34;
1660 float fConst35;
1661 float fRec39[2];
1662 float fRec38[2];
1663 float fVec14[16384];
1664 float fConst36;
1665 int iConst37;
1666 float fVec15[4096];
1667 int iConst38;
1668 float fRec36[2];
1669 float fConst39;
1670 float fConst40;
1671 float fRec43[2];
1672 float fRec42[2];
1673 float fVec16[16384];
1674 float fConst41;
1675 int iConst42;
1676 float fVec17[2048];
1677 int iConst43;
1678 float fRec40[2];
1679 float fRec4[3];
1680 float fRec5[3];
1681 float fRec6[3];
1682 float fRec7[3];
1683 float fRec8[3];
1684 float fRec9[3];
1685 float fRec10[3];
1686 float fRec11[3];
1687 float fRec3[3];
1688 float fRec2[3];
1689 float fRec45[3];
1690 float fRec44[3];
1691
1692 public:
1693
1694 void metadata(Meta* m) {
1695 m->declare("basics.lib/name", "Faust Basic Element Library");
1696 m->declare("basics.lib/version", "0.1");
1697 m->declare("delays.lib/name", "Faust Delay Library");
1698 m->declare("delays.lib/version", "0.1");
1699 m->declare("filename", "zitarevdsp.dsp");
1700 m->declare("filters.lib/allpass_comb:author", "Julius O. Smith III");
1701 m->declare("filters.lib/allpass_comb:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
1702 m->declare("filters.lib/allpass_comb:license", "MIT-style STK-4.3 license");
1703 m->declare("filters.lib/fir:author", "Julius O. Smith III");
1704 m->declare("filters.lib/fir:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
1705 m->declare("filters.lib/fir:license", "MIT-style STK-4.3 license");
1706 m->declare("filters.lib/iir:author", "Julius O. Smith III");
1707 m->declare("filters.lib/iir:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
1708 m->declare("filters.lib/iir:license", "MIT-style STK-4.3 license");
1709 m->declare("filters.lib/lowpass0_highpass1", "MIT-style STK-4.3 license");
1710 m->declare("filters.lib/lowpass0_highpass1:author", "Julius O. Smith III");
1711 m->declare("filters.lib/lowpass:author", "Julius O. Smith III");
1712 m->declare("filters.lib/lowpass:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
1713 m->declare("filters.lib/lowpass:license", "MIT-style STK-4.3 license");
1714 m->declare("filters.lib/name", "Faust Filters Library");
1715 m->declare("filters.lib/peak_eq_rm:author", "Julius O. Smith III");
1716 m->declare("filters.lib/peak_eq_rm:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
1717 m->declare("filters.lib/peak_eq_rm:license", "MIT-style STK-4.3 license");
1718 m->declare("filters.lib/tf1:author", "Julius O. Smith III");
1719 m->declare("filters.lib/tf1:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
1720 m->declare("filters.lib/tf1:license", "MIT-style STK-4.3 license");
1721 m->declare("filters.lib/tf1s:author", "Julius O. Smith III");
1722 m->declare("filters.lib/tf1s:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
1723 m->declare("filters.lib/tf1s:license", "MIT-style STK-4.3 license");
1724 m->declare("filters.lib/tf2:author", "Julius O. Smith III");
1725 m->declare("filters.lib/tf2:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
1726 m->declare("filters.lib/tf2:license", "MIT-style STK-4.3 license");
1727 m->declare("maths.lib/author", "GRAME");
1728 m->declare("maths.lib/copyright", "GRAME");
1729 m->declare("maths.lib/license", "LGPL with exception");
1730 m->declare("maths.lib/name", "Faust Math Library");
1731 m->declare("maths.lib/version", "2.3");
1732 m->declare("name", "zitarevdsp");
1733 m->declare("platform.lib/name", "Generic Platform Library");
1734 m->declare("platform.lib/version", "0.1");
1735 m->declare("reverbs.lib/name", "Faust Reverb Library");
1736 m->declare("reverbs.lib/version", "0.0");
1737 m->declare("routes.lib/name", "Faust Signal Routing Library");
1738 m->declare("routes.lib/version", "0.2");
1739 m->declare("signals.lib/name", "Faust Signal Routing Library");
1740 m->declare("signals.lib/version", "0.0");
1741 }
1742
1743 virtual int getNumInputs() {
1744 return 2;
1745 }
1746 virtual int getNumOutputs() {
1747 return 2;
1748 }
1749 virtual int getInputRate(int channel) {
1750 int rate;
1751 switch ((channel)) {
1752 case 0: {
1753 rate = 1;
1754 break;
1755 }
1756 case 1: {
1757 rate = 1;
1758 break;
1759 }
1760 default: {
1761 rate = -1;
1762 break;
1763 }
1764 }
1765 return rate;
1766 }
1767 virtual int getOutputRate(int channel) {
1768 int rate;
1769 switch ((channel)) {
1770 case 0: {
1771 rate = 1;
1772 break;
1773 }
1774 case 1: {
1775 rate = 1;
1776 break;
1777 }
1778 default: {
1779 rate = -1;
1780 break;
1781 }
1782 }
1783 return rate;
1784 }
1785
1786 static void classInit(int sample_rate) {
1787 }
1788
1789 virtual void instanceConstants(int sample_rate) {
1790 fSampleRate = sample_rate;
1791 fConst0 = std::min<float>(192000.0f, std::max<float>(1.0f, float(fSampleRate)));
1792 fConst1 = (6.28318548f / fConst0);
1793 fConst2 = std::floor(((0.219990999f * fConst0) + 0.5f));
1794 fConst3 = ((0.0f - (6.90775537f * fConst2)) / fConst0);
1795 fConst4 = (3.14159274f / fConst0);
1796 fConst5 = std::floor(((0.0191229992f * fConst0) + 0.5f));
1797 iConst6 = int(std::min<float>(16384.0f, std::max<float>(0.0f, (fConst2 - fConst5))));
1798 fConst7 = (0.00100000005f * fConst0);
1799 iConst8 = int(std::min<float>(1024.0f, std::max<float>(0.0f, (fConst5 + -1.0f))));
1800 fConst9 = std::floor(((0.256891012f * fConst0) + 0.5f));
1801 fConst10 = ((0.0f - (6.90775537f * fConst9)) / fConst0);
1802 fConst11 = std::floor(((0.0273330007f * fConst0) + 0.5f));
1803 iConst12 = int(std::min<float>(16384.0f, std::max<float>(0.0f, (fConst9 - fConst11))));
1804 iConst13 = int(std::min<float>(2048.0f, std::max<float>(0.0f, (fConst11 + -1.0f))));
1805 fConst14 = std::floor(((0.192303002f * fConst0) + 0.5f));
1806 fConst15 = ((0.0f - (6.90775537f * fConst14)) / fConst0);
1807 fConst16 = std::floor(((0.0292910002f * fConst0) + 0.5f));
1808 iConst17 = int(std::min<float>(8192.0f, std::max<float>(0.0f, (fConst14 - fConst16))));
1809 iConst18 = int(std::min<float>(2048.0f, std::max<float>(0.0f, (fConst16 + -1.0f))));
1810 fConst19 = std::floor(((0.210389003f * fConst0) + 0.5f));
1811 fConst20 = ((0.0f - (6.90775537f * fConst19)) / fConst0);
1812 fConst21 = std::floor(((0.0244210009f * fConst0) + 0.5f));
1813 iConst22 = int(std::min<float>(16384.0f, std::max<float>(0.0f, (fConst19 - fConst21))));
1814 iConst23 = int(std::min<float>(2048.0f, std::max<float>(0.0f, (fConst21 + -1.0f))));
1815 fConst24 = std::floor(((0.125f * fConst0) + 0.5f));
1816 fConst25 = ((0.0f - (6.90775537f * fConst24)) / fConst0);
1817 fConst26 = std::floor(((0.0134579996f * fConst0) + 0.5f));
1818 iConst27 = int(std::min<float>(8192.0f, std::max<float>(0.0f, (fConst24 - fConst26))));
1819 iConst28 = int(std::min<float>(1024.0f, std::max<float>(0.0f, (fConst26 + -1.0f))));
1820 fConst29 = std::floor(((0.127837002f * fConst0) + 0.5f));
1821 fConst30 = ((0.0f - (6.90775537f * fConst29)) / fConst0);
1822 fConst31 = std::floor(((0.0316039994f * fConst0) + 0.5f));
1823 iConst32 = int(std::min<float>(8192.0f, std::max<float>(0.0f, (fConst29 - fConst31))));
1824 iConst33 = int(std::min<float>(2048.0f, std::max<float>(0.0f, (fConst31 + -1.0f))));
1825 fConst34 = std::floor(((0.174713001f * fConst0) + 0.5f));
1826 fConst35 = ((0.0f - (6.90775537f * fConst34)) / fConst0);
1827 fConst36 = std::floor(((0.0229039993f * fConst0) + 0.5f));
1828 iConst37 = int(std::min<float>(8192.0f, std::max<float>(0.0f, (fConst34 - fConst36))));
1829 iConst38 = int(std::min<float>(2048.0f, std::max<float>(0.0f, (fConst36 + -1.0f))));
1830 fConst39 = std::floor(((0.153128996f * fConst0) + 0.5f));
1831 fConst40 = ((0.0f - (6.90775537f * fConst39)) / fConst0);
1832 fConst41 = std::floor(((0.0203460008f * fConst0) + 0.5f));
1833 iConst42 = int(std::min<float>(8192.0f, std::max<float>(0.0f, (fConst39 - fConst41))));
1834 iConst43 = int(std::min<float>(1024.0f, std::max<float>(0.0f, (fConst41 + -1.0f))));
1835 }
1836
1837 virtual void instanceResetUserInterface() {
1838 fVslider0 = FAUSTFLOAT(-3.0f);
1839 fVslider1 = FAUSTFLOAT(0.0f);
1840 fVslider2 = FAUSTFLOAT(1500.0f);
1841 fVslider3 = FAUSTFLOAT(0.0f);
1842 fVslider4 = FAUSTFLOAT(315.0f);
1843 fVslider5 = FAUSTFLOAT(0.0f);
1844 fVslider6 = FAUSTFLOAT(2.0f);
1845 fVslider7 = FAUSTFLOAT(6000.0f);
1846 fVslider8 = FAUSTFLOAT(3.0f);
1847 fVslider9 = FAUSTFLOAT(200.0f);
1848 fVslider10 = FAUSTFLOAT(60.0f);
1849 }
1850
1851 virtual void instanceClear() {
1852 IOTA = 0;
1853 for (int l0 = 0; (l0 < 16384); l0 = (l0 + 1)) {
1854 fVec0[l0] = 0.0f;
1855 }
1856 for (int l1 = 0; (l1 < 16384); l1 = (l1 + 1)) {
1857 fVec1[l1] = 0.0f;
1858 }
1859 for (int l2 = 0; (l2 < 2); l2 = (l2 + 1)) {
1860 fRec0[l2] = 0.0f;
1861 }
1862 for (int l3 = 0; (l3 < 2); l3 = (l3 + 1)) {
1863 fRec1[l3] = 0.0f;
1864 }
1865 for (int l4 = 0; (l4 < 2); l4 = (l4 + 1)) {
1866 fRec15[l4] = 0.0f;
1867 }
1868 for (int l5 = 0; (l5 < 2); l5 = (l5 + 1)) {
1869 fRec14[l5] = 0.0f;
1870 }
1871 for (int l6 = 0; (l6 < 32768); l6 = (l6 + 1)) {
1872 fVec2[l6] = 0.0f;
1873 }
1874 for (int l7 = 0; (l7 < 2048); l7 = (l7 + 1)) {
1875 fVec3[l7] = 0.0f;
1876 }
1877 for (int l8 = 0; (l8 < 2); l8 = (l8 + 1)) {
1878 fRec12[l8] = 0.0f;
1879 }
1880 for (int l9 = 0; (l9 < 2); l9 = (l9 + 1)) {
1881 fRec19[l9] = 0.0f;
1882 }
1883 for (int l10 = 0; (l10 < 2); l10 = (l10 + 1)) {
1884 fRec18[l10] = 0.0f;
1885 }
1886 for (int l11 = 0; (l11 < 32768); l11 = (l11 + 1)) {
1887 fVec4[l11] = 0.0f;
1888 }
1889 for (int l12 = 0; (l12 < 4096); l12 = (l12 + 1)) {
1890 fVec5[l12] = 0.0f;
1891 }
1892 for (int l13 = 0; (l13 < 2); l13 = (l13 + 1)) {
1893 fRec16[l13] = 0.0f;
1894 }
1895 for (int l14 = 0; (l14 < 2); l14 = (l14 + 1)) {
1896 fRec23[l14] = 0.0f;
1897 }
1898 for (int l15 = 0; (l15 < 2); l15 = (l15 + 1)) {
1899 fRec22[l15] = 0.0f;
1900 }
1901 for (int l16 = 0; (l16 < 16384); l16 = (l16 + 1)) {
1902 fVec6[l16] = 0.0f;
1903 }
1904 for (int l17 = 0; (l17 < 4096); l17 = (l17 + 1)) {
1905 fVec7[l17] = 0.0f;
1906 }
1907 for (int l18 = 0; (l18 < 2); l18 = (l18 + 1)) {
1908 fRec20[l18] = 0.0f;
1909 }
1910 for (int l19 = 0; (l19 < 2); l19 = (l19 + 1)) {
1911 fRec27[l19] = 0.0f;
1912 }
1913 for (int l20 = 0; (l20 < 2); l20 = (l20 + 1)) {
1914 fRec26[l20] = 0.0f;
1915 }
1916 for (int l21 = 0; (l21 < 32768); l21 = (l21 + 1)) {
1917 fVec8[l21] = 0.0f;
1918 }
1919 for (int l22 = 0; (l22 < 4096); l22 = (l22 + 1)) {
1920 fVec9[l22] = 0.0f;
1921 }
1922 for (int l23 = 0; (l23 < 2); l23 = (l23 + 1)) {
1923 fRec24[l23] = 0.0f;
1924 }
1925 for (int l24 = 0; (l24 < 2); l24 = (l24 + 1)) {
1926 fRec31[l24] = 0.0f;
1927 }
1928 for (int l25 = 0; (l25 < 2); l25 = (l25 + 1)) {
1929 fRec30[l25] = 0.0f;
1930 }
1931 for (int l26 = 0; (l26 < 16384); l26 = (l26 + 1)) {
1932 fVec10[l26] = 0.0f;
1933 }
1934 for (int l27 = 0; (l27 < 2048); l27 = (l27 + 1)) {
1935 fVec11[l27] = 0.0f;
1936 }
1937 for (int l28 = 0; (l28 < 2); l28 = (l28 + 1)) {
1938 fRec28[l28] = 0.0f;
1939 }
1940 for (int l29 = 0; (l29 < 2); l29 = (l29 + 1)) {
1941 fRec35[l29] = 0.0f;
1942 }
1943 for (int l30 = 0; (l30 < 2); l30 = (l30 + 1)) {
1944 fRec34[l30] = 0.0f;
1945 }
1946 for (int l31 = 0; (l31 < 16384); l31 = (l31 + 1)) {
1947 fVec12[l31] = 0.0f;
1948 }
1949 for (int l32 = 0; (l32 < 4096); l32 = (l32 + 1)) {
1950 fVec13[l32] = 0.0f;
1951 }
1952 for (int l33 = 0; (l33 < 2); l33 = (l33 + 1)) {
1953 fRec32[l33] = 0.0f;
1954 }
1955 for (int l34 = 0; (l34 < 2); l34 = (l34 + 1)) {
1956 fRec39[l34] = 0.0f;
1957 }
1958 for (int l35 = 0; (l35 < 2); l35 = (l35 + 1)) {
1959 fRec38[l35] = 0.0f;
1960 }
1961 for (int l36 = 0; (l36 < 16384); l36 = (l36 + 1)) {
1962 fVec14[l36] = 0.0f;
1963 }
1964 for (int l37 = 0; (l37 < 4096); l37 = (l37 + 1)) {
1965 fVec15[l37] = 0.0f;
1966 }
1967 for (int l38 = 0; (l38 < 2); l38 = (l38 + 1)) {
1968 fRec36[l38] = 0.0f;
1969 }
1970 for (int l39 = 0; (l39 < 2); l39 = (l39 + 1)) {
1971 fRec43[l39] = 0.0f;
1972 }
1973 for (int l40 = 0; (l40 < 2); l40 = (l40 + 1)) {
1974 fRec42[l40] = 0.0f;
1975 }
1976 for (int l41 = 0; (l41 < 16384); l41 = (l41 + 1)) {
1977 fVec16[l41] = 0.0f;
1978 }
1979 for (int l42 = 0; (l42 < 2048); l42 = (l42 + 1)) {
1980 fVec17[l42] = 0.0f;
1981 }
1982 for (int l43 = 0; (l43 < 2); l43 = (l43 + 1)) {
1983 fRec40[l43] = 0.0f;
1984 }
1985 for (int l44 = 0; (l44 < 3); l44 = (l44 + 1)) {
1986 fRec4[l44] = 0.0f;
1987 }
1988 for (int l45 = 0; (l45 < 3); l45 = (l45 + 1)) {
1989 fRec5[l45] = 0.0f;
1990 }
1991 for (int l46 = 0; (l46 < 3); l46 = (l46 + 1)) {
1992 fRec6[l46] = 0.0f;
1993 }
1994 for (int l47 = 0; (l47 < 3); l47 = (l47 + 1)) {
1995 fRec7[l47] = 0.0f;
1996 }
1997 for (int l48 = 0; (l48 < 3); l48 = (l48 + 1)) {
1998 fRec8[l48] = 0.0f;
1999 }
2000 for (int l49 = 0; (l49 < 3); l49 = (l49 + 1)) {
2001 fRec9[l49] = 0.0f;
2002 }
2003 for (int l50 = 0; (l50 < 3); l50 = (l50 + 1)) {
2004 fRec10[l50] = 0.0f;
2005 }
2006 for (int l51 = 0; (l51 < 3); l51 = (l51 + 1)) {
2007 fRec11[l51] = 0.0f;
2008 }
2009 for (int l52 = 0; (l52 < 3); l52 = (l52 + 1)) {
2010 fRec3[l52] = 0.0f;
2011 }
2012 for (int l53 = 0; (l53 < 3); l53 = (l53 + 1)) {
2013 fRec2[l53] = 0.0f;
2014 }
2015 for (int l54 = 0; (l54 < 3); l54 = (l54 + 1)) {
2016 fRec45[l54] = 0.0f;
2017 }
2018 for (int l55 = 0; (l55 < 3); l55 = (l55 + 1)) {
2019 fRec44[l55] = 0.0f;
2020 }
2021 }
2022
2023 virtual void init(int sample_rate) {
2024 classInit(sample_rate);
2025 instanceInit(sample_rate);
2026 }
2027 virtual void instanceInit(int sample_rate) {
2028 instanceConstants(sample_rate);
2029 instanceResetUserInterface();
2030 instanceClear();
2031 }
2032
2033 virtual zitarevdsp* clone() {
2034 return new zitarevdsp();
2035 }
2036
2037 virtual int getSampleRate() {
2038 return fSampleRate;
2039 }
2040
2041 virtual void buildUserInterface(UI* ui_interface) {
2042 ui_interface->declare(0, "0", "");
2043 ui_interface->declare(0, "tooltip", "~ ZITA REV1 FEEDBACK DELAY NETWORK (FDN) & SCHROEDER ALLPASS-COMB REVERBERATOR (8x8). See Faust's reverbs.lib for documentation and references");
2044 ui_interface->openHorizontalBox("Zita_Rev1");
2045 ui_interface->declare(0, "1", "");
2046 ui_interface->openHorizontalBox("Input");
2047 ui_interface->declare(&fVslider10, "1", "");
2048 ui_interface->declare(&fVslider10, "style", "knob");
2049 ui_interface->declare(&fVslider10, "tooltip", "Delay in ms before reverberation begins");
2050 ui_interface->declare(&fVslider10, "unit", "ms");
2051 ui_interface->addVerticalSlider("In Delay", &fVslider10, 60.0f, 20.0f, 100.0f, 1.0f);
2052 ui_interface->closeBox();
2053 ui_interface->declare(0, "2", "");
2054 ui_interface->openHorizontalBox("Decay Times in Bands (see tooltips)");
2055 ui_interface->declare(&fVslider9, "1", "");
2056 ui_interface->declare(&fVslider9, "scale", "log");
2057 ui_interface->declare(&fVslider9, "style", "knob");
2058 ui_interface->declare(&fVslider9, "tooltip", "Crossover frequency (Hz) separating low and middle frequencies");
2059 ui_interface->declare(&fVslider9, "unit", "Hz");
2060 ui_interface->addVerticalSlider("LF X", &fVslider9, 200.0f, 50.0f, 1000.0f, 1.0f);
2061 ui_interface->declare(&fVslider8, "2", "");
2062 ui_interface->declare(&fVslider8, "scale", "log");
2063 ui_interface->declare(&fVslider8, "style", "knob");
2064 ui_interface->declare(&fVslider8, "tooltip", "T60 = time (in seconds) to decay 60dB in low-frequency band");
2065 ui_interface->declare(&fVslider8, "unit", "s");
2066 ui_interface->addVerticalSlider("Low RT60", &fVslider8, 3.0f, 1.0f, 8.0f, 0.100000001f);
2067 ui_interface->declare(&fVslider6, "3", "");
2068 ui_interface->declare(&fVslider6, "scale", "log");
2069 ui_interface->declare(&fVslider6, "style", "knob");
2070 ui_interface->declare(&fVslider6, "tooltip", "T60 = time (in seconds) to decay 60dB in middle band");
2071 ui_interface->declare(&fVslider6, "unit", "s");
2072 ui_interface->addVerticalSlider("Mid RT60", &fVslider6, 2.0f, 1.0f, 8.0f, 0.100000001f);
2073 ui_interface->declare(&fVslider7, "4", "");
2074 ui_interface->declare(&fVslider7, "scale", "log");
2075 ui_interface->declare(&fVslider7, "style", "knob");
2076 ui_interface->declare(&fVslider7, "tooltip", "Frequency (Hz) at which the high-frequency T60 is half the middle-band's T60");
2077 ui_interface->declare(&fVslider7, "unit", "Hz");
2078 ui_interface->addVerticalSlider("HF Damping", &fVslider7, 6000.0f, 1500.0f, 23520.0f, 1.0f);
2079 ui_interface->closeBox();
2080 ui_interface->declare(0, "3", "");
2081 ui_interface->openHorizontalBox("RM Peaking Equalizer 1");
2082 ui_interface->declare(&fVslider4, "1", "");
2083 ui_interface->declare(&fVslider4, "scale", "log");
2084 ui_interface->declare(&fVslider4, "style", "knob");
2085 ui_interface->declare(&fVslider4, "tooltip", "Center-frequency of second-order Regalia-Mitra peaking equalizer section 1");
2086 ui_interface->declare(&fVslider4, "unit", "Hz");
2087 ui_interface->addVerticalSlider("Eq1 Freq", &fVslider4, 315.0f, 40.0f, 2500.0f, 1.0f);
2088 ui_interface->declare(&fVslider5, "2", "");
2089 ui_interface->declare(&fVslider5, "style", "knob");
2090 ui_interface->declare(&fVslider5, "tooltip", "Peak level in dB of second-order Regalia-Mitra peaking equalizer section 1");
2091 ui_interface->declare(&fVslider5, "unit", "dB");
2092 ui_interface->addVerticalSlider("Eq1 Level", &fVslider5, 0.0f, -15.0f, 15.0f, 0.100000001f);
2093 ui_interface->closeBox();
2094 ui_interface->declare(0, "4", "");
2095 ui_interface->openHorizontalBox("RM Peaking Equalizer 2");
2096 ui_interface->declare(&fVslider2, "1", "");
2097 ui_interface->declare(&fVslider2, "scale", "log");
2098 ui_interface->declare(&fVslider2, "style", "knob");
2099 ui_interface->declare(&fVslider2, "tooltip", "Center-frequency of second-order Regalia-Mitra peaking equalizer section 2");
2100 ui_interface->declare(&fVslider2, "unit", "Hz");
2101 ui_interface->addVerticalSlider("Eq2 Freq", &fVslider2, 1500.0f, 160.0f, 10000.0f, 1.0f);
2102 ui_interface->declare(&fVslider3, "2", "");
2103 ui_interface->declare(&fVslider3, "style", "knob");
2104 ui_interface->declare(&fVslider3, "tooltip", "Peak level in dB of second-order Regalia-Mitra peaking equalizer section 2");
2105 ui_interface->declare(&fVslider3, "unit", "dB");
2106 ui_interface->addVerticalSlider("Eq2 Level", &fVslider3, 0.0f, -15.0f, 15.0f, 0.100000001f);
2107 ui_interface->closeBox();
2108 ui_interface->declare(0, "5", "");
2109 ui_interface->openHorizontalBox("Output");
2110 ui_interface->declare(&fVslider1, "1", "");
2111 ui_interface->declare(&fVslider1, "style", "knob");
2112 ui_interface->declare(&fVslider1, "tooltip", "Dry/Wet Mix: 0 = dry, 1 = wet");
2113 ui_interface->addVerticalSlider("Wet", &fVslider1, 0.0f, 0.0f, 1.0f, 0.00999999978f);
2114 ui_interface->declare(&fVslider0, "2", "");
2115 ui_interface->declare(&fVslider0, "style", "knob");
2116 ui_interface->declare(&fVslider0, "tooltip", "Output scale factor");
2117 ui_interface->declare(&fVslider0, "unit", "dB");
2118 ui_interface->addVerticalSlider("Level", &fVslider0, -3.0f, -70.0f, 20.0f, 0.100000001f);
2119 ui_interface->closeBox();
2120 ui_interface->closeBox();
2121 }
2122
2123 virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) {
2124 FAUSTFLOAT* input0 = inputs[0];
2125 FAUSTFLOAT* input1 = inputs[1];
2126 FAUSTFLOAT* output0 = outputs[0];
2127 FAUSTFLOAT* output1 = outputs[1];
2128 float fSlow0 = (0.00100000005f * std::pow(10.0f, (0.0500000007f * float(fVslider0))));
2129 float fSlow1 = (0.00100000005f * float(fVslider1));
2130 float fSlow2 = float(fVslider2);
2131 float fSlow3 = std::pow(10.0f, (0.0500000007f * float(fVslider3)));
2132 float fSlow4 = (fConst1 * (fSlow2 / std::sqrt(std::max<float>(0.0f, fSlow3))));
2133 float fSlow5 = ((1.0f - fSlow4) / (fSlow4 + 1.0f));
2134 float fSlow6 = float(fVslider4);
2135 float fSlow7 = std::pow(10.0f, (0.0500000007f * float(fVslider5)));
2136 float fSlow8 = (fConst1 * (fSlow6 / std::sqrt(std::max<float>(0.0f, fSlow7))));
2137 float fSlow9 = ((1.0f - fSlow8) / (fSlow8 + 1.0f));
2138 float fSlow10 = float(fVslider6);
2139 float fSlow11 = std::exp((fConst3 / fSlow10));
2140 float fSlow12 = zitarevdsp_faustpower2_f(fSlow11);
2141 float fSlow13 = std::cos((fConst1 * float(fVslider7)));
2142 float fSlow14 = (1.0f - (fSlow12 * fSlow13));
2143 float fSlow15 = (1.0f - fSlow12);
2144 float fSlow16 = (fSlow14 / fSlow15);
2145 float fSlow17 = std::sqrt(std::max<float>(0.0f, ((zitarevdsp_faustpower2_f(fSlow14) / zitarevdsp_faustpower2_f(fSlow15)) + -1.0f)));
2146 float fSlow18 = (fSlow16 - fSlow17);
2147 float fSlow19 = (fSlow11 * (fSlow17 + (1.0f - fSlow16)));
2148 float fSlow20 = float(fVslider8);
2149 float fSlow21 = ((std::exp((fConst3 / fSlow20)) / fSlow11) + -1.0f);
2150 float fSlow22 = (1.0f / std::tan((fConst4 * float(fVslider9))));
2151 float fSlow23 = (1.0f / (fSlow22 + 1.0f));
2152 float fSlow24 = (1.0f - fSlow22);
2153 int iSlow25 = int(std::min<float>(8192.0f, std::max<float>(0.0f, (fConst7 * float(fVslider10)))));
2154 float fSlow26 = std::exp((fConst10 / fSlow10));
2155 float fSlow27 = zitarevdsp_faustpower2_f(fSlow26);
2156 float fSlow28 = (1.0f - (fSlow27 * fSlow13));
2157 float fSlow29 = (1.0f - fSlow27);
2158 float fSlow30 = (fSlow28 / fSlow29);
2159 float fSlow31 = std::sqrt(std::max<float>(0.0f, ((zitarevdsp_faustpower2_f(fSlow28) / zitarevdsp_faustpower2_f(fSlow29)) + -1.0f)));
2160 float fSlow32 = (fSlow30 - fSlow31);
2161 float fSlow33 = (fSlow26 * (fSlow31 + (1.0f - fSlow30)));
2162 float fSlow34 = ((std::exp((fConst10 / fSlow20)) / fSlow26) + -1.0f);
2163 float fSlow35 = std::exp((fConst15 / fSlow10));
2164 float fSlow36 = zitarevdsp_faustpower2_f(fSlow35);
2165 float fSlow37 = (1.0f - (fSlow36 * fSlow13));
2166 float fSlow38 = (1.0f - fSlow36);
2167 float fSlow39 = (fSlow37 / fSlow38);
2168 float fSlow40 = std::sqrt(std::max<float>(0.0f, ((zitarevdsp_faustpower2_f(fSlow37) / zitarevdsp_faustpower2_f(fSlow38)) + -1.0f)));
2169 float fSlow41 = (fSlow39 - fSlow40);
2170 float fSlow42 = (fSlow35 * (fSlow40 + (1.0f - fSlow39)));
2171 float fSlow43 = ((std::exp((fConst15 / fSlow20)) / fSlow35) + -1.0f);
2172 float fSlow44 = std::exp((fConst20 / fSlow10));
2173 float fSlow45 = zitarevdsp_faustpower2_f(fSlow44);
2174 float fSlow46 = (1.0f - (fSlow45 * fSlow13));
2175 float fSlow47 = (1.0f - fSlow45);
2176 float fSlow48 = (fSlow46 / fSlow47);
2177 float fSlow49 = std::sqrt(std::max<float>(0.0f, ((zitarevdsp_faustpower2_f(fSlow46) / zitarevdsp_faustpower2_f(fSlow47)) + -1.0f)));
2178 float fSlow50 = (fSlow48 - fSlow49);
2179 float fSlow51 = (fSlow44 * (fSlow49 + (1.0f - fSlow48)));
2180 float fSlow52 = ((std::exp((fConst20 / fSlow20)) / fSlow44) + -1.0f);
2181 float fSlow53 = std::exp((fConst25 / fSlow10));
2182 float fSlow54 = zitarevdsp_faustpower2_f(fSlow53);
2183 float fSlow55 = (1.0f - (fSlow54 * fSlow13));
2184 float fSlow56 = (1.0f - fSlow54);
2185 float fSlow57 = (fSlow55 / fSlow56);
2186 float fSlow58 = std::sqrt(std::max<float>(0.0f, ((zitarevdsp_faustpower2_f(fSlow55) / zitarevdsp_faustpower2_f(fSlow56)) + -1.0f)));
2187 float fSlow59 = (fSlow57 - fSlow58);
2188 float fSlow60 = (fSlow53 * (fSlow58 + (1.0f - fSlow57)));
2189 float fSlow61 = ((std::exp((fConst25 / fSlow20)) / fSlow53) + -1.0f);
2190 float fSlow62 = std::exp((fConst30 / fSlow10));
2191 float fSlow63 = zitarevdsp_faustpower2_f(fSlow62);
2192 float fSlow64 = (1.0f - (fSlow63 * fSlow13));
2193 float fSlow65 = (1.0f - fSlow63);
2194 float fSlow66 = (fSlow64 / fSlow65);
2195 float fSlow67 = std::sqrt(std::max<float>(0.0f, ((zitarevdsp_faustpower2_f(fSlow64) / zitarevdsp_faustpower2_f(fSlow65)) + -1.0f)));
2196 float fSlow68 = (fSlow66 - fSlow67);
2197 float fSlow69 = (fSlow62 * (fSlow67 + (1.0f - fSlow66)));
2198 float fSlow70 = ((std::exp((fConst30 / fSlow20)) / fSlow62) + -1.0f);
2199 float fSlow71 = std::exp((fConst35 / fSlow10));
2200 float fSlow72 = zitarevdsp_faustpower2_f(fSlow71);
2201 float fSlow73 = (1.0f - (fSlow72 * fSlow13));
2202 float fSlow74 = (1.0f - fSlow72);
2203 float fSlow75 = (fSlow73 / fSlow74);
2204 float fSlow76 = std::sqrt(std::max<float>(0.0f, ((zitarevdsp_faustpower2_f(fSlow73) / zitarevdsp_faustpower2_f(fSlow74)) + -1.0f)));
2205 float fSlow77 = (fSlow75 - fSlow76);
2206 float fSlow78 = (fSlow71 * (fSlow76 + (1.0f - fSlow75)));
2207 float fSlow79 = ((std::exp((fConst35 / fSlow20)) / fSlow71) + -1.0f);
2208 float fSlow80 = std::exp((fConst40 / fSlow10));
2209 float fSlow81 = zitarevdsp_faustpower2_f(fSlow80);
2210 float fSlow82 = (1.0f - (fSlow81 * fSlow13));
2211 float fSlow83 = (1.0f - fSlow81);
2212 float fSlow84 = (fSlow82 / fSlow83);
2213 float fSlow85 = std::sqrt(std::max<float>(0.0f, ((zitarevdsp_faustpower2_f(fSlow82) / zitarevdsp_faustpower2_f(fSlow83)) + -1.0f)));
2214 float fSlow86 = (fSlow84 - fSlow85);
2215 float fSlow87 = (fSlow80 * (fSlow85 + (1.0f - fSlow84)));
2216 float fSlow88 = ((std::exp((fConst40 / fSlow20)) / fSlow80) + -1.0f);
2217 float fSlow89 = (0.0f - (std::cos((fConst1 * fSlow6)) * (fSlow9 + 1.0f)));
2218 float fSlow90 = (0.0f - (std::cos((fConst1 * fSlow2)) * (fSlow5 + 1.0f)));
2219 for (int i = 0; (i < count); i = (i + 1)) {
2220 float fTemp0 = float(input0[i]);
2221 fVec0[(IOTA & 16383)] = fTemp0;
2222 float fTemp1 = float(input1[i]);
2223 fVec1[(IOTA & 16383)] = fTemp1;
2224 fRec0[0] = (fSlow0 + (0.999000013f * fRec0[1]));
2225 fRec1[0] = (fSlow1 + (0.999000013f * fRec1[1]));
2226 fRec15[0] = (0.0f - (fSlow23 * ((fSlow24 * fRec15[1]) - (fRec11[1] + fRec11[2]))));
2227 fRec14[0] = ((fSlow18 * fRec14[1]) + (fSlow19 * (fRec11[1] + (fSlow21 * fRec15[0]))));
2228 fVec2[(IOTA & 32767)] = ((0.353553385f * fRec14[0]) + 9.99999968e-21f);
2229 float fTemp2 = (0.300000012f * fVec1[((IOTA - iSlow25) & 16383)]);
2230 float fTemp3 = (((0.600000024f * fRec12[1]) + fVec2[((IOTA - iConst6) & 32767)]) - fTemp2);
2231 fVec3[(IOTA & 2047)] = fTemp3;
2232 fRec12[0] = fVec3[((IOTA - iConst8) & 2047)];
2233 float fRec13 = (0.0f - (0.600000024f * fTemp3));
2234 fRec19[0] = (0.0f - (fSlow23 * ((fSlow24 * fRec19[1]) - (fRec7[1] + fRec7[2]))));
2235 fRec18[0] = ((fSlow32 * fRec18[1]) + (fSlow33 * (fRec7[1] + (fSlow34 * fRec19[0]))));
2236 fVec4[(IOTA & 32767)] = ((0.353553385f * fRec18[0]) + 9.99999968e-21f);
2237 float fTemp4 = (((0.600000024f * fRec16[1]) + fVec4[((IOTA - iConst12) & 32767)]) - fTemp2);
2238 fVec5[(IOTA & 4095)] = fTemp4;
2239 fRec16[0] = fVec5[((IOTA - iConst13) & 4095)];
2240 float fRec17 = (0.0f - (0.600000024f * fTemp4));
2241 fRec23[0] = (0.0f - (fSlow23 * ((fSlow24 * fRec23[1]) - (fRec9[1] + fRec9[2]))));
2242 fRec22[0] = ((fSlow41 * fRec22[1]) + (fSlow42 * (fRec9[1] + (fSlow43 * fRec23[0]))));
2243 fVec6[(IOTA & 16383)] = ((0.353553385f * fRec22[0]) + 9.99999968e-21f);
2244 float fTemp5 = (fVec6[((IOTA - iConst17) & 16383)] + (fTemp2 + (0.600000024f * fRec20[1])));
2245 fVec7[(IOTA & 4095)] = fTemp5;
2246 fRec20[0] = fVec7[((IOTA - iConst18) & 4095)];
2247 float fRec21 = (0.0f - (0.600000024f * fTemp5));
2248 fRec27[0] = (0.0f - (fSlow23 * ((fSlow24 * fRec27[1]) - (fRec5[1] + fRec5[2]))));
2249 fRec26[0] = ((fSlow50 * fRec26[1]) + (fSlow51 * (fRec5[1] + (fSlow52 * fRec27[0]))));
2250 fVec8[(IOTA & 32767)] = ((0.353553385f * fRec26[0]) + 9.99999968e-21f);
2251 float fTemp6 = (fTemp2 + ((0.600000024f * fRec24[1]) + fVec8[((IOTA - iConst22) & 32767)]));
2252 fVec9[(IOTA & 4095)] = fTemp6;
2253 fRec24[0] = fVec9[((IOTA - iConst23) & 4095)];
2254 float fRec25 = (0.0f - (0.600000024f * fTemp6));
2255 fRec31[0] = (0.0f - (fSlow23 * ((fSlow24 * fRec31[1]) - (fRec10[1] + fRec10[2]))));
2256 fRec30[0] = ((fSlow59 * fRec30[1]) + (fSlow60 * (fRec10[1] + (fSlow61 * fRec31[0]))));
2257 fVec10[(IOTA & 16383)] = ((0.353553385f * fRec30[0]) + 9.99999968e-21f);
2258 float fTemp7 = (0.300000012f * fVec0[((IOTA - iSlow25) & 16383)]);
2259 float fTemp8 = (fVec10[((IOTA - iConst27) & 16383)] - (fTemp7 + (0.600000024f * fRec28[1])));
2260 fVec11[(IOTA & 2047)] = fTemp8;
2261 fRec28[0] = fVec11[((IOTA - iConst28) & 2047)];
2262 float fRec29 = (0.600000024f * fTemp8);
2263 fRec35[0] = (0.0f - (fSlow23 * ((fSlow24 * fRec35[1]) - (fRec6[1] + fRec6[2]))));
2264 fRec34[0] = ((fSlow68 * fRec34[1]) + (fSlow69 * (fRec6[1] + (fSlow70 * fRec35[0]))));
2265 fVec12[(IOTA & 16383)] = ((0.353553385f * fRec34[0]) + 9.99999968e-21f);
2266 float fTemp9 = (fVec12[((IOTA - iConst32) & 16383)] - (fTemp7 + (0.600000024f * fRec32[1])));
2267 fVec13[(IOTA & 4095)] = fTemp9;
2268 fRec32[0] = fVec13[((IOTA - iConst33) & 4095)];
2269 float fRec33 = (0.600000024f * fTemp9);
2270 fRec39[0] = (0.0f - (fSlow23 * ((fSlow24 * fRec39[1]) - (fRec8[1] + fRec8[2]))));
2271 fRec38[0] = ((fSlow77 * fRec38[1]) + (fSlow78 * (fRec8[1] + (fSlow79 * fRec39[0]))));
2272 fVec14[(IOTA & 16383)] = ((0.353553385f * fRec38[0]) + 9.99999968e-21f);
2273 float fTemp10 = ((fTemp7 + fVec14[((IOTA - iConst37) & 16383)]) - (0.600000024f * fRec36[1]));
2274 fVec15[(IOTA & 4095)] = fTemp10;
2275 fRec36[0] = fVec15[((IOTA - iConst38) & 4095)];
2276 float fRec37 = (0.600000024f * fTemp10);
2277 fRec43[0] = (0.0f - (fSlow23 * ((fSlow24 * fRec43[1]) - (fRec4[1] + fRec4[2]))));
2278 fRec42[0] = ((fSlow86 * fRec42[1]) + (fSlow87 * (fRec4[1] + (fSlow88 * fRec43[0]))));
2279 fVec16[(IOTA & 16383)] = ((0.353553385f * fRec42[0]) + 9.99999968e-21f);
2280 float fTemp11 = ((fVec16[((IOTA - iConst42) & 16383)] + fTemp7) - (0.600000024f * fRec40[1]));
2281 fVec17[(IOTA & 2047)] = fTemp11;
2282 fRec40[0] = fVec17[((IOTA - iConst43) & 2047)];
2283 float fRec41 = (0.600000024f * fTemp11);
2284 float fTemp12 = (fRec41 + fRec37);
2285 float fTemp13 = (fRec29 + (fRec33 + fTemp12));
2286 fRec4[0] = (fRec12[1] + (fRec16[1] + (fRec20[1] + (fRec24[1] + (fRec28[1] + (fRec32[1] + (fRec36[1] + (fRec40[1] + (fRec13 + (fRec17 + (fRec21 + (fRec25 + fTemp13))))))))))));
2287 fRec5[0] = ((fRec28[1] + (fRec32[1] + (fRec36[1] + (fRec40[1] + fTemp13)))) - (fRec12[1] + (fRec16[1] + (fRec20[1] + (fRec24[1] + (fRec13 + (fRec17 + (fRec25 + fRec21))))))));
2288 float fTemp14 = (fRec33 + fRec29);
2289 fRec6[0] = ((fRec20[1] + (fRec24[1] + (fRec36[1] + (fRec40[1] + (fRec21 + (fRec25 + fTemp12)))))) - (fRec12[1] + (fRec16[1] + (fRec28[1] + (fRec32[1] + (fRec13 + (fRec17 + fTemp14)))))));
2290 fRec7[0] = ((fRec12[1] + (fRec16[1] + (fRec36[1] + (fRec40[1] + (fRec13 + (fRec17 + fTemp12)))))) - (fRec20[1] + (fRec24[1] + (fRec28[1] + (fRec32[1] + (fRec21 + (fRec25 + fTemp14)))))));
2291 float fTemp15 = (fRec41 + fRec33);
2292 float fTemp16 = (fRec37 + fRec29);
2293 fRec8[0] = ((fRec16[1] + (fRec24[1] + (fRec32[1] + (fRec40[1] + (fRec17 + (fRec25 + fTemp15)))))) - (fRec12[1] + (fRec20[1] + (fRec28[1] + (fRec36[1] + (fRec13 + (fRec21 + fTemp16)))))));
2294 fRec9[0] = ((fRec12[1] + (fRec20[1] + (fRec32[1] + (fRec40[1] + (fRec13 + (fRec21 + fTemp15)))))) - (fRec16[1] + (fRec24[1] + (fRec28[1] + (fRec36[1] + (fRec17 + (fRec25 + fTemp16)))))));
2295 float fTemp17 = (fRec41 + fRec29);
2296 float fTemp18 = (fRec37 + fRec33);
2297 fRec10[0] = ((fRec12[1] + (fRec24[1] + (fRec28[1] + (fRec40[1] + (fRec13 + (fRec25 + fTemp17)))))) - (fRec16[1] + (fRec20[1] + (fRec32[1] + (fRec36[1] + (fRec17 + (fRec21 + fTemp18)))))));
2298 fRec11[0] = ((fRec16[1] + (fRec20[1] + (fRec28[1] + (fRec40[1] + (fRec17 + (fRec21 + fTemp17)))))) - (fRec12[1] + (fRec24[1] + (fRec32[1] + (fRec36[1] + (fRec13 + (fRec25 + fTemp18)))))));
2299 float fTemp19 = (0.370000005f * (fRec5[0] + fRec6[0]));
2300 float fTemp20 = (fSlow89 * fRec3[1]);
2301 fRec3[0] = (fTemp19 - (fTemp20 + (fSlow9 * fRec3[2])));
2302 float fTemp21 = (fSlow9 * fRec3[0]);
2303 float fTemp22 = (0.5f * ((fTemp21 + (fRec3[2] + (fTemp19 + fTemp20))) + (fSlow7 * ((fTemp21 + (fTemp20 + fRec3[2])) - fTemp19))));
2304 float fTemp23 = (fSlow90 * fRec2[1]);
2305 fRec2[0] = (fTemp22 - (fTemp23 + (fSlow5 * fRec2[2])));
2306 float fTemp24 = (fSlow5 * fRec2[0]);
2307 float fTemp25 = (1.0f - fRec1[0]);
2308 output0[i] = FAUSTFLOAT((fRec0[0] * ((0.5f * (fRec1[0] * ((fTemp24 + (fRec2[2] + (fTemp22 + fTemp23))) + (fSlow3 * ((fTemp24 + (fTemp23 + fRec2[2])) - fTemp22))))) + (fTemp0 * fTemp25))));
2309 float fTemp26 = (0.370000005f * (fRec5[0] - fRec6[0]));
2310 float fTemp27 = (fSlow89 * fRec45[1]);
2311 fRec45[0] = (fTemp26 - (fTemp27 + (fSlow9 * fRec45[2])));
2312 float fTemp28 = (fSlow9 * fRec45[0]);
2313 float fTemp29 = (0.5f * ((fTemp28 + (fRec45[2] + (fTemp26 + fTemp27))) + (fSlow7 * ((fTemp28 + (fTemp27 + fRec45[2])) - fTemp26))));
2314 float fTemp30 = (fSlow90 * fRec44[1]);
2315 fRec44[0] = (fTemp29 - (fTemp30 + (fSlow5 * fRec44[2])));
2316 float fTemp31 = (fSlow5 * fRec44[0]);
2317 output1[i] = FAUSTFLOAT((fRec0[0] * ((0.5f * (fRec1[0] * ((fTemp31 + (fRec44[2] + (fTemp29 + fTemp30))) + (fSlow3 * ((fTemp31 + (fTemp30 + fRec44[2])) - fTemp29))))) + (fTemp1 * fTemp25))));
2318 IOTA = (IOTA + 1);
2319 fRec0[1] = fRec0[0];
2320 fRec1[1] = fRec1[0];
2321 fRec15[1] = fRec15[0];
2322 fRec14[1] = fRec14[0];
2323 fRec12[1] = fRec12[0];
2324 fRec19[1] = fRec19[0];
2325 fRec18[1] = fRec18[0];
2326 fRec16[1] = fRec16[0];
2327 fRec23[1] = fRec23[0];
2328 fRec22[1] = fRec22[0];
2329 fRec20[1] = fRec20[0];
2330 fRec27[1] = fRec27[0];
2331 fRec26[1] = fRec26[0];
2332 fRec24[1] = fRec24[0];
2333 fRec31[1] = fRec31[0];
2334 fRec30[1] = fRec30[0];
2335 fRec28[1] = fRec28[0];
2336 fRec35[1] = fRec35[0];
2337 fRec34[1] = fRec34[0];
2338 fRec32[1] = fRec32[0];
2339 fRec39[1] = fRec39[0];
2340 fRec38[1] = fRec38[0];
2341 fRec36[1] = fRec36[0];
2342 fRec43[1] = fRec43[0];
2343 fRec42[1] = fRec42[0];
2344 fRec40[1] = fRec40[0];
2345 fRec4[2] = fRec4[1];
2346 fRec4[1] = fRec4[0];
2347 fRec5[2] = fRec5[1];
2348 fRec5[1] = fRec5[0];
2349 fRec6[2] = fRec6[1];
2350 fRec6[1] = fRec6[0];
2351 fRec7[2] = fRec7[1];
2352 fRec7[1] = fRec7[0];
2353 fRec8[2] = fRec8[1];
2354 fRec8[1] = fRec8[0];
2355 fRec9[2] = fRec9[1];
2356 fRec9[1] = fRec9[0];
2357 fRec10[2] = fRec10[1];
2358 fRec10[1] = fRec10[0];
2359 fRec11[2] = fRec11[1];
2360 fRec11[1] = fRec11[0];
2361 fRec3[2] = fRec3[1];
2362 fRec3[1] = fRec3[0];
2363 fRec2[2] = fRec2[1];
2364 fRec2[1] = fRec2[0];
2365 fRec45[2] = fRec45[1];
2366 fRec45[1] = fRec45[0];
2367 fRec44[2] = fRec44[1];
2368 fRec44[1] = fRec44[0];
2369 }
2370 }
2371
2372 };
2373
2374 #endif
0 /* ------------------------------------------------------------
1 name: "zitarevmonodsp"
2 Code generated with Faust 2.28.6 (https://faust.grame.fr)
3 Compilation options: -lang cpp -inpl -scal -ftz 0
4 ------------------------------------------------------------ */
5
6 #ifndef __zitarevmonodsp_H__
7 #define __zitarevmonodsp_H__
8
9 // NOTE: ANY INCLUDE-GUARD HERE MUST BE DERIVED FROM THE CLASS NAME
10 //
11 // faust2header.cpp - FAUST Architecture File
12 // This is a simple variation of matlabplot.cpp in the Faust distribution
13 // aimed at creating a simple C++ header file (.h) containing a Faust DSP.
14 // See the Makefile for how to use it.
15
16 /************************** BEGIN dsp.h **************************/
17 /************************************************************************
18 FAUST Architecture File
19 Copyright (C) 2003-2017 GRAME, Centre National de Creation Musicale
20 ---------------------------------------------------------------------
21 This Architecture section is free software; you can redistribute it
22 and/or modify it under the terms of the GNU General Public License
23 as published by the Free Software Foundation; either version 3 of
24 the License, or (at your option) any later version.
25
26 This program is distributed in the hope that it will be useful,
27 but WITHOUT ANY WARRANTY; without even the implied warranty of
28 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 GNU General Public License for more details.
30
31 You should have received a copy of the GNU General Public License
32 along with this program; If not, see <http://www.gnu.org/licenses/>.
33
34 EXCEPTION : As a special exception, you may create a larger work
35 that contains this FAUST architecture section and distribute
36 that work under terms of your choice, so long as this FAUST
37 architecture section is not modified.
38 ************************************************************************/
39
40 #ifndef __dsp__
41 #define __dsp__
42
43 #include <string>
44 #include <vector>
45
46 #ifndef FAUSTFLOAT
47 #define FAUSTFLOAT float
48 #endif
49
50 struct UI;
51 struct Meta;
52
53 /**
54 * DSP memory manager.
55 */
56
57 struct dsp_memory_manager {
58
59 virtual ~dsp_memory_manager() {}
60
61 virtual void* allocate(size_t size) = 0;
62 virtual void destroy(void* ptr) = 0;
63
64 };
65
66 /**
67 * Signal processor definition.
68 */
69
70 class dsp {
71
72 public:
73
74 dsp() {}
75 virtual ~dsp() {}
76
77 /* Return instance number of audio inputs */
78 virtual int getNumInputs() = 0;
79
80 /* Return instance number of audio outputs */
81 virtual int getNumOutputs() = 0;
82
83 /**
84 * Trigger the ui_interface parameter with instance specific calls
85 * to 'openTabBox', 'addButton', 'addVerticalSlider'... in order to build the UI.
86 *
87 * @param ui_interface - the user interface builder
88 */
89 virtual void buildUserInterface(UI* ui_interface) = 0;
90
91 /* Returns the sample rate currently used by the instance */
92 virtual int getSampleRate() = 0;
93
94 /**
95 * Global init, calls the following methods:
96 * - static class 'classInit': static tables initialization
97 * - 'instanceInit': constants and instance state initialization
98 *
99 * @param sample_rate - the sampling rate in Hertz
100 */
101 virtual void init(int sample_rate) = 0;
102
103 /**
104 * Init instance state
105 *
106 * @param sample_rate - the sampling rate in Hertz
107 */
108 virtual void instanceInit(int sample_rate) = 0;
109
110 /**
111 * Init instance constant state
112 *
113 * @param sample_rate - the sampling rate in Hertz
114 */
115 virtual void instanceConstants(int sample_rate) = 0;
116
117 /* Init default control parameters values */
118 virtual void instanceResetUserInterface() = 0;
119
120 /* Init instance state (delay lines...) */
121 virtual void instanceClear() = 0;
122
123 /**
124 * Return a clone of the instance.
125 *
126 * @return a copy of the instance on success, otherwise a null pointer.
127 */
128 virtual dsp* clone() = 0;
129
130 /**
131 * Trigger the Meta* parameter with instance specific calls to 'declare' (key, value) metadata.
132 *
133 * @param m - the Meta* meta user
134 */
135 virtual void metadata(Meta* m) = 0;
136
137 /**
138 * DSP instance computation, to be called with successive in/out audio buffers.
139 *
140 * @param count - the number of frames to compute
141 * @param inputs - the input audio buffers as an array of non-interleaved FAUSTFLOAT samples (eiher float, double or quad)
142 * @param outputs - the output audio buffers as an array of non-interleaved FAUSTFLOAT samples (eiher float, double or quad)
143 *
144 */
145 virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) = 0;
146
147 /**
148 * DSP instance computation: alternative method to be used by subclasses.
149 *
150 * @param date_usec - the timestamp in microsec given by audio driver.
151 * @param count - the number of frames to compute
152 * @param inputs - the input audio buffers as an array of non-interleaved FAUSTFLOAT samples (either float, double or quad)
153 * @param outputs - the output audio buffers as an array of non-interleaved FAUSTFLOAT samples (either float, double or quad)
154 *
155 */
156 virtual void compute(double /*date_usec*/, int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { compute(count, inputs, outputs); }
157
158 };
159
160 /**
161 * Generic DSP decorator.
162 */
163
164 class decorator_dsp : public dsp {
165
166 protected:
167
168 dsp* fDSP;
169
170 public:
171
172 decorator_dsp(dsp* dsp = nullptr):fDSP(dsp) {}
173 virtual ~decorator_dsp() { delete fDSP; }
174
175 virtual int getNumInputs() { return fDSP->getNumInputs(); }
176 virtual int getNumOutputs() { return fDSP->getNumOutputs(); }
177 virtual void buildUserInterface(UI* ui_interface) { fDSP->buildUserInterface(ui_interface); }
178 virtual int getSampleRate() { return fDSP->getSampleRate(); }
179 virtual void init(int sample_rate) { fDSP->init(sample_rate); }
180 virtual void instanceInit(int sample_rate) { fDSP->instanceInit(sample_rate); }
181 virtual void instanceConstants(int sample_rate) { fDSP->instanceConstants(sample_rate); }
182 virtual void instanceResetUserInterface() { fDSP->instanceResetUserInterface(); }
183 virtual void instanceClear() { fDSP->instanceClear(); }
184 virtual decorator_dsp* clone() { return new decorator_dsp(fDSP->clone()); }
185 virtual void metadata(Meta* m) { fDSP->metadata(m); }
186 // Beware: subclasses usually have to overload the two 'compute' methods
187 virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { fDSP->compute(count, inputs, outputs); }
188 virtual void compute(double date_usec, int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { fDSP->compute(date_usec, count, inputs, outputs); }
189
190 };
191
192 /**
193 * DSP factory class.
194 */
195
196 class dsp_factory {
197
198 protected:
199
200 // So that to force sub-classes to use deleteDSPFactory(dsp_factory* factory);
201 virtual ~dsp_factory() {}
202
203 public:
204
205 virtual std::string getName() = 0;
206 virtual std::string getSHAKey() = 0;
207 virtual std::string getDSPCode() = 0;
208 virtual std::string getCompileOptions() = 0;
209 virtual std::vector<std::string> getLibraryList() = 0;
210 virtual std::vector<std::string> getIncludePathnames() = 0;
211
212 virtual dsp* createDSPInstance() = 0;
213
214 virtual void setMemoryManager(dsp_memory_manager* manager) = 0;
215 virtual dsp_memory_manager* getMemoryManager() = 0;
216
217 };
218
219 /**
220 * On Intel set FZ (Flush to Zero) and DAZ (Denormals Are Zero)
221 * flags to avoid costly denormals.
222 */
223
224 #ifdef __SSE__
225 #include <xmmintrin.h>
226 #ifdef __SSE2__
227 #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8040)
228 #else
229 #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8000)
230 #endif
231 #else
232 #define AVOIDDENORMALS
233 #endif
234
235 #endif
236 /************************** END dsp.h **************************/
237
238 /************************** BEGIN APIUI.h **************************/
239 /************************************************************************
240 FAUST Architecture File
241 Copyright (C) 2003-2017 GRAME, Centre National de Creation Musicale
242 ---------------------------------------------------------------------
243 This Architecture section is free software; you can redistribute it
244 and/or modify it under the terms of the GNU General Public License
245 as published by the Free Software Foundation; either version 3 of
246 the License, or (at your option) any later version.
247
248 This program is distributed in the hope that it will be useful,
249 but WITHOUT ANY WARRANTY; without even the implied warranty of
250 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
251 GNU General Public License for more details.
252
253 You should have received a copy of the GNU General Public License
254 along with this program; If not, see <http://www.gnu.org/licenses/>.
255
256 EXCEPTION : As a special exception, you may create a larger work
257 that contains this FAUST architecture section and distribute
258 that work under terms of your choice, so long as this FAUST
259 architecture section is not modified.
260 ************************************************************************/
261
262 #ifndef API_UI_H
263 #define API_UI_H
264
265 #include <sstream>
266 #include <string>
267 #include <vector>
268 #include <iostream>
269 #include <map>
270
271 /************************** BEGIN meta.h **************************/
272 /************************************************************************
273 FAUST Architecture File
274 Copyright (C) 2003-2017 GRAME, Centre National de Creation Musicale
275 ---------------------------------------------------------------------
276 This Architecture section is free software; you can redistribute it
277 and/or modify it under the terms of the GNU General Public License
278 as published by the Free Software Foundation; either version 3 of
279 the License, or (at your option) any later version.
280
281 This program is distributed in the hope that it will be useful,
282 but WITHOUT ANY WARRANTY; without even the implied warranty of
283 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
284 GNU General Public License for more details.
285
286 You should have received a copy of the GNU General Public License
287 along with this program; If not, see <http://www.gnu.org/licenses/>.
288
289 EXCEPTION : As a special exception, you may create a larger work
290 that contains this FAUST architecture section and distribute
291 that work under terms of your choice, so long as this FAUST
292 architecture section is not modified.
293 ************************************************************************/
294
295 #ifndef __meta__
296 #define __meta__
297
298 struct Meta
299 {
300 virtual ~Meta() {};
301 virtual void declare(const char* key, const char* value) = 0;
302
303 };
304
305 #endif
306 /************************** END meta.h **************************/
307 /************************** BEGIN UI.h **************************/
308 /************************************************************************
309 FAUST Architecture File
310 Copyright (C) 2003-2020 GRAME, Centre National de Creation Musicale
311 ---------------------------------------------------------------------
312 This Architecture section is free software; you can redistribute it
313 and/or modify it under the terms of the GNU General Public License
314 as published by the Free Software Foundation; either version 3 of
315 the License, or (at your option) any later version.
316
317 This program is distributed in the hope that it will be useful,
318 but WITHOUT ANY WARRANTY; without even the implied warranty of
319 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
320 GNU General Public License for more details.
321
322 You should have received a copy of the GNU General Public License
323 along with this program; If not, see <http://www.gnu.org/licenses/>.
324
325 EXCEPTION : As a special exception, you may create a larger work
326 that contains this FAUST architecture section and distribute
327 that work under terms of your choice, so long as this FAUST
328 architecture section is not modified.
329 ************************************************************************/
330
331 #ifndef __UI_H__
332 #define __UI_H__
333
334 #ifndef FAUSTFLOAT
335 #define FAUSTFLOAT float
336 #endif
337
338 /*******************************************************************************
339 * UI : Faust DSP User Interface
340 * User Interface as expected by the buildUserInterface() method of a DSP.
341 * This abstract class contains only the method that the Faust compiler can
342 * generate to describe a DSP user interface.
343 ******************************************************************************/
344
345 struct Soundfile;
346
347 template <typename REAL>
348 struct UIReal
349 {
350 UIReal() {}
351 virtual ~UIReal() {}
352
353 // -- widget's layouts
354
355 virtual void openTabBox(const char* label) = 0;
356 virtual void openHorizontalBox(const char* label) = 0;
357 virtual void openVerticalBox(const char* label) = 0;
358 virtual void closeBox() = 0;
359
360 // -- active widgets
361
362 virtual void addButton(const char* label, REAL* zone) = 0;
363 virtual void addCheckButton(const char* label, REAL* zone) = 0;
364 virtual void addVerticalSlider(const char* label, REAL* zone, REAL init, REAL min, REAL max, REAL step) = 0;
365 virtual void addHorizontalSlider(const char* label, REAL* zone, REAL init, REAL min, REAL max, REAL step) = 0;
366 virtual void addNumEntry(const char* label, REAL* zone, REAL init, REAL min, REAL max, REAL step) = 0;
367
368 // -- passive widgets
369
370 virtual void addHorizontalBargraph(const char* label, REAL* zone, REAL min, REAL max) = 0;
371 virtual void addVerticalBargraph(const char* label, REAL* zone, REAL min, REAL max) = 0;
372
373 // -- soundfiles
374
375 virtual void addSoundfile(const char* label, const char* filename, Soundfile** sf_zone) = 0;
376
377 // -- metadata declarations
378
379 virtual void declare(REAL* zone, const char* key, const char* val) {}
380 };
381
382 struct UI : public UIReal<FAUSTFLOAT>
383 {
384 UI() {}
385 virtual ~UI() {}
386 };
387
388 #endif
389 /************************** END UI.h **************************/
390 /************************** BEGIN PathBuilder.h **************************/
391 /************************************************************************
392 FAUST Architecture File
393 Copyright (C) 2003-2017 GRAME, Centre National de Creation Musicale
394 ---------------------------------------------------------------------
395 This Architecture section is free software; you can redistribute it
396 and/or modify it under the terms of the GNU General Public License
397 as published by the Free Software Foundation; either version 3 of
398 the License, or (at your option) any later version.
399
400 This program is distributed in the hope that it will be useful,
401 but WITHOUT ANY WARRANTY; without even the implied warranty of
402 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
403 GNU General Public License for more details.
404
405 You should have received a copy of the GNU General Public License
406 along with this program; If not, see <http://www.gnu.org/licenses/>.
407
408 EXCEPTION : As a special exception, you may create a larger work
409 that contains this FAUST architecture section and distribute
410 that work under terms of your choice, so long as this FAUST
411 architecture section is not modified.
412 ************************************************************************/
413
414 #ifndef FAUST_PATHBUILDER_H
415 #define FAUST_PATHBUILDER_H
416
417 #include <vector>
418 #include <string>
419 #include <algorithm>
420
421 /*******************************************************************************
422 * PathBuilder : Faust User Interface
423 * Helper class to build complete hierarchical path for UI items.
424 ******************************************************************************/
425
426 class PathBuilder
427 {
428
429 protected:
430
431 std::vector<std::string> fControlsLevel;
432
433 public:
434
435 PathBuilder() {}
436 virtual ~PathBuilder() {}
437
438 std::string buildPath(const std::string& label)
439 {
440 std::string res = "/";
441 for (size_t i = 0; i < fControlsLevel.size(); i++) {
442 res += fControlsLevel[i];
443 res += "/";
444 }
445 res += label;
446 std::replace(res.begin(), res.end(), ' ', '_');
447 return res;
448 }
449
450 std::string buildLabel(std::string label)
451 {
452 std::replace(label.begin(), label.end(), ' ', '_');
453 return label;
454 }
455
456 void pushLabel(const std::string& label) { fControlsLevel.push_back(label); }
457 void popLabel() { fControlsLevel.pop_back(); }
458
459 };
460
461 #endif // FAUST_PATHBUILDER_H
462 /************************** END PathBuilder.h **************************/
463 /************************** BEGIN ValueConverter.h **************************/
464 /************************************************************************
465 FAUST Architecture File
466 Copyright (C) 2003-2017 GRAME, Centre National de Creation Musicale
467 ---------------------------------------------------------------------
468 This Architecture section is free software; you can redistribute it
469 and/or modify it under the terms of the GNU General Public License
470 as published by the Free Software Foundation; either version 3 of
471 the License, or (at your option) any later version.
472
473 This program is distributed in the hope that it will be useful,
474 but WITHOUT ANY WARRANTY; without even the implied warranty of
475 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
476 GNU General Public License for more details.
477
478 You should have received a copy of the GNU General Public License
479 along with this program; If not, see <http://www.gnu.org/licenses/>.
480
481 EXCEPTION : As a special exception, you may create a larger work
482 that contains this FAUST architecture section and distribute
483 that work under terms of your choice, so long as this FAUST
484 architecture section is not modified.
485 ************************************************************************/
486
487 #ifndef __ValueConverter__
488 #define __ValueConverter__
489
490 /***************************************************************************************
491 ValueConverter.h
492 (GRAME, Copyright 2015-2019)
493
494 Set of conversion objects used to map user interface values (for example a gui slider
495 delivering values between 0 and 1) to faust values (for example a vslider between
496 20 and 20000) using a log scale.
497
498 -- Utilities
499
500 Range(lo,hi) : clip a value x between lo and hi
501 Interpolator(lo,hi,v1,v2) : Maps a value x between lo and hi to a value y between v1 and v2
502 Interpolator3pt(lo,mi,hi,v1,vm,v2) : Map values between lo mid hi to values between v1 vm v2
503
504 -- Value Converters
505
506 ValueConverter::ui2faust(x)
507 ValueConverter::faust2ui(x)
508
509 -- ValueConverters used for sliders depending of the scale
510
511 LinearValueConverter(umin, umax, fmin, fmax)
512 LinearValueConverter2(lo, mi, hi, v1, vm, v2) using 2 segments
513 LogValueConverter(umin, umax, fmin, fmax)
514 ExpValueConverter(umin, umax, fmin, fmax)
515
516 -- ValueConverters used for accelerometers based on 3 points
517
518 AccUpConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 0
519 AccDownConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 1
520 AccUpDownConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 2
521 AccDownUpConverter(amin, amid, amax, fmin, fmid, fmax) -- curve 3
522
523 -- lists of ZoneControl are used to implement accelerometers metadata for each axes
524
525 ZoneControl(zone, valueConverter) : a zone with an accelerometer data converter
526
527 -- ZoneReader are used to implement screencolor metadata
528
529 ZoneReader(zone, valueConverter) : a zone with a data converter
530
531 ****************************************************************************************/
532
533 #include <float.h>
534 #include <algorithm> // std::max
535 #include <cmath>
536 #include <vector>
537 #include <assert.h>
538
539 //--------------------------------------------------------------------------------------
540 // Interpolator(lo,hi,v1,v2)
541 // Maps a value x between lo and hi to a value y between v1 and v2
542 // y = v1 + (x-lo)/(hi-lo)*(v2-v1)
543 // y = v1 + (x-lo) * coef with coef = (v2-v1)/(hi-lo)
544 // y = v1 + x*coef - lo*coef
545 // y = v1 - lo*coef + x*coef
546 // y = offset + x*coef with offset = v1 - lo*coef
547 //--------------------------------------------------------------------------------------
548 class Interpolator
549 {
550 private:
551
552 //--------------------------------------------------------------------------------------
553 // Range(lo,hi) clip a value between lo and hi
554 //--------------------------------------------------------------------------------------
555 struct Range
556 {
557 double fLo;
558 double fHi;
559
560 Range(double x, double y) : fLo(std::min<double>(x,y)), fHi(std::max<double>(x,y)) {}
561 double operator()(double x) { return (x<fLo) ? fLo : (x>fHi) ? fHi : x; }
562 };
563
564
565 Range fRange;
566 double fCoef;
567 double fOffset;
568
569 public:
570
571 Interpolator(double lo, double hi, double v1, double v2) : fRange(lo,hi)
572 {
573 if (hi != lo) {
574 // regular case
575 fCoef = (v2-v1)/(hi-lo);
576 fOffset = v1 - lo*fCoef;
577 } else {
578 // degenerate case, avoids division by zero
579 fCoef = 0;
580 fOffset = (v1+v2)/2;
581 }
582 }
583 double operator()(double v)
584 {
585 double x = fRange(v);
586 return fOffset + x*fCoef;
587 }
588
589 void getLowHigh(double& amin, double& amax)
590 {
591 amin = fRange.fLo;
592 amax = fRange.fHi;
593 }
594 };
595
596 //--------------------------------------------------------------------------------------
597 // Interpolator3pt(lo,mi,hi,v1,vm,v2)
598 // Map values between lo mid hi to values between v1 vm v2
599 //--------------------------------------------------------------------------------------
600 class Interpolator3pt
601 {
602
603 private:
604
605 Interpolator fSegment1;
606 Interpolator fSegment2;
607 double fMid;
608
609 public:
610
611 Interpolator3pt(double lo, double mi, double hi, double v1, double vm, double v2) :
612 fSegment1(lo, mi, v1, vm),
613 fSegment2(mi, hi, vm, v2),
614 fMid(mi) {}
615 double operator()(double x) { return (x < fMid) ? fSegment1(x) : fSegment2(x); }
616
617 void getMappingValues(double& amin, double& amid, double& amax)
618 {
619 fSegment1.getLowHigh(amin, amid);
620 fSegment2.getLowHigh(amid, amax);
621 }
622 };
623
624 //--------------------------------------------------------------------------------------
625 // Abstract ValueConverter class. Converts values between UI and Faust representations
626 //--------------------------------------------------------------------------------------
627 class ValueConverter
628 {
629
630 public:
631
632 virtual ~ValueConverter() {}
633 virtual double ui2faust(double x) = 0;
634 virtual double faust2ui(double x) = 0;
635 };
636
637 //--------------------------------------------------------------------------------------
638 // A converter than can be updated
639 //--------------------------------------------------------------------------------------
640
641 class UpdatableValueConverter : public ValueConverter {
642
643 protected:
644
645 bool fActive;
646
647 public:
648
649 UpdatableValueConverter():fActive(true)
650 {}
651 virtual ~UpdatableValueConverter()
652 {}
653
654 virtual void setMappingValues(double amin, double amid, double amax, double min, double init, double max) = 0;
655 virtual void getMappingValues(double& amin, double& amid, double& amax) = 0;
656
657 void setActive(bool on_off) { fActive = on_off; }
658 bool getActive() { return fActive; }
659
660 };
661
662
663 //--------------------------------------------------------------------------------------
664 // Linear conversion between ui and Faust values
665 //--------------------------------------------------------------------------------------
666 class LinearValueConverter : public ValueConverter
667 {
668
669 private:
670
671 Interpolator fUI2F;
672 Interpolator fF2UI;
673
674 public:
675
676 LinearValueConverter(double umin, double umax, double fmin, double fmax) :
677 fUI2F(umin,umax,fmin,fmax), fF2UI(fmin,fmax,umin,umax)
678 {}
679
680 LinearValueConverter() : fUI2F(0.,0.,0.,0.), fF2UI(0.,0.,0.,0.)
681 {}
682 virtual double ui2faust(double x) { return fUI2F(x); }
683 virtual double faust2ui(double x) { return fF2UI(x); }
684
685 };
686
687 //--------------------------------------------------------------------------------------
688 // Two segments linear conversion between ui and Faust values
689 //--------------------------------------------------------------------------------------
690 class LinearValueConverter2 : public UpdatableValueConverter
691 {
692
693 private:
694
695 Interpolator3pt fUI2F;
696 Interpolator3pt fF2UI;
697
698 public:
699
700 LinearValueConverter2(double amin, double amid, double amax, double min, double init, double max) :
701 fUI2F(amin, amid, amax, min, init, max), fF2UI(min, init, max, amin, amid, amax)
702 {}
703
704 LinearValueConverter2() : fUI2F(0.,0.,0.,0.,0.,0.), fF2UI(0.,0.,0.,0.,0.,0.)
705 {}
706
707 virtual double ui2faust(double x) { return fUI2F(x); }
708 virtual double faust2ui(double x) { return fF2UI(x); }
709
710 virtual void setMappingValues(double amin, double amid, double amax, double min, double init, double max)
711 {
712 fUI2F = Interpolator3pt(amin, amid, amax, min, init, max);
713 fF2UI = Interpolator3pt(min, init, max, amin, amid, amax);
714 }
715
716 virtual void getMappingValues(double& amin, double& amid, double& amax)
717 {
718 fUI2F.getMappingValues(amin, amid, amax);
719 }
720
721 };
722
723 //--------------------------------------------------------------------------------------
724 // Logarithmic conversion between ui and Faust values
725 //--------------------------------------------------------------------------------------
726 class LogValueConverter : public LinearValueConverter
727 {
728
729 public:
730
731 LogValueConverter(double umin, double umax, double fmin, double fmax) :
732 LinearValueConverter(umin, umax, std::log(std::max<double>(DBL_MIN, fmin)), std::log(std::max<double>(DBL_MIN, fmax)))
733 {}
734
735 virtual double ui2faust(double x) { return std::exp(LinearValueConverter::ui2faust(x)); }
736 virtual double faust2ui(double x) { return LinearValueConverter::faust2ui(std::log(std::max<double>(x, DBL_MIN))); }
737
738 };
739
740 //--------------------------------------------------------------------------------------
741 // Exponential conversion between ui and Faust values
742 //--------------------------------------------------------------------------------------
743 class ExpValueConverter : public LinearValueConverter
744 {
745
746 public:
747
748 ExpValueConverter(double umin, double umax, double fmin, double fmax) :
749 LinearValueConverter(umin, umax, std::min<double>(DBL_MAX, std::exp(fmin)), std::min<double>(DBL_MAX, std::exp(fmax)))
750 {}
751
752 virtual double ui2faust(double x) { return std::log(LinearValueConverter::ui2faust(x)); }
753 virtual double faust2ui(double x) { return LinearValueConverter::faust2ui(std::min<double>(DBL_MAX, std::exp(x))); }
754
755 };
756
757 //--------------------------------------------------------------------------------------
758 // Convert accelerometer or gyroscope values to Faust values
759 // Using an Up curve (curve 0)
760 //--------------------------------------------------------------------------------------
761 class AccUpConverter : public UpdatableValueConverter
762 {
763
764 private:
765
766 Interpolator3pt fA2F;
767 Interpolator3pt fF2A;
768
769 public:
770
771 AccUpConverter(double amin, double amid, double amax, double fmin, double fmid, double fmax) :
772 fA2F(amin,amid,amax,fmin,fmid,fmax),
773 fF2A(fmin,fmid,fmax,amin,amid,amax)
774 {}
775
776 virtual double ui2faust(double x) { return fA2F(x); }
777 virtual double faust2ui(double x) { return fF2A(x); }
778
779 virtual void setMappingValues(double amin, double amid, double amax, double fmin, double fmid, double fmax)
780 {
781 //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccUpConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax);
782 fA2F = Interpolator3pt(amin, amid, amax, fmin, fmid, fmax);
783 fF2A = Interpolator3pt(fmin, fmid, fmax, amin, amid, amax);
784 }
785
786 virtual void getMappingValues(double& amin, double& amid, double& amax)
787 {
788 fA2F.getMappingValues(amin, amid, amax);
789 }
790
791 };
792
793 //--------------------------------------------------------------------------------------
794 // Convert accelerometer or gyroscope values to Faust values
795 // Using a Down curve (curve 1)
796 //--------------------------------------------------------------------------------------
797 class AccDownConverter : public UpdatableValueConverter
798 {
799
800 private:
801
802 Interpolator3pt fA2F;
803 Interpolator3pt fF2A;
804
805 public:
806
807 AccDownConverter(double amin, double amid, double amax, double fmin, double fmid, double fmax) :
808 fA2F(amin,amid,amax,fmax,fmid,fmin),
809 fF2A(fmin,fmid,fmax,amax,amid,amin)
810 {}
811
812 virtual double ui2faust(double x) { return fA2F(x); }
813 virtual double faust2ui(double x) { return fF2A(x); }
814
815 virtual void setMappingValues(double amin, double amid, double amax, double fmin, double fmid, double fmax)
816 {
817 //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccDownConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax);
818 fA2F = Interpolator3pt(amin, amid, amax, fmax, fmid, fmin);
819 fF2A = Interpolator3pt(fmin, fmid, fmax, amax, amid, amin);
820 }
821
822 virtual void getMappingValues(double& amin, double& amid, double& amax)
823 {
824 fA2F.getMappingValues(amin, amid, amax);
825 }
826 };
827
828 //--------------------------------------------------------------------------------------
829 // Convert accelerometer or gyroscope values to Faust values
830 // Using an Up-Down curve (curve 2)
831 //--------------------------------------------------------------------------------------
832 class AccUpDownConverter : public UpdatableValueConverter
833 {
834
835 private:
836
837 Interpolator3pt fA2F;
838 Interpolator fF2A;
839
840 public:
841
842 AccUpDownConverter(double amin, double amid, double amax, double fmin, double fmid, double fmax) :
843 fA2F(amin,amid,amax,fmin,fmax,fmin),
844 fF2A(fmin,fmax,amin,amax) // Special, pseudo inverse of a non monotonic function
845 {}
846
847 virtual double ui2faust(double x) { return fA2F(x); }
848 virtual double faust2ui(double x) { return fF2A(x); }
849
850 virtual void setMappingValues(double amin, double amid, double amax, double fmin, double fmid, double fmax)
851 {
852 //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccUpDownConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax);
853 fA2F = Interpolator3pt(amin, amid, amax, fmin, fmax, fmin);
854 fF2A = Interpolator(fmin, fmax, amin, amax);
855 }
856
857 virtual void getMappingValues(double& amin, double& amid, double& amax)
858 {
859 fA2F.getMappingValues(amin, amid, amax);
860 }
861 };
862
863 //--------------------------------------------------------------------------------------
864 // Convert accelerometer or gyroscope values to Faust values
865 // Using a Down-Up curve (curve 3)
866 //--------------------------------------------------------------------------------------
867 class AccDownUpConverter : public UpdatableValueConverter
868 {
869
870 private:
871
872 Interpolator3pt fA2F;
873 Interpolator fF2A;
874
875 public:
876
877 AccDownUpConverter(double amin, double amid, double amax, double fmin, double fmid, double fmax) :
878 fA2F(amin,amid,amax,fmax,fmin,fmax),
879 fF2A(fmin,fmax,amin,amax) // Special, pseudo inverse of a non monotonic function
880 {}
881
882 virtual double ui2faust(double x) { return fA2F(x); }
883 virtual double faust2ui(double x) { return fF2A(x); }
884
885 virtual void setMappingValues(double amin, double amid, double amax, double fmin, double fmid, double fmax)
886 {
887 //__android_log_print(ANDROID_LOG_ERROR, "Faust", "AccDownUpConverter update %f %f %f %f %f %f", amin,amid,amax,fmin,fmid,fmax);
888 fA2F = Interpolator3pt(amin, amid, amax, fmax, fmin, fmax);
889 fF2A = Interpolator(fmin, fmax, amin, amax);
890 }
891
892 virtual void getMappingValues(double& amin, double& amid, double& amax)
893 {
894 fA2F.getMappingValues(amin, amid, amax);
895 }
896 };
897
898 //--------------------------------------------------------------------------------------
899 // Base class for ZoneControl
900 //--------------------------------------------------------------------------------------
901 class ZoneControl
902 {
903
904 protected:
905
906 FAUSTFLOAT* fZone;
907
908 public:
909
910 ZoneControl(FAUSTFLOAT* zone) : fZone(zone) {}
911 virtual ~ZoneControl() {}
912
913 virtual void update(double v) const {}
914
915 virtual void setMappingValues(int curve, double amin, double amid, double amax, double min, double init, double max) {}
916 virtual void getMappingValues(double& amin, double& amid, double& amax) {}
917
918 FAUSTFLOAT* getZone() { return fZone; }
919
920 virtual void setActive(bool on_off) {}
921 virtual bool getActive() { return false; }
922
923 virtual int getCurve() { return -1; }
924
925 };
926
927 //--------------------------------------------------------------------------------------
928 // Useful to implement accelerometers metadata as a list of ZoneControl for each axes
929 //--------------------------------------------------------------------------------------
930 class ConverterZoneControl : public ZoneControl
931 {
932
933 protected:
934
935 ValueConverter* fValueConverter;
936
937 public:
938
939 ConverterZoneControl(FAUSTFLOAT* zone, ValueConverter* converter) : ZoneControl(zone), fValueConverter(converter) {}
940 virtual ~ConverterZoneControl() { delete fValueConverter; } // Assuming fValueConverter is not kept elsewhere...
941
942 virtual void update(double v) const { *fZone = fValueConverter->ui2faust(v); }
943
944 ValueConverter* getConverter() { return fValueConverter; }
945
946 };
947
948 //--------------------------------------------------------------------------------------
949 // Association of a zone and a four value converter, each one for each possible curve.
950 // Useful to implement accelerometers metadata as a list of ZoneControl for each axes
951 //--------------------------------------------------------------------------------------
952 class CurveZoneControl : public ZoneControl
953 {
954
955 private:
956
957 std::vector<UpdatableValueConverter*> fValueConverters;
958 int fCurve;
959
960 public:
961
962 CurveZoneControl(FAUSTFLOAT* zone, int curve, double amin, double amid, double amax, double min, double init, double max) : ZoneControl(zone), fCurve(0)
963 {
964 assert(curve >= 0 && curve <= 3);
965 fValueConverters.push_back(new AccUpConverter(amin, amid, amax, min, init, max));
966 fValueConverters.push_back(new AccDownConverter(amin, amid, amax, min, init, max));
967 fValueConverters.push_back(new AccUpDownConverter(amin, amid, amax, min, init, max));
968 fValueConverters.push_back(new AccDownUpConverter(amin, amid, amax, min, init, max));
969 fCurve = curve;
970 }
971 virtual ~CurveZoneControl()
972 {
973 std::vector<UpdatableValueConverter*>::iterator it;
974 for (it = fValueConverters.begin(); it != fValueConverters.end(); it++) {
975 delete(*it);
976 }
977 }
978 void update(double v) const { if (fValueConverters[fCurve]->getActive()) *fZone = fValueConverters[fCurve]->ui2faust(v); }
979
980 void setMappingValues(int curve, double amin, double amid, double amax, double min, double init, double max)
981 {
982 fValueConverters[curve]->setMappingValues(amin, amid, amax, min, init, max);
983 fCurve = curve;
984 }
985
986 void getMappingValues(double& amin, double& amid, double& amax)
987 {
988 fValueConverters[fCurve]->getMappingValues(amin, amid, amax);
989 }
990
991 void setActive(bool on_off)
992 {
993 std::vector<UpdatableValueConverter*>::iterator it;
994 for (it = fValueConverters.begin(); it != fValueConverters.end(); it++) {
995 (*it)->setActive(on_off);
996 }
997 }
998
999 int getCurve() { return fCurve; }
1000 };
1001
1002 class ZoneReader
1003 {
1004
1005 private:
1006
1007 FAUSTFLOAT* fZone;
1008 Interpolator fInterpolator;
1009
1010 public:
1011
1012 ZoneReader(FAUSTFLOAT* zone, double lo, double hi) : fZone(zone), fInterpolator(lo, hi, 0, 255) {}
1013
1014 virtual ~ZoneReader() {}
1015
1016 int getValue()
1017 {
1018 return (fZone != nullptr) ? int(fInterpolator(*fZone)) : 127;
1019 }
1020
1021 };
1022
1023 #endif
1024 /************************** END ValueConverter.h **************************/
1025
1026 class APIUI : public PathBuilder, public Meta, public UI
1027 {
1028 public:
1029
1030 enum ItemType { kButton = 0, kCheckButton, kVSlider, kHSlider, kNumEntry, kHBargraph, kVBargraph };
1031
1032 protected:
1033
1034 enum { kLin = 0, kLog = 1, kExp = 2 };
1035
1036 int fNumParameters;
1037 std::vector<std::string> fPaths;
1038 std::vector<std::string> fLabels;
1039 std::map<std::string, int> fPathMap;
1040 std::map<std::string, int> fLabelMap;
1041 std::vector<ValueConverter*> fConversion;
1042 std::vector<FAUSTFLOAT*> fZone;
1043 std::vector<FAUSTFLOAT> fInit;
1044 std::vector<FAUSTFLOAT> fMin;
1045 std::vector<FAUSTFLOAT> fMax;
1046 std::vector<FAUSTFLOAT> fStep;
1047 std::vector<ItemType> fItemType;
1048 std::vector<std::map<std::string, std::string> > fMetaData;
1049 std::vector<ZoneControl*> fAcc[3];
1050 std::vector<ZoneControl*> fGyr[3];
1051
1052 // Screen color control
1053 // "...[screencolor:red]..." etc.
1054 bool fHasScreenControl; // true if control screen color metadata
1055 ZoneReader* fRedReader;
1056 ZoneReader* fGreenReader;
1057 ZoneReader* fBlueReader;
1058
1059 // Current values controlled by metadata
1060 std::string fCurrentUnit;
1061 int fCurrentScale;
1062 std::string fCurrentAcc;
1063 std::string fCurrentGyr;
1064 std::string fCurrentColor;
1065 std::string fCurrentTooltip;
1066 std::map<std::string, std::string> fCurrentMetadata;
1067
1068 // Add a generic parameter
1069 virtual void addParameter(const char* label,
1070 FAUSTFLOAT* zone,
1071 FAUSTFLOAT init,
1072 FAUSTFLOAT min,
1073 FAUSTFLOAT max,
1074 FAUSTFLOAT step,
1075 ItemType type)
1076 {
1077 std::string path = buildPath(label);
1078 fPathMap[path] = fLabelMap[label] = fNumParameters++;
1079 fPaths.push_back(path);
1080 fLabels.push_back(label);
1081 fZone.push_back(zone);
1082 fInit.push_back(init);
1083 fMin.push_back(min);
1084 fMax.push_back(max);
1085 fStep.push_back(step);
1086 fItemType.push_back(type);
1087
1088 // handle scale metadata
1089 switch (fCurrentScale) {
1090 case kLin:
1091 fConversion.push_back(new LinearValueConverter(0, 1, min, max));
1092 break;
1093 case kLog:
1094 fConversion.push_back(new LogValueConverter(0, 1, min, max));
1095 break;
1096 case kExp: fConversion.push_back(new ExpValueConverter(0, 1, min, max));
1097 break;
1098 }
1099 fCurrentScale = kLin;
1100
1101 if (fCurrentAcc.size() > 0 && fCurrentGyr.size() > 0) {
1102 std::cerr << "warning : 'acc' and 'gyr' metadata used for the same " << label << " parameter !!\n";
1103 }
1104
1105 // handle acc metadata "...[acc : <axe> <curve> <amin> <amid> <amax>]..."
1106 if (fCurrentAcc.size() > 0) {
1107 std::istringstream iss(fCurrentAcc);
1108 int axe, curve;
1109 double amin, amid, amax;
1110 iss >> axe >> curve >> amin >> amid >> amax;
1111
1112 if ((0 <= axe) && (axe < 3) &&
1113 (0 <= curve) && (curve < 4) &&
1114 (amin < amax) && (amin <= amid) && (amid <= amax))
1115 {
1116 fAcc[axe].push_back(new CurveZoneControl(zone, curve, amin, amid, amax, min, init, max));
1117 } else {
1118 std::cerr << "incorrect acc metadata : " << fCurrentAcc << std::endl;
1119 }
1120 fCurrentAcc = "";
1121 }
1122
1123 // handle gyr metadata "...[gyr : <axe> <curve> <amin> <amid> <amax>]..."
1124 if (fCurrentGyr.size() > 0) {
1125 std::istringstream iss(fCurrentGyr);
1126 int axe, curve;
1127 double amin, amid, amax;
1128 iss >> axe >> curve >> amin >> amid >> amax;
1129
1130 if ((0 <= axe) && (axe < 3) &&
1131 (0 <= curve) && (curve < 4) &&
1132 (amin < amax) && (amin <= amid) && (amid <= amax))
1133 {
1134 fGyr[axe].push_back(new CurveZoneControl(zone, curve, amin, amid, amax, min, init, max));
1135 } else {
1136 std::cerr << "incorrect gyr metadata : " << fCurrentGyr << std::endl;
1137 }
1138 fCurrentGyr = "";
1139 }
1140
1141 // handle screencolor metadata "...[screencolor:red|green|blue|white]..."
1142 if (fCurrentColor.size() > 0) {
1143 if ((fCurrentColor == "red") && (fRedReader == 0)) {
1144 fRedReader = new ZoneReader(zone, min, max);
1145 fHasScreenControl = true;
1146 } else if ((fCurrentColor == "green") && (fGreenReader == 0)) {
1147 fGreenReader = new ZoneReader(zone, min, max);
1148 fHasScreenControl = true;
1149 } else if ((fCurrentColor == "blue") && (fBlueReader == 0)) {
1150 fBlueReader = new ZoneReader(zone, min, max);
1151 fHasScreenControl = true;
1152 } else if ((fCurrentColor == "white") && (fRedReader == 0) && (fGreenReader == 0) && (fBlueReader == 0)) {
1153 fRedReader = new ZoneReader(zone, min, max);
1154 fGreenReader = new ZoneReader(zone, min, max);
1155 fBlueReader = new ZoneReader(zone, min, max);
1156 fHasScreenControl = true;
1157 } else {
1158 std::cerr << "incorrect screencolor metadata : " << fCurrentColor << std::endl;
1159 }
1160 }
1161 fCurrentColor = "";
1162
1163 fMetaData.push_back(fCurrentMetadata);
1164 fCurrentMetadata.clear();
1165 }
1166
1167 int getZoneIndex(std::vector<ZoneControl*>* table, int p, int val)
1168 {
1169 FAUSTFLOAT* zone = fZone[p];
1170 for (size_t i = 0; i < table[val].size(); i++) {
1171 if (zone == table[val][i]->getZone()) return int(i);
1172 }
1173 return -1;
1174 }
1175
1176 void setConverter(std::vector<ZoneControl*>* table, int p, int val, int curve, double amin, double amid, double amax)
1177 {
1178 int id1 = getZoneIndex(table, p, 0);
1179 int id2 = getZoneIndex(table, p, 1);
1180 int id3 = getZoneIndex(table, p, 2);
1181
1182 // Deactivates everywhere..
1183 if (id1 != -1) table[0][id1]->setActive(false);
1184 if (id2 != -1) table[1][id2]->setActive(false);
1185 if (id3 != -1) table[2][id3]->setActive(false);
1186
1187 if (val == -1) { // Means: no more mapping...
1188 // So stay all deactivated...
1189 } else {
1190 int id4 = getZoneIndex(table, p, val);
1191 if (id4 != -1) {
1192 // Reactivate the one we edit...
1193 table[val][id4]->setMappingValues(curve, amin, amid, amax, fMin[p], fInit[p], fMax[p]);
1194 table[val][id4]->setActive(true);
1195 } else {
1196 // Allocate a new CurveZoneControl which is 'active' by default
1197 FAUSTFLOAT* zone = fZone[p];
1198 table[val].push_back(new CurveZoneControl(zone, curve, amin, amid, amax, fMin[p], fInit[p], fMax[p]));
1199 }
1200 }
1201 }
1202
1203 void getConverter(std::vector<ZoneControl*>* table, int p, int& val, int& curve, double& amin, double& amid, double& amax)
1204 {
1205 int id1 = getZoneIndex(table, p, 0);
1206 int id2 = getZoneIndex(table, p, 1);
1207 int id3 = getZoneIndex(table, p, 2);
1208
1209 if (id1 != -1) {
1210 val = 0;
1211 curve = table[val][id1]->getCurve();
1212 table[val][id1]->getMappingValues(amin, amid, amax);
1213 } else if (id2 != -1) {
1214 val = 1;
1215 curve = table[val][id2]->getCurve();
1216 table[val][id2]->getMappingValues(amin, amid, amax);
1217 } else if (id3 != -1) {
1218 val = 2;
1219 curve = table[val][id3]->getCurve();
1220 table[val][id3]->getMappingValues(amin, amid, amax);
1221 } else {
1222 val = -1; // No mapping
1223 curve = 0;
1224 amin = -100.;
1225 amid = 0.;
1226 amax = 100.;
1227 }
1228 }
1229
1230 public:
1231
1232 enum Type { kAcc = 0, kGyr = 1, kNoType };
1233
1234 APIUI() : fNumParameters(0), fHasScreenControl(false), fRedReader(0), fGreenReader(0), fBlueReader(0), fCurrentScale(kLin)
1235 {}
1236
1237 virtual ~APIUI()
1238 {
1239 for (auto& it : fConversion) delete it;
1240 for (int i = 0; i < 3; i++) {
1241 for (auto& it : fAcc[i]) delete it;
1242 for (auto& it : fGyr[i]) delete it;
1243 }
1244 delete fRedReader;
1245 delete fGreenReader;
1246 delete fBlueReader;
1247 }
1248
1249 // -- widget's layouts
1250
1251 virtual void openTabBox(const char* label) { pushLabel(label); }
1252 virtual void openHorizontalBox(const char* label) { pushLabel(label); }
1253 virtual void openVerticalBox(const char* label) { pushLabel(label); }
1254 virtual void closeBox() { popLabel(); }
1255
1256 // -- active widgets
1257
1258 virtual void addButton(const char* label, FAUSTFLOAT* zone)
1259 {
1260 addParameter(label, zone, 0, 0, 1, 1, kButton);
1261 }
1262
1263 virtual void addCheckButton(const char* label, FAUSTFLOAT* zone)
1264 {
1265 addParameter(label, zone, 0, 0, 1, 1, kCheckButton);
1266 }
1267
1268 virtual void addVerticalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step)
1269 {
1270 addParameter(label, zone, init, min, max, step, kVSlider);
1271 }
1272
1273 virtual void addHorizontalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step)
1274 {
1275 addParameter(label, zone, init, min, max, step, kHSlider);
1276 }
1277
1278 virtual void addNumEntry(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step)
1279 {
1280 addParameter(label, zone, init, min, max, step, kNumEntry);
1281 }
1282
1283 // -- passive widgets
1284
1285 virtual void addHorizontalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max)
1286 {
1287 addParameter(label, zone, min, min, max, (max-min)/1000.0, kHBargraph);
1288 }
1289
1290 virtual void addVerticalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max)
1291 {
1292 addParameter(label, zone, min, min, max, (max-min)/1000.0, kVBargraph);
1293 }
1294
1295 // -- soundfiles
1296
1297 virtual void addSoundfile(const char* label, const char* filename, Soundfile** sf_zone) {}
1298
1299 // -- metadata declarations
1300
1301 virtual void declare(FAUSTFLOAT* zone, const char* key, const char* val)
1302 {
1303 // Keep metadata
1304 fCurrentMetadata[key] = val;
1305
1306 if (strcmp(key, "scale") == 0) {
1307 if (strcmp(val, "log") == 0) {
1308 fCurrentScale = kLog;
1309 } else if (strcmp(val, "exp") == 0) {
1310 fCurrentScale = kExp;
1311 } else {
1312 fCurrentScale = kLin;
1313 }
1314 } else if (strcmp(key, "unit") == 0) {
1315 fCurrentUnit = val;
1316 } else if (strcmp(key, "acc") == 0) {
1317 fCurrentAcc = val;
1318 } else if (strcmp(key, "gyr") == 0) {
1319 fCurrentGyr = val;
1320 } else if (strcmp(key, "screencolor") == 0) {
1321 fCurrentColor = val; // val = "red", "green", "blue" or "white"
1322 } else if (strcmp(key, "tooltip") == 0) {
1323 fCurrentTooltip = val;
1324 }
1325 }
1326
1327 virtual void declare(const char* key, const char* val)
1328 {}
1329
1330 //-------------------------------------------------------------------------------
1331 // Simple API part
1332 //-------------------------------------------------------------------------------
1333 int getParamsCount() { return fNumParameters; }
1334 int getParamIndex(const char* path)
1335 {
1336 if (fPathMap.find(path) != fPathMap.end()) {
1337 return fPathMap[path];
1338 } else if (fLabelMap.find(path) != fLabelMap.end()) {
1339 return fLabelMap[path];
1340 } else {
1341 return -1;
1342 }
1343 }
1344 const char* getParamAddress(int p) { return fPaths[p].c_str(); }
1345 const char* getParamLabel(int p) { return fLabels[p].c_str(); }
1346 std::map<const char*, const char*> getMetadata(int p)
1347 {
1348 std::map<const char*, const char*> res;
1349 std::map<std::string, std::string> metadata = fMetaData[p];
1350 for (auto it : metadata) {
1351 res[it.first.c_str()] = it.second.c_str();
1352 }
1353 return res;
1354 }
1355
1356 const char* getMetadata(int p, const char* key)
1357 {
1358 return (fMetaData[p].find(key) != fMetaData[p].end()) ? fMetaData[p][key].c_str() : "";
1359 }
1360 FAUSTFLOAT getParamMin(int p) { return fMin[p]; }
1361 FAUSTFLOAT getParamMax(int p) { return fMax[p]; }
1362 FAUSTFLOAT getParamStep(int p) { return fStep[p]; }
1363 FAUSTFLOAT getParamInit(int p) { return fInit[p]; }
1364
1365 FAUSTFLOAT* getParamZone(int p) { return fZone[p]; }
1366 FAUSTFLOAT getParamValue(int p) { return *fZone[p]; }
1367 void setParamValue(int p, FAUSTFLOAT v) { *fZone[p] = v; }
1368
1369 double getParamRatio(int p) { return fConversion[p]->faust2ui(*fZone[p]); }
1370 void setParamRatio(int p, double r) { *fZone[p] = fConversion[p]->ui2faust(r); }
1371
1372 double value2ratio(int p, double r) { return fConversion[p]->faust2ui(r); }
1373 double ratio2value(int p, double r) { return fConversion[p]->ui2faust(r); }
1374
1375 /**
1376 * Return the control type (kAcc, kGyr, or -1) for a given parameter
1377 *
1378 * @param p - the UI parameter index
1379 *
1380 * @return the type
1381 */
1382 Type getParamType(int p)
1383 {
1384 if (p >= 0) {
1385 if (getZoneIndex(fAcc, p, 0) != -1
1386 || getZoneIndex(fAcc, p, 1) != -1
1387 || getZoneIndex(fAcc, p, 2) != -1) {
1388 return kAcc;
1389 } else if (getZoneIndex(fGyr, p, 0) != -1
1390 || getZoneIndex(fGyr, p, 1) != -1
1391 || getZoneIndex(fGyr, p, 2) != -1) {
1392 return kGyr;
1393 }
1394 }
1395 return kNoType;
1396 }
1397
1398 /**
1399 * Return the Item type (kButton = 0, kCheckButton, kVSlider, kHSlider, kNumEntry, kHBargraph, kVBargraph) for a given parameter
1400 *
1401 * @param p - the UI parameter index
1402 *
1403 * @return the Item type
1404 */
1405 ItemType getParamItemType(int p)
1406 {
1407 return fItemType[p];
1408 }
1409
1410 /**
1411 * Set a new value coming from an accelerometer, propagate it to all relevant FAUSTFLOAT* zones.
1412 *
1413 * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer
1414 * @param value - the new value
1415 *
1416 */
1417 void propagateAcc(int acc, double value)
1418 {
1419 for (size_t i = 0; i < fAcc[acc].size(); i++) {
1420 fAcc[acc][i]->update(value);
1421 }
1422 }
1423
1424 /**
1425 * Used to edit accelerometer curves and mapping. Set curve and related mapping for a given UI parameter.
1426 *
1427 * @param p - the UI parameter index
1428 * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer (-1 means "no mapping")
1429 * @param curve - between 0 and 3
1430 * @param amin - mapping 'min' point
1431 * @param amid - mapping 'middle' point
1432 * @param amax - mapping 'max' point
1433 *
1434 */
1435 void setAccConverter(int p, int acc, int curve, double amin, double amid, double amax)
1436 {
1437 setConverter(fAcc, p, acc, curve, amin, amid, amax);
1438 }
1439
1440 /**
1441 * Used to edit gyroscope curves and mapping. Set curve and related mapping for a given UI parameter.
1442 *
1443 * @param p - the UI parameter index
1444 * @param acc - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope (-1 means "no mapping")
1445 * @param curve - between 0 and 3
1446 * @param amin - mapping 'min' point
1447 * @param amid - mapping 'middle' point
1448 * @param amax - mapping 'max' point
1449 *
1450 */
1451 void setGyrConverter(int p, int gyr, int curve, double amin, double amid, double amax)
1452 {
1453 setConverter(fGyr, p, gyr, curve, amin, amid, amax);
1454 }
1455
1456 /**
1457 * Used to edit accelerometer curves and mapping. Get curve and related mapping for a given UI parameter.
1458 *
1459 * @param p - the UI parameter index
1460 * @param acc - the acc value to be retrieved (-1 means "no mapping")
1461 * @param curve - the curve value to be retrieved
1462 * @param amin - the amin value to be retrieved
1463 * @param amid - the amid value to be retrieved
1464 * @param amax - the amax value to be retrieved
1465 *
1466 */
1467 void getAccConverter(int p, int& acc, int& curve, double& amin, double& amid, double& amax)
1468 {
1469 getConverter(fAcc, p, acc, curve, amin, amid, amax);
1470 }
1471
1472 /**
1473 * Used to edit gyroscope curves and mapping. Get curve and related mapping for a given UI parameter.
1474 *
1475 * @param p - the UI parameter index
1476 * @param gyr - the gyr value to be retrieved (-1 means "no mapping")
1477 * @param curve - the curve value to be retrieved
1478 * @param amin - the amin value to be retrieved
1479 * @param amid - the amid value to be retrieved
1480 * @param amax - the amax value to be retrieved
1481 *
1482 */
1483 void getGyrConverter(int p, int& gyr, int& curve, double& amin, double& amid, double& amax)
1484 {
1485 getConverter(fGyr, p, gyr, curve, amin, amid, amax);
1486 }
1487
1488 /**
1489 * Set a new value coming from an gyroscope, propagate it to all relevant FAUSTFLOAT* zones.
1490 *
1491 * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope
1492 * @param value - the new value
1493 *
1494 */
1495 void propagateGyr(int gyr, double value)
1496 {
1497 for (size_t i = 0; i < fGyr[gyr].size(); i++) {
1498 fGyr[gyr][i]->update(value);
1499 }
1500 }
1501
1502 /**
1503 * Get the number of FAUSTFLOAT* zones controlled with the accelerometer
1504 *
1505 * @param acc - 0 for X accelerometer, 1 for Y accelerometer, 2 for Z accelerometer
1506 * @return the number of zones
1507 *
1508 */
1509 int getAccCount(int acc)
1510 {
1511 return (acc >= 0 && acc < 3) ? int(fAcc[acc].size()) : 0;
1512 }
1513
1514 /**
1515 * Get the number of FAUSTFLOAT* zones controlled with the gyroscope
1516 *
1517 * @param gyr - 0 for X gyroscope, 1 for Y gyroscope, 2 for Z gyroscope
1518 * @param the number of zones
1519 *
1520 */
1521 int getGyrCount(int gyr)
1522 {
1523 return (gyr >= 0 && gyr < 3) ? int(fGyr[gyr].size()) : 0;
1524 }
1525
1526 // getScreenColor() : -1 means no screen color control (no screencolor metadata found)
1527 // otherwise return 0x00RRGGBB a ready to use color
1528 int getScreenColor()
1529 {
1530 if (fHasScreenControl) {
1531 int r = (fRedReader) ? fRedReader->getValue() : 0;
1532 int g = (fGreenReader) ? fGreenReader->getValue() : 0;
1533 int b = (fBlueReader) ? fBlueReader->getValue() : 0;
1534 return (r<<16) | (g<<8) | b;
1535 } else {
1536 return -1;
1537 }
1538 }
1539
1540 };
1541
1542 #endif
1543 /************************** END APIUI.h **************************/
1544
1545 // NOTE: "faust -scn name" changes the last line above to
1546 // #include <faust/name/name.h>
1547
1548 //----------------------------------------------------------------------------
1549 // FAUST Generated Code
1550 //----------------------------------------------------------------------------
1551
1552
1553 #ifndef FAUSTFLOAT
1554 #define FAUSTFLOAT float
1555 #endif
1556
1557 #include <algorithm>
1558 #include <cmath>
1559 #include <math.h>
1560
1561 static float zitarevmonodsp_faustpower2_f(float value) {
1562 return (value * value);
1563 }
1564
1565 #ifndef FAUSTCLASS
1566 #define FAUSTCLASS zitarevmonodsp
1567 #endif
1568
1569 #ifdef __APPLE__
1570 #define exp10f __exp10f
1571 #define exp10 __exp10
1572 #endif
1573
1574 class zitarevmonodsp : public dsp {
1575
1576 private:
1577
1578 int IOTA;
1579 float fVec0[16384];
1580 FAUSTFLOAT fVslider0;
1581 float fRec0[2];
1582 FAUSTFLOAT fVslider1;
1583 float fRec1[2];
1584 int fSampleRate;
1585 float fConst0;
1586 float fConst1;
1587 FAUSTFLOAT fVslider2;
1588 FAUSTFLOAT fVslider3;
1589 FAUSTFLOAT fVslider4;
1590 FAUSTFLOAT fVslider5;
1591 float fConst2;
1592 float fConst3;
1593 FAUSTFLOAT fVslider6;
1594 FAUSTFLOAT fVslider7;
1595 FAUSTFLOAT fVslider8;
1596 float fConst4;
1597 FAUSTFLOAT fVslider9;
1598 float fRec15[2];
1599 float fRec14[2];
1600 float fVec1[32768];
1601 float fConst5;
1602 int iConst6;
1603 float fConst7;
1604 FAUSTFLOAT fVslider10;
1605 float fVec2[2048];
1606 int iConst8;
1607 float fRec12[2];
1608 float fConst9;
1609 float fConst10;
1610 float fRec19[2];
1611 float fRec18[2];
1612 float fVec3[32768];
1613 float fConst11;
1614 int iConst12;
1615 float fVec4[4096];
1616 int iConst13;
1617 float fRec16[2];
1618 float fConst14;
1619 float fConst15;
1620 float fRec23[2];
1621 float fRec22[2];
1622 float fVec5[16384];
1623 float fConst16;
1624 int iConst17;
1625 float fVec6[4096];
1626 int iConst18;
1627 float fRec20[2];
1628 float fConst19;
1629 float fConst20;
1630 float fRec27[2];
1631 float fRec26[2];
1632 float fVec7[32768];
1633 float fConst21;
1634 int iConst22;
1635 float fVec8[4096];
1636 int iConst23;
1637 float fRec24[2];
1638 float fConst24;
1639 float fConst25;
1640 float fRec31[2];
1641 float fRec30[2];
1642 float fVec9[16384];
1643 float fConst26;
1644 int iConst27;
1645 float fVec10[2048];
1646 int iConst28;
1647 float fRec28[2];
1648 float fConst29;
1649 float fConst30;
1650 float fRec35[2];
1651 float fRec34[2];
1652 float fVec11[16384];
1653 float fConst31;
1654 int iConst32;
1655 float fVec12[4096];
1656 int iConst33;
1657 float fRec32[2];
1658 float fConst34;
1659 float fConst35;
1660 float fRec39[2];
1661 float fRec38[2];
1662 float fVec13[16384];
1663 float fConst36;
1664 int iConst37;
1665 float fVec14[4096];
1666 int iConst38;
1667 float fRec36[2];
1668 float fConst39;
1669 float fConst40;
1670 float fRec43[2];
1671 float fRec42[2];
1672 float fVec15[16384];
1673 float fConst41;
1674 int iConst42;
1675 float fVec16[2048];
1676 int iConst43;
1677 float fRec40[2];
1678 float fRec4[3];
1679 float fRec5[3];
1680 float fRec6[3];
1681 float fRec7[3];
1682 float fRec8[3];
1683 float fRec9[3];
1684 float fRec10[3];
1685 float fRec11[3];
1686 float fRec3[3];
1687 float fRec2[3];
1688 float fRec45[3];
1689 float fRec44[3];
1690
1691 public:
1692
1693 void metadata(Meta* m) {
1694 m->declare("basics.lib/name", "Faust Basic Element Library");
1695 m->declare("basics.lib/version", "0.1");
1696 m->declare("delays.lib/name", "Faust Delay Library");
1697 m->declare("delays.lib/version", "0.1");
1698 m->declare("filename", "zitarevmonodsp.dsp");
1699 m->declare("filters.lib/allpass_comb:author", "Julius O. Smith III");
1700 m->declare("filters.lib/allpass_comb:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
1701 m->declare("filters.lib/allpass_comb:license", "MIT-style STK-4.3 license");
1702 m->declare("filters.lib/fir:author", "Julius O. Smith III");
1703 m->declare("filters.lib/fir:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
1704 m->declare("filters.lib/fir:license", "MIT-style STK-4.3 license");
1705 m->declare("filters.lib/iir:author", "Julius O. Smith III");
1706 m->declare("filters.lib/iir:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
1707 m->declare("filters.lib/iir:license", "MIT-style STK-4.3 license");
1708 m->declare("filters.lib/lowpass0_highpass1", "MIT-style STK-4.3 license");
1709 m->declare("filters.lib/lowpass0_highpass1:author", "Julius O. Smith III");
1710 m->declare("filters.lib/lowpass:author", "Julius O. Smith III");
1711 m->declare("filters.lib/lowpass:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
1712 m->declare("filters.lib/lowpass:license", "MIT-style STK-4.3 license");
1713 m->declare("filters.lib/name", "Faust Filters Library");
1714 m->declare("filters.lib/peak_eq_rm:author", "Julius O. Smith III");
1715 m->declare("filters.lib/peak_eq_rm:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
1716 m->declare("filters.lib/peak_eq_rm:license", "MIT-style STK-4.3 license");
1717 m->declare("filters.lib/tf1:author", "Julius O. Smith III");
1718 m->declare("filters.lib/tf1:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
1719 m->declare("filters.lib/tf1:license", "MIT-style STK-4.3 license");
1720 m->declare("filters.lib/tf1s:author", "Julius O. Smith III");
1721 m->declare("filters.lib/tf1s:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
1722 m->declare("filters.lib/tf1s:license", "MIT-style STK-4.3 license");
1723 m->declare("filters.lib/tf2:author", "Julius O. Smith III");
1724 m->declare("filters.lib/tf2:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
1725 m->declare("filters.lib/tf2:license", "MIT-style STK-4.3 license");
1726 m->declare("maths.lib/author", "GRAME");
1727 m->declare("maths.lib/copyright", "GRAME");
1728 m->declare("maths.lib/license", "LGPL with exception");
1729 m->declare("maths.lib/name", "Faust Math Library");
1730 m->declare("maths.lib/version", "2.3");
1731 m->declare("name", "zitarevmonodsp");
1732 m->declare("platform.lib/name", "Generic Platform Library");
1733 m->declare("platform.lib/version", "0.1");
1734 m->declare("reverbs.lib/name", "Faust Reverb Library");
1735 m->declare("reverbs.lib/version", "0.0");
1736 m->declare("routes.lib/name", "Faust Signal Routing Library");
1737 m->declare("routes.lib/version", "0.2");
1738 m->declare("signals.lib/name", "Faust Signal Routing Library");
1739 m->declare("signals.lib/version", "0.0");
1740 }
1741
1742 virtual int getNumInputs() {
1743 return 1;
1744 }
1745 virtual int getNumOutputs() {
1746 return 1;
1747 }
1748 virtual int getInputRate(int channel) {
1749 int rate;
1750 switch ((channel)) {
1751 case 0: {
1752 rate = 1;
1753 break;
1754 }
1755 default: {
1756 rate = -1;
1757 break;
1758 }
1759 }
1760 return rate;
1761 }
1762 virtual int getOutputRate(int channel) {
1763 int rate;
1764 switch ((channel)) {
1765 case 0: {
1766 rate = 1;
1767 break;
1768 }
1769 default: {
1770 rate = -1;
1771 break;
1772 }
1773 }
1774 return rate;
1775 }
1776
1777 static void classInit(int sample_rate) {
1778 }
1779
1780 virtual void instanceConstants(int sample_rate) {
1781 fSampleRate = sample_rate;
1782 fConst0 = std::min<float>(192000.0f, std::max<float>(1.0f, float(fSampleRate)));
1783 fConst1 = (6.28318548f / fConst0);
1784 fConst2 = std::floor(((0.219990999f * fConst0) + 0.5f));
1785 fConst3 = ((0.0f - (6.90775537f * fConst2)) / fConst0);
1786 fConst4 = (3.14159274f / fConst0);
1787 fConst5 = std::floor(((0.0191229992f * fConst0) + 0.5f));
1788 iConst6 = int(std::min<float>(16384.0f, std::max<float>(0.0f, (fConst2 - fConst5))));
1789 fConst7 = (0.00100000005f * fConst0);
1790 iConst8 = int(std::min<float>(1024.0f, std::max<float>(0.0f, (fConst5 + -1.0f))));
1791 fConst9 = std::floor(((0.256891012f * fConst0) + 0.5f));
1792 fConst10 = ((0.0f - (6.90775537f * fConst9)) / fConst0);
1793 fConst11 = std::floor(((0.0273330007f * fConst0) + 0.5f));
1794 iConst12 = int(std::min<float>(16384.0f, std::max<float>(0.0f, (fConst9 - fConst11))));
1795 iConst13 = int(std::min<float>(2048.0f, std::max<float>(0.0f, (fConst11 + -1.0f))));
1796 fConst14 = std::floor(((0.192303002f * fConst0) + 0.5f));
1797 fConst15 = ((0.0f - (6.90775537f * fConst14)) / fConst0);
1798 fConst16 = std::floor(((0.0292910002f * fConst0) + 0.5f));
1799 iConst17 = int(std::min<float>(8192.0f, std::max<float>(0.0f, (fConst14 - fConst16))));
1800 iConst18 = int(std::min<float>(2048.0f, std::max<float>(0.0f, (fConst16 + -1.0f))));
1801 fConst19 = std::floor(((0.210389003f * fConst0) + 0.5f));
1802 fConst20 = ((0.0f - (6.90775537f * fConst19)) / fConst0);
1803 fConst21 = std::floor(((0.0244210009f * fConst0) + 0.5f));
1804 iConst22 = int(std::min<float>(16384.0f, std::max<float>(0.0f, (fConst19 - fConst21))));
1805 iConst23 = int(std::min<float>(2048.0f, std::max<float>(0.0f, (fConst21 + -1.0f))));
1806 fConst24 = std::floor(((0.125f * fConst0) + 0.5f));
1807 fConst25 = ((0.0f - (6.90775537f * fConst24)) / fConst0);
1808 fConst26 = std::floor(((0.0134579996f * fConst0) + 0.5f));
1809 iConst27 = int(std::min<float>(8192.0f, std::max<float>(0.0f, (fConst24 - fConst26))));
1810 iConst28 = int(std::min<float>(1024.0f, std::max<float>(0.0f, (fConst26 + -1.0f))));
1811 fConst29 = std::floor(((0.127837002f * fConst0) + 0.5f));
1812 fConst30 = ((0.0f - (6.90775537f * fConst29)) / fConst0);
1813 fConst31 = std::floor(((0.0316039994f * fConst0) + 0.5f));
1814 iConst32 = int(std::min<float>(8192.0f, std::max<float>(0.0f, (fConst29 - fConst31))));
1815 iConst33 = int(std::min<float>(2048.0f, std::max<float>(0.0f, (fConst31 + -1.0f))));
1816 fConst34 = std::floor(((0.174713001f * fConst0) + 0.5f));
1817 fConst35 = ((0.0f - (6.90775537f * fConst34)) / fConst0);
1818 fConst36 = std::floor(((0.0229039993f * fConst0) + 0.5f));
1819 iConst37 = int(std::min<float>(8192.0f, std::max<float>(0.0f, (fConst34 - fConst36))));
1820 iConst38 = int(std::min<float>(2048.0f, std::max<float>(0.0f, (fConst36 + -1.0f))));
1821 fConst39 = std::floor(((0.153128996f * fConst0) + 0.5f));
1822 fConst40 = ((0.0f - (6.90775537f * fConst39)) / fConst0);
1823 fConst41 = std::floor(((0.0203460008f * fConst0) + 0.5f));
1824 iConst42 = int(std::min<float>(8192.0f, std::max<float>(0.0f, (fConst39 - fConst41))));
1825 iConst43 = int(std::min<float>(1024.0f, std::max<float>(0.0f, (fConst41 + -1.0f))));
1826 }
1827
1828 virtual void instanceResetUserInterface() {
1829 fVslider0 = FAUSTFLOAT(-3.0f);
1830 fVslider1 = FAUSTFLOAT(0.0f);
1831 fVslider2 = FAUSTFLOAT(1500.0f);
1832 fVslider3 = FAUSTFLOAT(0.0f);
1833 fVslider4 = FAUSTFLOAT(315.0f);
1834 fVslider5 = FAUSTFLOAT(0.0f);
1835 fVslider6 = FAUSTFLOAT(2.0f);
1836 fVslider7 = FAUSTFLOAT(6000.0f);
1837 fVslider8 = FAUSTFLOAT(3.0f);
1838 fVslider9 = FAUSTFLOAT(200.0f);
1839 fVslider10 = FAUSTFLOAT(60.0f);
1840 }
1841
1842 virtual void instanceClear() {
1843 IOTA = 0;
1844 for (int l0 = 0; (l0 < 16384); l0 = (l0 + 1)) {
1845 fVec0[l0] = 0.0f;
1846 }
1847 for (int l1 = 0; (l1 < 2); l1 = (l1 + 1)) {
1848 fRec0[l1] = 0.0f;
1849 }
1850 for (int l2 = 0; (l2 < 2); l2 = (l2 + 1)) {
1851 fRec1[l2] = 0.0f;
1852 }
1853 for (int l3 = 0; (l3 < 2); l3 = (l3 + 1)) {
1854 fRec15[l3] = 0.0f;
1855 }
1856 for (int l4 = 0; (l4 < 2); l4 = (l4 + 1)) {
1857 fRec14[l4] = 0.0f;
1858 }
1859 for (int l5 = 0; (l5 < 32768); l5 = (l5 + 1)) {
1860 fVec1[l5] = 0.0f;
1861 }
1862 for (int l6 = 0; (l6 < 2048); l6 = (l6 + 1)) {
1863 fVec2[l6] = 0.0f;
1864 }
1865 for (int l7 = 0; (l7 < 2); l7 = (l7 + 1)) {
1866 fRec12[l7] = 0.0f;
1867 }
1868 for (int l8 = 0; (l8 < 2); l8 = (l8 + 1)) {
1869 fRec19[l8] = 0.0f;
1870 }
1871 for (int l9 = 0; (l9 < 2); l9 = (l9 + 1)) {
1872 fRec18[l9] = 0.0f;
1873 }
1874 for (int l10 = 0; (l10 < 32768); l10 = (l10 + 1)) {
1875 fVec3[l10] = 0.0f;
1876 }
1877 for (int l11 = 0; (l11 < 4096); l11 = (l11 + 1)) {
1878 fVec4[l11] = 0.0f;
1879 }
1880 for (int l12 = 0; (l12 < 2); l12 = (l12 + 1)) {
1881 fRec16[l12] = 0.0f;
1882 }
1883 for (int l13 = 0; (l13 < 2); l13 = (l13 + 1)) {
1884 fRec23[l13] = 0.0f;
1885 }
1886 for (int l14 = 0; (l14 < 2); l14 = (l14 + 1)) {
1887 fRec22[l14] = 0.0f;
1888 }
1889 for (int l15 = 0; (l15 < 16384); l15 = (l15 + 1)) {
1890 fVec5[l15] = 0.0f;
1891 }
1892 for (int l16 = 0; (l16 < 4096); l16 = (l16 + 1)) {
1893 fVec6[l16] = 0.0f;
1894 }
1895 for (int l17 = 0; (l17 < 2); l17 = (l17 + 1)) {
1896 fRec20[l17] = 0.0f;
1897 }
1898 for (int l18 = 0; (l18 < 2); l18 = (l18 + 1)) {
1899 fRec27[l18] = 0.0f;
1900 }
1901 for (int l19 = 0; (l19 < 2); l19 = (l19 + 1)) {
1902 fRec26[l19] = 0.0f;
1903 }
1904 for (int l20 = 0; (l20 < 32768); l20 = (l20 + 1)) {
1905 fVec7[l20] = 0.0f;
1906 }
1907 for (int l21 = 0; (l21 < 4096); l21 = (l21 + 1)) {
1908 fVec8[l21] = 0.0f;
1909 }
1910 for (int l22 = 0; (l22 < 2); l22 = (l22 + 1)) {
1911 fRec24[l22] = 0.0f;
1912 }
1913 for (int l23 = 0; (l23 < 2); l23 = (l23 + 1)) {
1914 fRec31[l23] = 0.0f;
1915 }
1916 for (int l24 = 0; (l24 < 2); l24 = (l24 + 1)) {
1917 fRec30[l24] = 0.0f;
1918 }
1919 for (int l25 = 0; (l25 < 16384); l25 = (l25 + 1)) {
1920 fVec9[l25] = 0.0f;
1921 }
1922 for (int l26 = 0; (l26 < 2048); l26 = (l26 + 1)) {
1923 fVec10[l26] = 0.0f;
1924 }
1925 for (int l27 = 0; (l27 < 2); l27 = (l27 + 1)) {
1926 fRec28[l27] = 0.0f;
1927 }
1928 for (int l28 = 0; (l28 < 2); l28 = (l28 + 1)) {
1929 fRec35[l28] = 0.0f;
1930 }
1931 for (int l29 = 0; (l29 < 2); l29 = (l29 + 1)) {
1932 fRec34[l29] = 0.0f;
1933 }
1934 for (int l30 = 0; (l30 < 16384); l30 = (l30 + 1)) {
1935 fVec11[l30] = 0.0f;
1936 }
1937 for (int l31 = 0; (l31 < 4096); l31 = (l31 + 1)) {
1938 fVec12[l31] = 0.0f;
1939 }
1940 for (int l32 = 0; (l32 < 2); l32 = (l32 + 1)) {
1941 fRec32[l32] = 0.0f;
1942 }
1943 for (int l33 = 0; (l33 < 2); l33 = (l33 + 1)) {
1944 fRec39[l33] = 0.0f;
1945 }
1946 for (int l34 = 0; (l34 < 2); l34 = (l34 + 1)) {
1947 fRec38[l34] = 0.0f;
1948 }
1949 for (int l35 = 0; (l35 < 16384); l35 = (l35 + 1)) {
1950 fVec13[l35] = 0.0f;
1951 }
1952 for (int l36 = 0; (l36 < 4096); l36 = (l36 + 1)) {
1953 fVec14[l36] = 0.0f;
1954 }
1955 for (int l37 = 0; (l37 < 2); l37 = (l37 + 1)) {
1956 fRec36[l37] = 0.0f;
1957 }
1958 for (int l38 = 0; (l38 < 2); l38 = (l38 + 1)) {
1959 fRec43[l38] = 0.0f;
1960 }
1961 for (int l39 = 0; (l39 < 2); l39 = (l39 + 1)) {
1962 fRec42[l39] = 0.0f;
1963 }
1964 for (int l40 = 0; (l40 < 16384); l40 = (l40 + 1)) {
1965 fVec15[l40] = 0.0f;
1966 }
1967 for (int l41 = 0; (l41 < 2048); l41 = (l41 + 1)) {
1968 fVec16[l41] = 0.0f;
1969 }
1970 for (int l42 = 0; (l42 < 2); l42 = (l42 + 1)) {
1971 fRec40[l42] = 0.0f;
1972 }
1973 for (int l43 = 0; (l43 < 3); l43 = (l43 + 1)) {
1974 fRec4[l43] = 0.0f;
1975 }
1976 for (int l44 = 0; (l44 < 3); l44 = (l44 + 1)) {
1977 fRec5[l44] = 0.0f;
1978 }
1979 for (int l45 = 0; (l45 < 3); l45 = (l45 + 1)) {
1980 fRec6[l45] = 0.0f;
1981 }
1982 for (int l46 = 0; (l46 < 3); l46 = (l46 + 1)) {
1983 fRec7[l46] = 0.0f;
1984 }
1985 for (int l47 = 0; (l47 < 3); l47 = (l47 + 1)) {
1986 fRec8[l47] = 0.0f;
1987 }
1988 for (int l48 = 0; (l48 < 3); l48 = (l48 + 1)) {
1989 fRec9[l48] = 0.0f;
1990 }
1991 for (int l49 = 0; (l49 < 3); l49 = (l49 + 1)) {
1992 fRec10[l49] = 0.0f;
1993 }
1994 for (int l50 = 0; (l50 < 3); l50 = (l50 + 1)) {
1995 fRec11[l50] = 0.0f;
1996 }
1997 for (int l51 = 0; (l51 < 3); l51 = (l51 + 1)) {
1998 fRec3[l51] = 0.0f;
1999 }
2000 for (int l52 = 0; (l52 < 3); l52 = (l52 + 1)) {
2001 fRec2[l52] = 0.0f;
2002 }
2003 for (int l53 = 0; (l53 < 3); l53 = (l53 + 1)) {
2004 fRec45[l53] = 0.0f;
2005 }
2006 for (int l54 = 0; (l54 < 3); l54 = (l54 + 1)) {
2007 fRec44[l54] = 0.0f;
2008 }
2009 }
2010
2011 virtual void init(int sample_rate) {
2012 classInit(sample_rate);
2013 instanceInit(sample_rate);
2014 }
2015 virtual void instanceInit(int sample_rate) {
2016 instanceConstants(sample_rate);
2017 instanceResetUserInterface();
2018 instanceClear();
2019 }
2020
2021 virtual zitarevmonodsp* clone() {
2022 return new zitarevmonodsp();
2023 }
2024
2025 virtual int getSampleRate() {
2026 return fSampleRate;
2027 }
2028
2029 virtual void buildUserInterface(UI* ui_interface) {
2030 ui_interface->declare(0, "0", "");
2031 ui_interface->declare(0, "tooltip", "~ ZITA REV1 FEEDBACK DELAY NETWORK (FDN) & SCHROEDER ALLPASS-COMB REVERBERATOR (8x8). See Faust's reverbs.lib for documentation and references");
2032 ui_interface->openHorizontalBox("Zita_Rev1");
2033 ui_interface->declare(0, "1", "");
2034 ui_interface->openHorizontalBox("Input");
2035 ui_interface->declare(&fVslider10, "1", "");
2036 ui_interface->declare(&fVslider10, "style", "knob");
2037 ui_interface->declare(&fVslider10, "tooltip", "Delay in ms before reverberation begins");
2038 ui_interface->declare(&fVslider10, "unit", "ms");
2039 ui_interface->addVerticalSlider("In Delay", &fVslider10, 60.0f, 20.0f, 100.0f, 1.0f);
2040 ui_interface->closeBox();
2041 ui_interface->declare(0, "2", "");
2042 ui_interface->openHorizontalBox("Decay Times in Bands (see tooltips)");
2043 ui_interface->declare(&fVslider9, "1", "");
2044 ui_interface->declare(&fVslider9, "scale", "log");
2045 ui_interface->declare(&fVslider9, "style", "knob");
2046 ui_interface->declare(&fVslider9, "tooltip", "Crossover frequency (Hz) separating low and middle frequencies");
2047 ui_interface->declare(&fVslider9, "unit", "Hz");
2048 ui_interface->addVerticalSlider("LF X", &fVslider9, 200.0f, 50.0f, 1000.0f, 1.0f);
2049 ui_interface->declare(&fVslider8, "2", "");
2050 ui_interface->declare(&fVslider8, "scale", "log");
2051 ui_interface->declare(&fVslider8, "style", "knob");
2052 ui_interface->declare(&fVslider8, "tooltip", "T60 = time (in seconds) to decay 60dB in low-frequency band");
2053 ui_interface->declare(&fVslider8, "unit", "s");
2054 ui_interface->addVerticalSlider("Low RT60", &fVslider8, 3.0f, 1.0f, 8.0f, 0.100000001f);
2055 ui_interface->declare(&fVslider6, "3", "");
2056 ui_interface->declare(&fVslider6, "scale", "log");
2057 ui_interface->declare(&fVslider6, "style", "knob");
2058 ui_interface->declare(&fVslider6, "tooltip", "T60 = time (in seconds) to decay 60dB in middle band");
2059 ui_interface->declare(&fVslider6, "unit", "s");
2060 ui_interface->addVerticalSlider("Mid RT60", &fVslider6, 2.0f, 1.0f, 8.0f, 0.100000001f);
2061 ui_interface->declare(&fVslider7, "4", "");
2062 ui_interface->declare(&fVslider7, "scale", "log");
2063 ui_interface->declare(&fVslider7, "style", "knob");
2064 ui_interface->declare(&fVslider7, "tooltip", "Frequency (Hz) at which the high-frequency T60 is half the middle-band's T60");
2065 ui_interface->declare(&fVslider7, "unit", "Hz");
2066 ui_interface->addVerticalSlider("HF Damping", &fVslider7, 6000.0f, 1500.0f, 23520.0f, 1.0f);
2067 ui_interface->closeBox();
2068 ui_interface->declare(0, "3", "");
2069 ui_interface->openHorizontalBox("RM Peaking Equalizer 1");
2070 ui_interface->declare(&fVslider4, "1", "");
2071 ui_interface->declare(&fVslider4, "scale", "log");
2072 ui_interface->declare(&fVslider4, "style", "knob");
2073 ui_interface->declare(&fVslider4, "tooltip", "Center-frequency of second-order Regalia-Mitra peaking equalizer section 1");
2074 ui_interface->declare(&fVslider4, "unit", "Hz");
2075 ui_interface->addVerticalSlider("Eq1 Freq", &fVslider4, 315.0f, 40.0f, 2500.0f, 1.0f);
2076 ui_interface->declare(&fVslider5, "2", "");
2077 ui_interface->declare(&fVslider5, "style", "knob");
2078 ui_interface->declare(&fVslider5, "tooltip", "Peak level in dB of second-order Regalia-Mitra peaking equalizer section 1");
2079 ui_interface->declare(&fVslider5, "unit", "dB");
2080 ui_interface->addVerticalSlider("Eq1 Level", &fVslider5, 0.0f, -15.0f, 15.0f, 0.100000001f);
2081 ui_interface->closeBox();
2082 ui_interface->declare(0, "4", "");
2083 ui_interface->openHorizontalBox("RM Peaking Equalizer 2");
2084 ui_interface->declare(&fVslider2, "1", "");
2085 ui_interface->declare(&fVslider2, "scale", "log");
2086 ui_interface->declare(&fVslider2, "style", "knob");
2087 ui_interface->declare(&fVslider2, "tooltip", "Center-frequency of second-order Regalia-Mitra peaking equalizer section 2");
2088 ui_interface->declare(&fVslider2, "unit", "Hz");
2089 ui_interface->addVerticalSlider("Eq2 Freq", &fVslider2, 1500.0f, 160.0f, 10000.0f, 1.0f);
2090 ui_interface->declare(&fVslider3, "2", "");
2091 ui_interface->declare(&fVslider3, "style", "knob");
2092 ui_interface->declare(&fVslider3, "tooltip", "Peak level in dB of second-order Regalia-Mitra peaking equalizer section 2");
2093 ui_interface->declare(&fVslider3, "unit", "dB");
2094 ui_interface->addVerticalSlider("Eq2 Level", &fVslider3, 0.0f, -15.0f, 15.0f, 0.100000001f);
2095 ui_interface->closeBox();
2096 ui_interface->declare(0, "5", "");
2097 ui_interface->openHorizontalBox("Output");
2098 ui_interface->declare(&fVslider1, "1", "");
2099 ui_interface->declare(&fVslider1, "style", "knob");
2100 ui_interface->declare(&fVslider1, "tooltip", "Dry/Wet Mix: 0 = dry, 1 = wet");
2101 ui_interface->addVerticalSlider("Wet", &fVslider1, 0.0f, 0.0f, 1.0f, 0.00999999978f);
2102 ui_interface->declare(&fVslider0, "2", "");
2103 ui_interface->declare(&fVslider0, "style", "knob");
2104 ui_interface->declare(&fVslider0, "tooltip", "Output scale factor");
2105 ui_interface->declare(&fVslider0, "unit", "dB");
2106 ui_interface->addVerticalSlider("Level", &fVslider0, -3.0f, -70.0f, 20.0f, 0.100000001f);
2107 ui_interface->closeBox();
2108 ui_interface->closeBox();
2109 }
2110
2111 virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) {
2112 FAUSTFLOAT* input0 = inputs[0];
2113 FAUSTFLOAT* output0 = outputs[0];
2114 float fSlow0 = (0.00100000005f * std::pow(10.0f, (0.0500000007f * float(fVslider0))));
2115 float fSlow1 = (0.00100000005f * float(fVslider1));
2116 float fSlow2 = float(fVslider2);
2117 float fSlow3 = std::pow(10.0f, (0.0500000007f * float(fVslider3)));
2118 float fSlow4 = (fConst1 * (fSlow2 / std::sqrt(std::max<float>(0.0f, fSlow3))));
2119 float fSlow5 = ((1.0f - fSlow4) / (fSlow4 + 1.0f));
2120 float fSlow6 = float(fVslider4);
2121 float fSlow7 = std::pow(10.0f, (0.0500000007f * float(fVslider5)));
2122 float fSlow8 = (fConst1 * (fSlow6 / std::sqrt(std::max<float>(0.0f, fSlow7))));
2123 float fSlow9 = ((1.0f - fSlow8) / (fSlow8 + 1.0f));
2124 float fSlow10 = float(fVslider6);
2125 float fSlow11 = std::exp((fConst3 / fSlow10));
2126 float fSlow12 = zitarevmonodsp_faustpower2_f(fSlow11);
2127 float fSlow13 = std::cos((fConst1 * float(fVslider7)));
2128 float fSlow14 = (1.0f - (fSlow12 * fSlow13));
2129 float fSlow15 = (1.0f - fSlow12);
2130 float fSlow16 = (fSlow14 / fSlow15);
2131 float fSlow17 = std::sqrt(std::max<float>(0.0f, ((zitarevmonodsp_faustpower2_f(fSlow14) / zitarevmonodsp_faustpower2_f(fSlow15)) + -1.0f)));
2132 float fSlow18 = (fSlow16 - fSlow17);
2133 float fSlow19 = (fSlow11 * (fSlow17 + (1.0f - fSlow16)));
2134 float fSlow20 = float(fVslider8);
2135 float fSlow21 = ((std::exp((fConst3 / fSlow20)) / fSlow11) + -1.0f);
2136 float fSlow22 = (1.0f / std::tan((fConst4 * float(fVslider9))));
2137 float fSlow23 = (1.0f / (fSlow22 + 1.0f));
2138 float fSlow24 = (1.0f - fSlow22);
2139 int iSlow25 = int(std::min<float>(8192.0f, std::max<float>(0.0f, (fConst7 * float(fVslider10)))));
2140 float fSlow26 = std::exp((fConst10 / fSlow10));
2141 float fSlow27 = zitarevmonodsp_faustpower2_f(fSlow26);
2142 float fSlow28 = (1.0f - (fSlow27 * fSlow13));
2143 float fSlow29 = (1.0f - fSlow27);
2144 float fSlow30 = (fSlow28 / fSlow29);
2145 float fSlow31 = std::sqrt(std::max<float>(0.0f, ((zitarevmonodsp_faustpower2_f(fSlow28) / zitarevmonodsp_faustpower2_f(fSlow29)) + -1.0f)));
2146 float fSlow32 = (fSlow30 - fSlow31);
2147 float fSlow33 = (fSlow26 * (fSlow31 + (1.0f - fSlow30)));
2148 float fSlow34 = ((std::exp((fConst10 / fSlow20)) / fSlow26) + -1.0f);
2149 float fSlow35 = std::exp((fConst15 / fSlow10));
2150 float fSlow36 = zitarevmonodsp_faustpower2_f(fSlow35);
2151 float fSlow37 = (1.0f - (fSlow36 * fSlow13));
2152 float fSlow38 = (1.0f - fSlow36);
2153 float fSlow39 = (fSlow37 / fSlow38);
2154 float fSlow40 = std::sqrt(std::max<float>(0.0f, ((zitarevmonodsp_faustpower2_f(fSlow37) / zitarevmonodsp_faustpower2_f(fSlow38)) + -1.0f)));
2155 float fSlow41 = (fSlow39 - fSlow40);
2156 float fSlow42 = (fSlow35 * (fSlow40 + (1.0f - fSlow39)));
2157 float fSlow43 = ((std::exp((fConst15 / fSlow20)) / fSlow35) + -1.0f);
2158 float fSlow44 = std::exp((fConst20 / fSlow10));
2159 float fSlow45 = zitarevmonodsp_faustpower2_f(fSlow44);
2160 float fSlow46 = (1.0f - (fSlow45 * fSlow13));
2161 float fSlow47 = (1.0f - fSlow45);
2162 float fSlow48 = (fSlow46 / fSlow47);
2163 float fSlow49 = std::sqrt(std::max<float>(0.0f, ((zitarevmonodsp_faustpower2_f(fSlow46) / zitarevmonodsp_faustpower2_f(fSlow47)) + -1.0f)));
2164 float fSlow50 = (fSlow48 - fSlow49);
2165 float fSlow51 = (fSlow44 * (fSlow49 + (1.0f - fSlow48)));
2166 float fSlow52 = ((std::exp((fConst20 / fSlow20)) / fSlow44) + -1.0f);
2167 float fSlow53 = std::exp((fConst25 / fSlow10));
2168 float fSlow54 = zitarevmonodsp_faustpower2_f(fSlow53);
2169 float fSlow55 = (1.0f - (fSlow54 * fSlow13));
2170 float fSlow56 = (1.0f - fSlow54);
2171 float fSlow57 = (fSlow55 / fSlow56);
2172 float fSlow58 = std::sqrt(std::max<float>(0.0f, ((zitarevmonodsp_faustpower2_f(fSlow55) / zitarevmonodsp_faustpower2_f(fSlow56)) + -1.0f)));
2173 float fSlow59 = (fSlow57 - fSlow58);
2174 float fSlow60 = (fSlow53 * (fSlow58 + (1.0f - fSlow57)));
2175 float fSlow61 = ((std::exp((fConst25 / fSlow20)) / fSlow53) + -1.0f);
2176 float fSlow62 = std::exp((fConst30 / fSlow10));
2177 float fSlow63 = zitarevmonodsp_faustpower2_f(fSlow62);
2178 float fSlow64 = (1.0f - (fSlow63 * fSlow13));
2179 float fSlow65 = (1.0f - fSlow63);
2180 float fSlow66 = (fSlow64 / fSlow65);
2181 float fSlow67 = std::sqrt(std::max<float>(0.0f, ((zitarevmonodsp_faustpower2_f(fSlow64) / zitarevmonodsp_faustpower2_f(fSlow65)) + -1.0f)));
2182 float fSlow68 = (fSlow66 - fSlow67);
2183 float fSlow69 = (fSlow62 * (fSlow67 + (1.0f - fSlow66)));
2184 float fSlow70 = ((std::exp((fConst30 / fSlow20)) / fSlow62) + -1.0f);
2185 float fSlow71 = std::exp((fConst35 / fSlow10));
2186 float fSlow72 = zitarevmonodsp_faustpower2_f(fSlow71);
2187 float fSlow73 = (1.0f - (fSlow72 * fSlow13));
2188 float fSlow74 = (1.0f - fSlow72);
2189 float fSlow75 = (fSlow73 / fSlow74);
2190 float fSlow76 = std::sqrt(std::max<float>(0.0f, ((zitarevmonodsp_faustpower2_f(fSlow73) / zitarevmonodsp_faustpower2_f(fSlow74)) + -1.0f)));
2191 float fSlow77 = (fSlow75 - fSlow76);
2192 float fSlow78 = (fSlow71 * (fSlow76 + (1.0f - fSlow75)));
2193 float fSlow79 = ((std::exp((fConst35 / fSlow20)) / fSlow71) + -1.0f);
2194 float fSlow80 = std::exp((fConst40 / fSlow10));
2195 float fSlow81 = zitarevmonodsp_faustpower2_f(fSlow80);
2196 float fSlow82 = (1.0f - (fSlow81 * fSlow13));
2197 float fSlow83 = (1.0f - fSlow81);
2198 float fSlow84 = (fSlow82 / fSlow83);
2199 float fSlow85 = std::sqrt(std::max<float>(0.0f, ((zitarevmonodsp_faustpower2_f(fSlow82) / zitarevmonodsp_faustpower2_f(fSlow83)) + -1.0f)));
2200 float fSlow86 = (fSlow84 - fSlow85);
2201 float fSlow87 = (fSlow80 * (fSlow85 + (1.0f - fSlow84)));
2202 float fSlow88 = ((std::exp((fConst40 / fSlow20)) / fSlow80) + -1.0f);
2203 float fSlow89 = (0.0f - (std::cos((fConst1 * fSlow6)) * (fSlow9 + 1.0f)));
2204 float fSlow90 = (0.0f - (std::cos((fConst1 * fSlow2)) * (fSlow5 + 1.0f)));
2205 for (int i = 0; (i < count); i = (i + 1)) {
2206 float fTemp0 = float(input0[i]);
2207 fVec0[(IOTA & 16383)] = fTemp0;
2208 fRec0[0] = (fSlow0 + (0.999000013f * fRec0[1]));
2209 fRec1[0] = (fSlow1 + (0.999000013f * fRec1[1]));
2210 fRec15[0] = (0.0f - (fSlow23 * ((fSlow24 * fRec15[1]) - (fRec11[1] + fRec11[2]))));
2211 fRec14[0] = ((fSlow18 * fRec14[1]) + (fSlow19 * (fRec11[1] + (fSlow21 * fRec15[0]))));
2212 fVec1[(IOTA & 32767)] = ((0.353553385f * fRec14[0]) + 9.99999968e-21f);
2213 float fTemp1 = (0.300000012f * fVec0[((IOTA - iSlow25) & 16383)]);
2214 float fTemp2 = (((0.600000024f * fRec12[1]) + fVec1[((IOTA - iConst6) & 32767)]) - fTemp1);
2215 fVec2[(IOTA & 2047)] = fTemp2;
2216 fRec12[0] = fVec2[((IOTA - iConst8) & 2047)];
2217 float fRec13 = (0.0f - (0.600000024f * fTemp2));
2218 fRec19[0] = (0.0f - (fSlow23 * ((fSlow24 * fRec19[1]) - (fRec7[1] + fRec7[2]))));
2219 fRec18[0] = ((fSlow32 * fRec18[1]) + (fSlow33 * (fRec7[1] + (fSlow34 * fRec19[0]))));
2220 fVec3[(IOTA & 32767)] = ((0.353553385f * fRec18[0]) + 9.99999968e-21f);
2221 float fTemp3 = (((0.600000024f * fRec16[1]) + fVec3[((IOTA - iConst12) & 32767)]) - fTemp1);
2222 fVec4[(IOTA & 4095)] = fTemp3;
2223 fRec16[0] = fVec4[((IOTA - iConst13) & 4095)];
2224 float fRec17 = (0.0f - (0.600000024f * fTemp3));
2225 fRec23[0] = (0.0f - (fSlow23 * ((fSlow24 * fRec23[1]) - (fRec9[1] + fRec9[2]))));
2226 fRec22[0] = ((fSlow41 * fRec22[1]) + (fSlow42 * (fRec9[1] + (fSlow43 * fRec23[0]))));
2227 fVec5[(IOTA & 16383)] = ((0.353553385f * fRec22[0]) + 9.99999968e-21f);
2228 float fTemp4 = (fVec5[((IOTA - iConst17) & 16383)] + (fTemp1 + (0.600000024f * fRec20[1])));
2229 fVec6[(IOTA & 4095)] = fTemp4;
2230 fRec20[0] = fVec6[((IOTA - iConst18) & 4095)];
2231 float fRec21 = (0.0f - (0.600000024f * fTemp4));
2232 fRec27[0] = (0.0f - (fSlow23 * ((fSlow24 * fRec27[1]) - (fRec5[1] + fRec5[2]))));
2233 fRec26[0] = ((fSlow50 * fRec26[1]) + (fSlow51 * (fRec5[1] + (fSlow52 * fRec27[0]))));
2234 fVec7[(IOTA & 32767)] = ((0.353553385f * fRec26[0]) + 9.99999968e-21f);
2235 float fTemp5 = (fVec7[((IOTA - iConst22) & 32767)] + (fTemp1 + (0.600000024f * fRec24[1])));
2236 fVec8[(IOTA & 4095)] = fTemp5;
2237 fRec24[0] = fVec8[((IOTA - iConst23) & 4095)];
2238 float fRec25 = (0.0f - (0.600000024f * fTemp5));
2239 fRec31[0] = (0.0f - (fSlow23 * ((fSlow24 * fRec31[1]) - (fRec10[1] + fRec10[2]))));
2240 fRec30[0] = ((fSlow59 * fRec30[1]) + (fSlow60 * (fRec10[1] + (fSlow61 * fRec31[0]))));
2241 fVec9[(IOTA & 16383)] = ((0.353553385f * fRec30[0]) + 9.99999968e-21f);
2242 float fTemp6 = (fVec9[((IOTA - iConst27) & 16383)] - (fTemp1 + (0.600000024f * fRec28[1])));
2243 fVec10[(IOTA & 2047)] = fTemp6;
2244 fRec28[0] = fVec10[((IOTA - iConst28) & 2047)];
2245 float fRec29 = (0.600000024f * fTemp6);
2246 fRec35[0] = (0.0f - (fSlow23 * ((fSlow24 * fRec35[1]) - (fRec6[1] + fRec6[2]))));
2247 fRec34[0] = ((fSlow68 * fRec34[1]) + (fSlow69 * (fRec6[1] + (fSlow70 * fRec35[0]))));
2248 fVec11[(IOTA & 16383)] = ((0.353553385f * fRec34[0]) + 9.99999968e-21f);
2249 float fTemp7 = (fVec11[((IOTA - iConst32) & 16383)] - (fTemp1 + (0.600000024f * fRec32[1])));
2250 fVec12[(IOTA & 4095)] = fTemp7;
2251 fRec32[0] = fVec12[((IOTA - iConst33) & 4095)];
2252 float fRec33 = (0.600000024f * fTemp7);
2253 fRec39[0] = (0.0f - (fSlow23 * ((fSlow24 * fRec39[1]) - (fRec8[1] + fRec8[2]))));
2254 fRec38[0] = ((fSlow77 * fRec38[1]) + (fSlow78 * (fRec8[1] + (fSlow79 * fRec39[0]))));
2255 fVec13[(IOTA & 16383)] = ((0.353553385f * fRec38[0]) + 9.99999968e-21f);
2256 float fTemp8 = ((fTemp1 + fVec13[((IOTA - iConst37) & 16383)]) - (0.600000024f * fRec36[1]));
2257 fVec14[(IOTA & 4095)] = fTemp8;
2258 fRec36[0] = fVec14[((IOTA - iConst38) & 4095)];
2259 float fRec37 = (0.600000024f * fTemp8);
2260 fRec43[0] = (0.0f - (fSlow23 * ((fSlow24 * fRec43[1]) - (fRec4[1] + fRec4[2]))));
2261 fRec42[0] = ((fSlow86 * fRec42[1]) + (fSlow87 * (fRec4[1] + (fSlow88 * fRec43[0]))));
2262 fVec15[(IOTA & 16383)] = ((0.353553385f * fRec42[0]) + 9.99999968e-21f);
2263 float fTemp9 = ((fVec15[((IOTA - iConst42) & 16383)] + fTemp1) - (0.600000024f * fRec40[1]));
2264 fVec16[(IOTA & 2047)] = fTemp9;
2265 fRec40[0] = fVec16[((IOTA - iConst43) & 2047)];
2266 float fRec41 = (0.600000024f * fTemp9);
2267 float fTemp10 = (fRec41 + fRec37);
2268 float fTemp11 = (fRec29 + (fRec33 + fTemp10));
2269 fRec4[0] = (fRec12[1] + (fRec16[1] + (fRec20[1] + (fRec24[1] + (fRec28[1] + (fRec32[1] + (fRec36[1] + (fRec40[1] + (fRec13 + (fRec17 + (fRec21 + (fRec25 + fTemp11))))))))))));
2270 fRec5[0] = ((fRec28[1] + (fRec32[1] + (fRec36[1] + (fRec40[1] + fTemp11)))) - (fRec12[1] + (fRec16[1] + (fRec20[1] + (fRec24[1] + (fRec13 + (fRec17 + (fRec25 + fRec21))))))));
2271 float fTemp12 = (fRec33 + fRec29);
2272 fRec6[0] = ((fRec20[1] + (fRec24[1] + (fRec36[1] + (fRec40[1] + (fRec21 + (fRec25 + fTemp10)))))) - (fRec12[1] + (fRec16[1] + (fRec28[1] + (fRec32[1] + (fRec13 + (fRec17 + fTemp12)))))));
2273 fRec7[0] = ((fRec12[1] + (fRec16[1] + (fRec36[1] + (fRec40[1] + (fRec13 + (fRec17 + fTemp10)))))) - (fRec20[1] + (fRec24[1] + (fRec28[1] + (fRec32[1] + (fRec21 + (fRec25 + fTemp12)))))));
2274 float fTemp13 = (fRec41 + fRec33);
2275 float fTemp14 = (fRec37 + fRec29);
2276 fRec8[0] = ((fRec16[1] + (fRec24[1] + (fRec32[1] + (fRec40[1] + (fRec17 + (fRec25 + fTemp13)))))) - (fRec12[1] + (fRec20[1] + (fRec28[1] + (fRec36[1] + (fRec13 + (fRec21 + fTemp14)))))));
2277 fRec9[0] = ((fRec12[1] + (fRec20[1] + (fRec32[1] + (fRec40[1] + (fRec13 + (fRec21 + fTemp13)))))) - (fRec16[1] + (fRec24[1] + (fRec28[1] + (fRec36[1] + (fRec17 + (fRec25 + fTemp14)))))));
2278 float fTemp15 = (fRec41 + fRec29);
2279 float fTemp16 = (fRec37 + fRec33);
2280 fRec10[0] = ((fRec12[1] + (fRec24[1] + (fRec28[1] + (fRec40[1] + (fRec13 + (fRec25 + fTemp15)))))) - (fRec16[1] + (fRec20[1] + (fRec32[1] + (fRec36[1] + (fRec17 + (fRec21 + fTemp16)))))));
2281 fRec11[0] = ((fRec16[1] + (fRec20[1] + (fRec28[1] + (fRec40[1] + (fRec17 + (fRec21 + fTemp15)))))) - (fRec12[1] + (fRec24[1] + (fRec32[1] + (fRec36[1] + (fRec13 + (fRec25 + fTemp16)))))));
2282 float fTemp17 = (0.370000005f * (fRec5[0] + fRec6[0]));
2283 float fTemp18 = (fSlow89 * fRec3[1]);
2284 fRec3[0] = (fTemp17 - (fTemp18 + (fSlow9 * fRec3[2])));
2285 float fTemp19 = (fSlow9 * fRec3[0]);
2286 float fTemp20 = (0.5f * ((fTemp19 + (fRec3[2] + (fTemp17 + fTemp18))) + (fSlow7 * ((fTemp19 + (fTemp18 + fRec3[2])) - fTemp17))));
2287 float fTemp21 = (fSlow90 * fRec2[1]);
2288 fRec2[0] = (fTemp20 - (fTemp21 + (fSlow5 * fRec2[2])));
2289 float fTemp22 = (fSlow5 * fRec2[0]);
2290 float fTemp23 = (fTemp0 * (1.0f - fRec1[0]));
2291 float fTemp24 = (0.370000005f * (fRec5[0] - fRec6[0]));
2292 float fTemp25 = (fSlow89 * fRec45[1]);
2293 fRec45[0] = (fTemp24 - (fTemp25 + (fSlow9 * fRec45[2])));
2294 float fTemp26 = (fSlow9 * fRec45[0]);
2295 float fTemp27 = (0.5f * ((fTemp26 + (fRec45[2] + (fTemp24 + fTemp25))) + (fSlow7 * ((fTemp26 + (fTemp25 + fRec45[2])) - fTemp24))));
2296 float fTemp28 = (fSlow90 * fRec44[1]);
2297 fRec44[0] = (fTemp27 - (fTemp28 + (fSlow5 * fRec44[2])));
2298 float fTemp29 = (fSlow5 * fRec44[0]);
2299 output0[i] = FAUSTFLOAT((fRec0[0] * (((0.5f * (fRec1[0] * ((fTemp22 + (fRec2[2] + (fTemp20 + fTemp21))) + (fSlow3 * ((fTemp22 + (fTemp21 + fRec2[2])) - fTemp20))))) + fTemp23) + (fTemp23 + (0.5f * (fRec1[0] * ((fTemp29 + (fRec44[2] + (fTemp27 + fTemp28))) + (fSlow3 * ((fTemp29 + (fTemp28 + fRec44[2])) - fTemp27)))))))));
2300 IOTA = (IOTA + 1);
2301 fRec0[1] = fRec0[0];
2302 fRec1[1] = fRec1[0];
2303 fRec15[1] = fRec15[0];
2304 fRec14[1] = fRec14[0];
2305 fRec12[1] = fRec12[0];
2306 fRec19[1] = fRec19[0];
2307 fRec18[1] = fRec18[0];
2308 fRec16[1] = fRec16[0];
2309 fRec23[1] = fRec23[0];
2310 fRec22[1] = fRec22[0];
2311 fRec20[1] = fRec20[0];
2312 fRec27[1] = fRec27[0];
2313 fRec26[1] = fRec26[0];
2314 fRec24[1] = fRec24[0];
2315 fRec31[1] = fRec31[0];
2316 fRec30[1] = fRec30[0];
2317 fRec28[1] = fRec28[0];
2318 fRec35[1] = fRec35[0];
2319 fRec34[1] = fRec34[0];
2320 fRec32[1] = fRec32[0];
2321 fRec39[1] = fRec39[0];
2322 fRec38[1] = fRec38[0];
2323 fRec36[1] = fRec36[0];
2324 fRec43[1] = fRec43[0];
2325 fRec42[1] = fRec42[0];
2326 fRec40[1] = fRec40[0];
2327 fRec4[2] = fRec4[1];
2328 fRec4[1] = fRec4[0];
2329 fRec5[2] = fRec5[1];
2330 fRec5[1] = fRec5[0];
2331 fRec6[2] = fRec6[1];
2332 fRec6[1] = fRec6[0];
2333 fRec7[2] = fRec7[1];
2334 fRec7[1] = fRec7[0];
2335 fRec8[2] = fRec8[1];
2336 fRec8[1] = fRec8[0];
2337 fRec9[2] = fRec9[1];
2338 fRec9[1] = fRec9[0];
2339 fRec10[2] = fRec10[1];
2340 fRec10[1] = fRec10[0];
2341 fRec11[2] = fRec11[1];
2342 fRec11[1] = fRec11[0];
2343 fRec3[2] = fRec3[1];
2344 fRec3[1] = fRec3[0];
2345 fRec2[2] = fRec2[1];
2346 fRec2[1] = fRec2[0];
2347 fRec45[2] = fRec45[1];
2348 fRec45[1] = fRec45[0];
2349 fRec44[2] = fRec44[1];
2350 fRec44[1] = fRec44[0];
2351 }
2352 }
2353
2354 };
2355
2356 #endif