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 
48 class Effects
49 {
50  int mNumIncomingChans;
51  int mNumOutgoingChans;
52  int gVerboseFlag = 0;
53 public:
54  enum LIMITER_MODE {
56  LIMITER_INCOMING, // from network
57  LIMITER_OUTGOING, // to network
59  };
60 private:
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 
92 public:
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 
134  bool getHaveEffect() {
135  return
136  inCompressor || outCompressor ||
137  inZitarev || outZitarev ||
138  inFreeverb || outFreeverb ;
139  }
140 
141  bool getHaveLimiter() {
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
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
ProcessPlugin * getOutFreeverb()
Definition: Effects.h:130
ProcessPlugin * getInLimiter()
Definition: Effects.h:131
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
ProcessPlugin * getOutLimiter()
Definition: Effects.h:132
unsigned int getNumClientsAssumed()
Definition: Effects.h:120
int parseLimiterOptArg(char *cmd, char *optarg)
Definition: Effects.h:488
ProcessPlugin * getOutCompressor()
Definition: Effects.h:126
LIMITER_MODE getLimit()
Definition: Effects.h:122
bool getHaveLimiter()
Definition: Effects.h:141
int parseCompresserArgs(char *args, InOrOut inOrOut)
Definition: Effects.h:300
ProcessPlugin * getOutZitarev()
Definition: Effects.h:128
~Effects()
Definition: Effects.h:102
void setNoLimiters()
Definition: Effects.h:123
ProcessPlugin * getInFreeverb()
Definition: Effects.h:129
int setCompressorPresetIndexFrom1(unsigned long presetIndexFrom1, InOrOut io)
Definition: Effects.h:281
int parseEffectsOptArg(char *cmd, char *optarg)
Definition: Effects.h:395
ProcessPlugin * getInZitarev()
Definition: Effects.h:127
ProcessPlugin * getInCompressor()
Definition: Effects.h:125
void setVerboseFlag(int v)
Definition: Effects.h:145
std::vector< ProcessPlugin * > allocateIncomingEffects(int nIncomingChans)
Definition: Effects.h:159
std::vector< ProcessPlugin * > allocateOutgoingEffects(int nOutgoingChans)
Definition: Effects.h:198
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