50 int mNumIncomingChans;
51 int mNumOutgoingChans;
62 unsigned int mNumClientsAssumed;
63 double limiterWarningAmplitude;
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;
78 Reverb* inZitarevP =
nullptr;
79 Reverb* outZitarevP =
nullptr;
80 Reverb* inFreeverbP =
nullptr;
81 Reverb* outFreeverbP =
nullptr;
83 char lastEffect =
'\0';
84 float zitarevInLevel = 1.0f;
85 float freeverbInLevel = 1.0f;
86 float zitarevOutLevel = 1.0f;
87 float freeverbOutLevel = 1.0f;
98 mNumClientsAssumed(2),
99 limiterWarningAmplitude(0.0)
136 inCompressor || outCompressor ||
137 inZitarev || outZitarev ||
138 inFreeverb || outFreeverb ;
150 return mNumIncomingChans;
154 return mNumOutgoingChans;
160 mNumIncomingChans = nIncomingChans;
161 if (incomingEffectsAllocated) {
162 std::cerr <<
"*** Effects.h: attempt to allocate incoming effects more than once\n";
165 std::vector<ProcessPlugin*> incomingEffects;
167 assert(inCompressorP ==
nullptr);
169 if (
gVerboseFlag) { std::cout <<
"Set up INCOMING COMPRESSOR\n"; }
170 incomingEffects.push_back(inCompressorP);
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);
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);
187 std::cout <<
"Set up INCOMING LIMITER for " << mNumIncomingChans <<
" input channels\n";
189 assert(inLimiterP ==
nullptr);
192 incomingEffects.push_back(inLimiterP);
194 incomingEffectsAllocated =
true;
195 return incomingEffects;
199 mNumOutgoingChans = nOutgoingChans;
200 if (outgoingEffectsAllocated) {
201 std::cerr <<
"*** Effects.h: attempt to allocate outgoing effects more than once\n";
204 std::vector<ProcessPlugin*> outgoingEffects;
206 assert(outCompressorP ==
nullptr);
208 if (
gVerboseFlag) { std::cout <<
"Set up OUTGOING COMPRESSOR\n"; }
209 outgoingEffects.push_back(outCompressorP);
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);
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);
227 std::cout <<
"Set up OUTGOING LIMITER for "
228 << mNumOutgoingChans <<
" output channels and "
229 << mNumClientsAssumed <<
" assumed client(s) ...\n";
231 assert(outLimiterP ==
nullptr);
232 outLimiterP =
new Limiter(mNumOutgoingChans,mNumClientsAssumed);
235 outgoingEffects.push_back(outLimiterP);
238 outgoingEffectsAllocated =
true;
239 return outgoingEffects;
243 std::cout <<
"HELP for `" << command <<
"' (end-of-line comments start with `//')\n";
245 std::cout <<
"Examples:\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";
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";
263 if (helpCase == 0 || helpCase ==
'O') {
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";
271 if (helpCase == 0 || helpCase ==
'a') {
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";
284 std::cerr <<
"*** Effects.h: setCompressorPresetFrom1: Index " << presetIndexFrom1 <<
" out of range\n";
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";
304 if (not isalpha(args[0])) {
305 int presetIndexFrom1 = atoi(args);
312 std::cout <<
"parseCompressorArgs = " << args << std::endl;
314 ulong argLen = strlen(args);
315 char lastParam =
'\0';
320 for (ulong i=0; i<argLen; i++) {
329 case 'c':
case 't':
case 'a':
case 'r':
case 'g':
334 if (ch!=
'-' && isalpha(ch)) {
335 std::cerr <<
"*** Effects.h: parseCompressorArgs: " << ch <<
" not recognized in args = " << args <<
"\n";
338 assert(ch==
'-'||ch==
'.'||isdigit(ch));
339 float paramValue = -1.0e10;
340 for (ulong j=i; j<argLen; j++) {
341 if (args[j] ==
',' || args[j] ==
' ' || j==argLen-1) {
342 char argsj = args[j];
346 paramValue = atof(&args[i]);
352 if (paramValue == -1.0e10) {
353 std::cerr <<
"*** Effects.h: parseCompressorArgs: Could not find parameter for "
354 << lastParam <<
" in args = " << args <<
"\n";
359 newPreset.
ratio = paramValue;
374 std::cerr <<
"*** Effects.h: parseCompressorArgs: lastParam " << lastParam <<
" invalid\n";
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";
399 if (c ==
'-' || c==0) {
402 }
else if (not isalpha(c)) {
404 mReverbLevel = atof(optarg);
405 outCompressor =
true;
406 inZitarev = mReverbLevel > 1.0;
407 inFreeverb = mReverbLevel <= 1.0;
409 zitarevInLevel = mReverbLevel - 1.0;
412 freeverbInLevel = mReverbLevel;
419 std::cout << cmd <<
" argument = " << optarg << std::endl;
421 ulong argLen = strlen(optarg);
423 for (ulong i=0; i<argLen; i++) {
424 if (optarg[i]!=
')' && parenLevel>0) {
continue; }
430 case 'h':
printHelp(cmd,
'f'); returnCode = 1;
break;
431 case 'i': io=IO_IN;
break;
432 case 'o': io=IO_OUT;
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); }
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); }
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); }
446 case '(': parenLevel++;
447 for (ulong j=i+1; j<argLen; j++) {
448 if (optarg[j] ==
')') {
455 float farg = atof(&optarg[i+1]);
457 zitarevInLevel = farg;
458 }
else if (io==IO_OUT) {
459 zitarevOutLevel = farg;
463 float farg = atof(&optarg[i+1]);
465 freeverbInLevel = farg;
466 }
else if (io==IO_OUT) {
467 freeverbOutLevel = farg;
478 case ')': parenLevel--;
491 char ch = tolower(optarg[0]);
492 if (ch ==
'-' || ch == 0) {
493 std::cerr << cmd <<
" argument i, o, or io is REQUIRED\n";
495 }
else if (ch ==
'h') {
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]);
517 haveIncoming =
false;
518 haveOutgoing =
false;
521 std::cerr <<
"*** Effects.h: parseLimiterOptArg: Unrecognized option " << ch <<
"\n";
529 limiterWarningAmplitude = 0.5;
534 std::cout <<
"Set up INCOMING Overflow Limiter\n";
537 std::cout <<
"Set up OUTGOING Overflow Limiter\n";
540 std::cout <<
"Enable DISTORTION WARNINGS in Overflow Limiters\n";
542 if(not haveIncoming and not haveOutgoing) {
543 std::cout <<
"Set up NO Overflow Limiters\n";
557 }
else if (ch ==
'-' || isalpha(ch) || ch == 0) {
558 std::cerr << cmd <<
" argument help or integer > 0 is REQUIRED\n";
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;
Applies compressor_mono from the faustlibraries distribution, compressors.lib.
Definition: Compressor.h:54
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