JackTrip
Effects.h
Go to the documentation of this file.
1//*****************************************************************
2/*
3 JackTrip: A System for High-Quality Audio Network Performance
4 over the Internet
5
6 Copyright (c) 2020 Julius Smith.
7 SoundWIRE group at CCRMA, Stanford University.
8
9 Permission is hereby granted, free of charge, to any person
10 obtaining a copy of this software and associated documentation
11 files (the "Software"), to deal in the Software without
12 restriction, including without limitation the rights to use,
13 copy, modify, merge, publish, distribute, sublicense, and/or sell
14 copies of the Software, and to permit persons to whom the
15 Software is furnished to do so, subject to the following
16 conditions:
17
18 The above copyright notice and this permission notice shall be
19 included in all copies or substantial portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 OTHER DEALINGS IN THE SOFTWARE.
29*/
30//*****************************************************************
31
38#pragma once
39
40#include "ProcessPlugin.h"
41#include "Limiter.h"
42#include "Compressor.h"
43#include "CompressorPresets.h"
44#include "Reverb.h"
45#include <assert.h>
46#include <vector>
47
49{
50 int mNumIncomingChans;
51 int mNumOutgoingChans;
52 int gVerboseFlag = 0;
53public:
56 LIMITER_INCOMING, // from network
57 LIMITER_OUTGOING, // to network
59 };
60private:
61 LIMITER_MODE mLimit;
62 unsigned int mNumClientsAssumed;
63 double limiterWarningAmplitude;
64
65 enum InOrOut { IO_NEITHER, IO_IN, IO_OUT } io;
66 bool inCompressor = false;
67 bool outCompressor = false;
68 bool inZitarev = false;
69 bool outZitarev = false;
70 bool inFreeverb = false;
71 bool outFreeverb = false;
72 bool incomingEffectsAllocated = false;
73 bool outgoingEffectsAllocated = false;
74 Compressor* inCompressorP = nullptr;
75 Compressor* outCompressorP = nullptr;
76 CompressorPreset inCompressorPreset = CompressorPresets::voice; // ./CompressorPresets.h
77 CompressorPreset outCompressorPreset = CompressorPresets::voice;
78 Reverb* inZitarevP = nullptr;
79 Reverb* outZitarevP = nullptr;
80 Reverb* inFreeverbP = nullptr;
81 Reverb* outFreeverbP = nullptr;
82 int parenLevel = 0;
83 char lastEffect = '\0';
84 float zitarevInLevel = 1.0f; // "Level" = wetness from 0 to 1
85 float freeverbInLevel = 1.0f;
86 float zitarevOutLevel = 1.0f;
87 float freeverbOutLevel = 1.0f;
88 float mReverbLevel; // for backward compatibility: 0-1 Freeverb, 1-2 Zitarev
89 Limiter* inLimiterP = nullptr;
90 Limiter* outLimiterP = nullptr;
91
92public:
93
94 Effects(bool outGoingLimiterOn=true) :
95 mNumIncomingChans(2),
96 mNumOutgoingChans(2),
97 mLimit(outGoingLimiterOn ? LIMITER_OUTGOING : LIMITER_NONE),
98 mNumClientsAssumed(2),
99 limiterWarningAmplitude(0.0)
100 {}
101
103 /*
104 Plugin ownership presently passes to JackTrip,
105 and deletion occurs in AudioInterface.cpp. See
106 delete mProcessPluginsFromNetwork[i];
107 delete mProcessPluginsToNetwork[i];
108 there. If/when we ever do it here:
109 if (inCompressor) { delete inCompressorP; }
110 if (outCompressor) { delete outCompressorP; }
111 if (inZitarev) { delete inZitarevP; }
112 if (outZitarev) { delete outZitarevP; }
113 if (inFreeverb) { delete inFreeverbP; }
114 if (outFreeverb) { delete outFreeverbP; }
115 but if everyone can compile C++11,
116 let's switch to using std::unique_ptr.
117 */
118 }
119
120 unsigned int getNumClientsAssumed() { return mNumClientsAssumed; }
121
122 LIMITER_MODE getLimit() { return mLimit; }
123 void setNoLimiters() { mLimit = LIMITER_NONE; }
124
125 ProcessPlugin* getInCompressor() { return inCompressorP; }
126 ProcessPlugin* getOutCompressor() { return outCompressorP; }
127 ProcessPlugin* getInZitarev() { return inZitarevP; }
128 ProcessPlugin* getOutZitarev() { return outZitarevP; }
129 ProcessPlugin* getInFreeverb() { return inFreeverbP; }
130 ProcessPlugin* getOutFreeverb() { return outFreeverbP; }
131 ProcessPlugin* getInLimiter() { return inLimiterP; }
132 ProcessPlugin* getOutLimiter() { return outLimiterP; }
133
135 return
136 inCompressor || outCompressor ||
137 inZitarev || outZitarev ||
138 inFreeverb || outFreeverb ;
139 }
140
142 return mLimit != LIMITER_NONE;
143 }
144
145 void setVerboseFlag(int v) {
146 gVerboseFlag = v;
147 }
148
150 return mNumIncomingChans;
151 }
152
154 return mNumOutgoingChans;
155 }
156
157 // call these next two after it is decided what effects we will be using for the duration:
158
159 std::vector<ProcessPlugin*> allocateIncomingEffects(int nIncomingChans) {
160 mNumIncomingChans = nIncomingChans;
161 if (incomingEffectsAllocated) {
162 std::cerr << "*** Effects.h: attempt to allocate incoming effects more than once\n";
163 std::exit(1);
164 }
165 std::vector<ProcessPlugin*> incomingEffects;
166 if (inCompressor) {
167 assert(inCompressorP == nullptr);
168 inCompressorP = new Compressor(mNumIncomingChans, gVerboseFlag, inCompressorPreset);
169 if (gVerboseFlag) { std::cout << "Set up INCOMING COMPRESSOR\n"; }
170 incomingEffects.push_back(inCompressorP);
171 }
172 if (inZitarev) {
173 assert(inZitarevP == nullptr);
174 inZitarevP = new Reverb(mNumIncomingChans,mNumIncomingChans, 1.0 + zitarevInLevel);
175 if (gVerboseFlag) { std::cout << "Set up INCOMING REVERB (Zitarev)\n"; }
176 incomingEffects.push_back(inZitarevP);
177 }
178 if (inFreeverb) {
179 assert(inFreeverbP == nullptr);
180 inFreeverbP = new Reverb(mNumIncomingChans, mNumIncomingChans, freeverbInLevel);
181 if (gVerboseFlag) { std::cout << "Set up INCOMING REVERB (Freeverb)\n"; }
182 incomingEffects.push_back(inFreeverbP);
183 }
184 // LIMITER MUST GO LAST:
185 if ( mLimit == LIMITER_INCOMING || mLimit == LIMITER_BOTH) {
186 if (gVerboseFlag) {
187 std::cout << "Set up INCOMING LIMITER for " << mNumIncomingChans << " input channels\n";
188 }
189 assert(inLimiterP == nullptr);
190 inLimiterP = new Limiter(mNumIncomingChans, 1, gVerboseFlag); // mNumClientsAssumed not needed this direction
191 // Never needed in normal practice for incoming limiter: inLimiterP->setWarningAmplitude(limiterWarningAmplitude);
192 incomingEffects.push_back(inLimiterP);
193 }
194 incomingEffectsAllocated = true;
195 return incomingEffects;
196 }
197
198 std::vector<ProcessPlugin*> allocateOutgoingEffects(int nOutgoingChans) {
199 mNumOutgoingChans = nOutgoingChans;
200 if (outgoingEffectsAllocated) {
201 std::cerr << "*** Effects.h: attempt to allocate outgoing effects more than once\n";
202 std::exit(1);
203 }
204 std::vector<ProcessPlugin*> outgoingEffects;
205 if (outCompressor) {
206 assert(outCompressorP == nullptr);
207 outCompressorP = new Compressor(mNumOutgoingChans, gVerboseFlag, outCompressorPreset);
208 if (gVerboseFlag) { std::cout << "Set up OUTGOING COMPRESSOR\n"; }
209 outgoingEffects.push_back(outCompressorP);
210 }
211 if (outZitarev) {
212 assert(outZitarevP == nullptr);
213 outZitarevP = new Reverb(mNumOutgoingChans, mNumOutgoingChans, 1.0 + zitarevOutLevel);
214 if (gVerboseFlag) { std::cout << "Set up OUTGOING REVERB (Zitarev)\n"; }
215 outgoingEffects.push_back(outZitarevP);
216 }
217 if (outFreeverb) {
218 assert(outFreeverbP == nullptr);
219 outFreeverbP = new Reverb(mNumOutgoingChans, mNumOutgoingChans, freeverbOutLevel);
220 if (gVerboseFlag) { std::cout << "Set up OUTGOING REVERB (Freeverb)\n"; }
221 outgoingEffects.push_back(outFreeverbP);
222 }
223 // LIMITER MUST GO LAST:
224 if ( mLimit != LIMITER_NONE) {
225 if ( mLimit == LIMITER_OUTGOING || mLimit == LIMITER_BOTH) {
226 if (gVerboseFlag) {
227 std::cout << "Set up OUTGOING LIMITER for "
228 << mNumOutgoingChans << " output channels and "
229 << mNumClientsAssumed << " assumed client(s) ...\n";
230 }
231 assert(outLimiterP == nullptr);
232 outLimiterP = new Limiter(mNumOutgoingChans,mNumClientsAssumed);
233 outLimiterP->setWarningAmplitude(limiterWarningAmplitude);
234 // do not have mSampleRate yet, so cannot call limiter->init(mSampleRate) here
235 outgoingEffects.push_back(outLimiterP);
236 }
237 }
238 outgoingEffectsAllocated = true;
239 return outgoingEffects;
240 }
241
242 void printHelp(char* command, char helpCase) {
243 std::cout << "HELP for `" << command << "' (end-of-line comments start with `//')\n";
244 std::cout << "\n";
245 std::cout << "Examples:\n";
246 std::cout << "\n";
247 if (helpCase == 0 || helpCase == 'f') { //
248 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";
249 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";
250 std::cout << "\n";
251 std::cout << command << " \"o:c i:f(0.3)\" // outgoing-compressor and incoming-freeverb example above using more general string argument\n";
252 std::cout << command << " \"o:c i:z(0.3)\" // outgoing-compressor and incoming-zitarev example above using more general string argument\n";
253 std::cout << command << " \"o:c(1)\" // outgoing compressor, using preset 1 (designed for voice - see below for details)\n";
254 std::cout << command << " \"o:c(2)\" // outgoing compressor, using preset 2 (for horns)\n";
255 std::cout << command << " \"o:c(3)\" // outgoing compressor, using preset 3 (for snare)\n";
256 std::cout << command << " \"o:c(c:compressionRatio t:thresholdDB a:attackTimeMS r:releaseTimeMS g:makeUpGainDB)\" // general compression parameter specification (all floats)\n";
257 std::cout << command << " \"o:c(c:2 t:-24 a:15 r:40 g:2)\" // outgoing compressor, preset 1 details\n";
258 std::cout << command << " \"o:c(c:3 t:-10 a:100 r:250 g:2)\" // outgoing compressor, preset 2 details\n";
259 std::cout << command << " \"o:c(c:5 t:-4 a:5 r:150 g:3)\" // outgoing compressor, preset 3 details\n";
260 std::cout << " For these and more suggested compression settings, see http://www.anythingpeaceful.org/sonar/settings/comp.html\n";
261 std::cout << "\n";
262 }
263 if (helpCase == 0 || helpCase == 'O') { // limiter (-O option most likely)
264 std::cout << command << " i // add limiter to INCOMING audio from network (only helpful for floats, i.e., -b32 used by server)\n";
265 std::cout << command << " o // add limiter to OUTGOING audio to network (prevents your sound from harshly clipping going out)\n";
266 std::cout << command << " ow // also warn and advise on levels when outgoing limiter compresses audio near clipping\n";
267 std::cout << command << " io // add limiter to both INCOMING and OUTGOING audio\n";
268 std::cout << command << " iow // limiters both ways and compression warnings on outgoing direction only\n";
269 std::cout << "\n";
270 }
271 if (helpCase == 0 || helpCase == 'a') { // assumedNumClients (-a option)
272 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";
273 std::cout << command << " 2 // assume 2 clients possibly playing at the same time\n";
274 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";
275 std::cout << "\n";
276 }
277 }
278
279 // ----------- Compressor stuff --------------
280
281 int setCompressorPresetIndexFrom1(unsigned long presetIndexFrom1, InOrOut io) {
282 int returnCode = 0;
283 if (presetIndexFrom1 <= 0 || presetIndexFrom1 > CompressorPresets::numPresets) {
284 std::cerr << "*** Effects.h: setCompressorPresetFrom1: Index " << presetIndexFrom1 << " out of range\n";
285 returnCode = 1;
286 } else {
287 CompressorPreset stdPreset = CompressorPresets::standardPresets[presetIndexFrom1-1];
288 if (io == IO_IN) {
289 inCompressorPreset = stdPreset;
290 } else if (io == IO_OUT) {
291 outCompressorPreset = stdPreset;
292 } else if (io != IO_NEITHER) {
293 std::cerr << "*** Effects.h: setCompressorPresetFrom1: Invalid InOrOut value " << io << "\n";
294 returnCode = 1;
295 }
296 }
297 return returnCode;
298 }
299
300 int parseCompresserArgs(char* args, InOrOut inOrOut) {
301 // args can be integerPresetNumberFrom1 or (all optional, any order):
302 // c:compressionRatio, a:attackTimeMS, r:releaseTimeMS, g:makeUpGain
303 int returnCode = 0;
304 if (not isalpha(args[0])) {
305 int presetIndexFrom1 = atoi(args);
306 setCompressorPresetIndexFrom1(presetIndexFrom1,inOrOut);
307 } else {
308 // args can be presetIndexFrom1, handled above, or (all optional, any order):
309 // c(c:compressionRatio, t:thresholdDB, a:attackTimeMS, r:releaseTimeMS, g:makeUpGainDB)
310 // See ./CompressorPresets.h for example settings.
311 if (gVerboseFlag) {
312 std::cout << "parseCompressorArgs = " << args << std::endl;
313 }
314 ulong argLen = strlen(args);
315 char lastParam = '\0';
316
317 CompressorPreset newPreset(CompressorPresets::voice); // Anything unset gets voice value (most gentle)
318
319 int nSkip = 0;
320 for (ulong i=0; i<argLen; i++) {
321 if (nSkip > 0) {
322 nSkip--;
323 continue;
324 }
325 char ch = args[i];
326 switch(ch) {
327 case ' ': break;
328 case '\t': break;
329 case 'c': case 't': case 'a': case 'r': case 'g':
330 lastParam = ch;
331 break;
332 case ':': break;
333 default: // must be a floating-point number at this point:
334 if (ch!='-' && isalpha(ch)) {
335 std::cerr << "*** Effects.h: parseCompressorArgs: " << ch << " not recognized in args = " << args << "\n";
336 returnCode = 2;
337 } else { // must have a digit or '-' or '.'
338 assert(ch=='-'||ch=='.'||isdigit(ch));
339 float paramValue = -1.0e10;
340 for (ulong j=i; j<argLen; j++) { // scan ahead for end of number
341 if (args[j] == ',' || args[j] == ' ' || j==argLen-1) { // comma or space required between parameters
342 char argsj = args[j];
343 if (j<argLen-1) { // there's more
344 args[j] = '\0';
345 }
346 paramValue = atof(&args[i]);
347 args[j] = argsj;
348 nSkip = j-i;
349 break;
350 }
351 }
352 if (paramValue == -1.0e10) {
353 std::cerr << "*** Effects.h: parseCompressorArgs: Could not find parameter for "
354 << lastParam << " in args = " << args << "\n";
355 returnCode = 2;
356 } else {
357 switch (lastParam) {
358 case 'c':
359 newPreset.ratio = paramValue;
360 break;
361 case 't':
362 newPreset.thresholdDB = paramValue;
363 break;
364 case 'a':
365 newPreset.attackMS = paramValue;
366 break;
367 case 'r':
368 newPreset.releaseMS = paramValue;
369 break;
370 case 'g':
371 newPreset.makeUpGainDB = paramValue;
372 break;
373 default: // cannot happen:
374 std::cerr << "*** Effects.h: parseCompressorArgs: lastParam " << lastParam << " invalid\n";
375 returnCode = 3; // "reality failure"
376 } // switch(lastParam)
377 } // have valid parameter from atof
378 } // have valid non-alpha char for parameter
379 } // switch(ch)
380 } // for (ulong i=0; i<argLen; i++) {
381 if (inOrOut == IO_IN) {
382 inCompressorPreset = newPreset;
383 } else if (inOrOut == IO_OUT) {
384 outCompressorPreset = newPreset;
385 } else if (inOrOut != IO_NEITHER) {
386 std::cerr << "*** Effects.h: parseCompressorArgs: invalid InOrOut value " << inOrOut << "\n";
387 returnCode = 2;
388 }
389 } // long-form compressor args
390 return returnCode;
391 } // int parseCompresserArgs(char* args, InOrOut inOrOut)
392
393 // ============== General argument processing for all effects =================
394
395 int parseEffectsOptArg(char* cmd, char* optarg) {
396 int returnCode = 0; // 0 means go, 1 means exit without error, higher => error exit
397
398 char c = optarg[0];
399 if (c == '-' || c==0) {
400 // happens when no -f argument specified
401 returnCode = 2;
402 } else if (not isalpha(c)) { // backward compatibility why not?, e.g., "-f 0.5"
403 // -f reverbLevelFloat
404 mReverbLevel = atof(optarg);
405 outCompressor = true;
406 inZitarev = mReverbLevel > 1.0;
407 inFreeverb = mReverbLevel <= 1.0;
408 if (inZitarev) {
409 zitarevInLevel = mReverbLevel - 1.0; // wetness from 0 to 1
410 }
411 if (inFreeverb) {
412 freeverbInLevel = mReverbLevel; // wetness from 0 to 1
413 }
414 } else { // long-form argument:
415 // -f "i:[c][f|z][(reverbLevel)]], o:[c][f|z][(rl)]"
416 // c can be c(integerPresetNumberFrom1) or (all optional, any order):
417 // c(c:compressionRatio, a:attackTimeMS, r:releaseTimeMS, g:makeUpGain)
418 if (gVerboseFlag) {
419 std::cout << cmd << " argument = " << optarg << std::endl;
420 }
421 ulong argLen = strlen(optarg);
422
423 for (ulong i=0; i<argLen; i++) {
424 if (optarg[i]!=')' && parenLevel>0) { continue; }
425 switch(optarg[i]) {
426 case ' ': break;
427 case ',': break;
428 case ';': break;
429 case '\t': break;
430 case 'h': printHelp(cmd,'f'); returnCode = 1; break;
431 case 'i': io=IO_IN; break;
432 case 'o': io=IO_OUT; break;
433 case ':': break;
434 case 'c': if (io==IO_IN) { inCompressor = true; } else if (io==IO_OUT) { outCompressor = true; }
435 else { std::cerr << "-f arg `" << optarg << "' malformed\n"; exit(1); }
436 lastEffect = 'c';
437 break;
438 case 'f': if (io==IO_IN) { inFreeverb = true; } else if (io==IO_OUT) { outFreeverb = true; }
439 else { std::cerr << "-f arg `" << optarg << "' malformed\n"; exit(1); }
440 lastEffect = 'f';
441 break;
442 case 'z': if (io==IO_IN) { inZitarev = true; } else if (io==IO_OUT) { outZitarev = true; }
443 else { std::cerr << "-f arg `" << optarg << "' malformed\n"; exit(1); }
444 lastEffect = 'z';
445 break;
446 case '(': parenLevel++;
447 for (ulong j=i+1; j<argLen; j++) {
448 if (optarg[j] == ')') {
449 optarg[j] = '\0';
450 switch(lastEffect) {
451 case 'c': {
452 returnCode += parseCompresserArgs(&optarg[i+1],io);
453 break; }
454 case 'z': {
455 float farg = atof(&optarg[i+1]);
456 if (io==IO_IN) {
457 zitarevInLevel = farg;
458 } else if (io==IO_OUT) {
459 zitarevOutLevel = farg;
460 } // else ignore the argument
461 break; }
462 case 'f': {
463 float farg = atof(&optarg[i+1]);
464 if (io==IO_IN) {
465 freeverbInLevel = farg;
466 } else if (io==IO_OUT) {
467 freeverbOutLevel = farg;
468 } // else ignore the argument
469 break; }
470 default: { // ignore
471 break; }
472 }
473 optarg[j] = ')';
474 break;
475 }
476 }
477 break;
478 case ')': parenLevel--;
479 break;
480 default:
481 break; // ignore
482 } // switch(optarg[i])
483 }
484 }
485 return returnCode;
486 }
487
488 int parseLimiterOptArg(char* cmd, char* optarg) {
489 int returnCode = 0;
490 lastEffect = 'O'; // OverflowLimiter
491 char ch = tolower(optarg[0]);
492 if (ch == '-' || ch == 0) {
493 std::cerr << cmd << " argument i, o, or io is REQUIRED\n";
494 returnCode = 2;
495 } else if (ch == 'h') {
496 printHelp(cmd,'O');
497 returnCode = 1;
498 } else {
499 bool haveIncoming = false;
500 bool haveOutgoing = false;
501 bool haveWarnings = false;
502 for (int i=0; i<strlen(optarg); i++) {
503 ch = tolower(optarg[i]);
504 switch(ch) {
505 case ' ': break;
506 case '\t': break;
507 case 'i':
508 haveIncoming = true;
509 break;
510 case 'o':
511 haveOutgoing = true;
512 break;
513 case 'w':
514 haveWarnings = true;
515 break;
516 case 'n':
517 haveIncoming = false;
518 haveOutgoing = false;
519 break;
520 default:
521 std::cerr << "*** Effects.h: parseLimiterOptArg: Unrecognized option " << ch << "\n";
522 returnCode = 2;
523 } // switch(ch)
524 } // process optarg char ch
525 mLimit = (haveIncoming && haveOutgoing ? LIMITER_BOTH
526 : (haveIncoming ? LIMITER_INCOMING
527 : (haveOutgoing ? LIMITER_OUTGOING : LIMITER_NONE)));
528 if (haveWarnings) {
529 limiterWarningAmplitude = 0.5; // KEEP IN SYNC WITH LIMITER THRESHOLD/CEILING 'softClipLevel' in ../faust-src/limiterdsp.dsp
530 // the warning amplitude and limiter compression threshold can of course be brought as a parameters, e.g. w(0.5)
531 }
532 if (gVerboseFlag) {
533 if(haveIncoming) {
534 std::cout << "Set up INCOMING Overflow Limiter\n";
535 }
536 if(haveOutgoing) {
537 std::cout << "Set up OUTGOING Overflow Limiter\n";
538 }
539 if(haveWarnings) {
540 std::cout << "Enable DISTORTION WARNINGS in Overflow Limiters\n";
541 }
542 if(not haveIncoming and not haveOutgoing) {
543 std::cout << "Set up NO Overflow Limiters\n";
544 }
545 } // gVerboseFlag
546 } // optarg cases
547 return returnCode;
548 } // parseLimiterOptArg()
549
550 int parseAssumedNumClientsOptArg(char* cmd, char* optarg) {
551 int returnCode = 0;
552 lastEffect = 'a'; // assumedNumClients
553 char ch = optarg[0];
554 if (ch == 'h') {
555 printHelp(cmd,'a');
556 returnCode = 1;
557 } else if (ch == '-' || isalpha(ch) || ch == 0) {
558 std::cerr << cmd << " argument help or integer > 0 is REQUIRED\n";
559 returnCode = 2;
560 } else {
561 mNumClientsAssumed = atoi(optarg);
562 if(mNumClientsAssumed < 1) {
563 std::cerr << "-p ERROR: Must have at least one assumed sound source: "
564 << atoi(optarg) << " is not supported." << std::endl;
565 returnCode = 2;
566 }
567 }
568 return returnCode;
569 }
570
571};
Applies compressor_mono from the faustlibraries distribution, compressors.lib.
Definition: Compressor.h:54
Definition: Effects.h:49
ProcessPlugin * getInFreeverb()
Definition: Effects.h:129
int getNumIncomingChans()
Definition: Effects.h:149
void printHelp(char *command, char helpCase)
Definition: Effects.h:242
LIMITER_MODE
Definition: Effects.h:54
@ LIMITER_NONE
Definition: Effects.h:55
@ LIMITER_INCOMING
Definition: Effects.h:56
@ LIMITER_BOTH
Definition: Effects.h:58
@ LIMITER_OUTGOING
Definition: Effects.h:57
bool getHaveEffect()
Definition: Effects.h:134
int parseAssumedNumClientsOptArg(char *cmd, char *optarg)
Definition: Effects.h:550
Effects(bool outGoingLimiterOn=true)
Definition: Effects.h:94
int getOutgoingNumChans()
Definition: Effects.h:153
std::vector< ProcessPlugin * > allocateOutgoingEffects(int nOutgoingChans)
Definition: Effects.h:198
ProcessPlugin * getOutCompressor()
Definition: Effects.h:126
unsigned int getNumClientsAssumed()
Definition: Effects.h:120
int parseLimiterOptArg(char *cmd, char *optarg)
Definition: Effects.h:488
ProcessPlugin * getOutZitarev()
Definition: Effects.h:128
LIMITER_MODE getLimit()
Definition: Effects.h:122
bool getHaveLimiter()
Definition: Effects.h:141
int parseCompresserArgs(char *args, InOrOut inOrOut)
Definition: Effects.h:300
ProcessPlugin * getInCompressor()
Definition: Effects.h:125
ProcessPlugin * getInZitarev()
Definition: Effects.h:127
ProcessPlugin * getOutLimiter()
Definition: Effects.h:132
ProcessPlugin * getOutFreeverb()
Definition: Effects.h:130
~Effects()
Definition: Effects.h:102
void setNoLimiters()
Definition: Effects.h:123
int setCompressorPresetIndexFrom1(unsigned long presetIndexFrom1, InOrOut io)
Definition: Effects.h:281
int parseEffectsOptArg(char *cmd, char *optarg)
Definition: Effects.h:395
ProcessPlugin * getInLimiter()
Definition: Effects.h:131
std::vector< ProcessPlugin * > allocateIncomingEffects(int nIncomingChans)
Definition: Effects.h:159
void setVerboseFlag(int v)
Definition: Effects.h:145
Applies limiter_lad_mono from the faustlibraries distribution, compressors.lib.
Definition: Limiter.h:60
void setWarningAmplitude(double wa)
Definition: Limiter.h:118
Interface for the process plugins to add to the JACK callback process in JackAudioInterface.
Definition: ProcessPlugin.h:53
Applies freeverb or zitarev from the faustlibraries distribution: reverbs.lib.
Definition: Reverb.h:57
int gVerboseFlag
Verbose mode flag declaration.
Definition: Settings.cpp:61
const std::array< CompressorPreset, numPresets > standardPresets
Definition: CompressorPresets.h:28
const CompressorPreset voice
Definition: CompressorPresets.h:24
const uint numPresets
Definition: CompressorPresets.h:27
Definition: CompressorPresets.h:5
float attackMS
Definition: CompressorPresets.h:8
float ratio
Definition: CompressorPresets.h:6
float releaseMS
Definition: CompressorPresets.h:9
float thresholdDB
Definition: CompressorPresets.h:7
float makeUpGainDB
Definition: CompressorPresets.h:10