JackTrip
Limiter.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, Juan-Pablo Caceres, Chris Chafe.
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
42#ifndef __LIMITER_H__
43#define __LIMITER_H__
44
45//#define SINE_TEST
46
47#ifdef SINE_TEST
48#include "limitertest.h"
49#endif
50
51#include "ProcessPlugin.h"
52#include "limiterdsp.h"
53#include <vector>
54#include "assert.h"
55
59class Limiter : public ProcessPlugin
60{
61public:
63 Limiter(int numchans, int numclients, bool verboseFlag = false) // xtor
64 : mNumChannels(numchans), mNumClients(numclients)
65 , warningAmp(0.0), warnCount(0), peakMagnitude(0.0), nextWarning(1)
66 {
67 setVerbose(verboseFlag);
68 for ( int i = 0; i < mNumChannels; i++ ) {
69 limiterP.push_back(new limiterdsp);
70 limiterUIP.push_back(new APIUI); // #included in limiterdsp.h
71 limiterP[i]->buildUserInterface(limiterUIP[i]);
72#ifdef SINE_TEST
73 limiterTestP.push_back(new limitertest);
74 limiterTestUIP.push_back(new APIUI); // #included in limitertest.h
75 limiterTestP[i]->buildUserInterface(limiterTestUIP[i]);
76#endif
77 }
78 // std::cout << "Limiter: constructed for "
79 // << mNumChannels << " channels and "
80 // << mNumClients << " assumed clients\n";
81 }
82
84 virtual ~Limiter() {
85 for ( int i = 0; i < mNumChannels; i++ ) {
86 delete limiterP[i];
87 delete limiterUIP[i];
88 }
89 limiterP.clear();
90 limiterUIP.clear();
91 }
92
93 void init(int samplingRate) override {
94 ProcessPlugin::init(samplingRate);
95 if (samplingRate != fSamplingFreq) {
96 std::cerr << "Sampling rate not set by superclass!\n";
97 std::exit(1); }
98 fs = float(fSamplingFreq);
99 for ( int i = 0; i < mNumChannels; i++ ) {
100 limiterP[i]->init(fs); // compression filter parameters depend on sampling rate
101 int ndx = limiterUIP[i]->getParamIndex("NumClientsAssumed");
102 limiterUIP[i]->setParamValue(ndx, mNumClients);
103#ifdef SINE_TEST
104 limiterTestP[i]->init(fs); // oscillator parameters depend on sampling rate
105 ndx = limiterTestUIP[i]->getParamIndex("Amp");
106 limiterTestUIP[i]->setParamValue(ndx, 0.2);
107 ndx = limiterTestUIP[i]->getParamIndex("Freq");
108 float sineFreq = 110.0 * pow(1.5,double(i)) * (mNumClients>1?1.25:1.0); // Maj 7 chord for stereo in & out
109 limiterTestUIP[i]->setParamValue(ndx, sineFreq);
110#endif
111 }
112 inited = true;
113 }
114 int getNumInputs() override { return(mNumChannels); }
115 int getNumOutputs() override { return(mNumChannels); }
116 void compute(int nframes, float** inputs, float** outputs) override;
117
118 void setWarningAmplitude(double wa) { // setting to 0 turns off warnings
119 warningAmp = std::max(0.0,std::min(1.0,wa));
120 }
121
122 private:
123
124 void checkAmplitudes(int nframes, float* buf) {
125 const int maxWarningInterval { 10000 }; // this could become an option
126 assert(warningAmp > 0.0);
127 assert(mNumClients > 0);
128 for (int i=0; i<nframes; i++) {
129 double tmp_sample = double(buf[i]);
130 double limiterAmp = fabs(tmp_sample)/sqrt(double(mNumClients)); // KEEP IN SYNC with gain in ../faust-src/limiterdsp.dsp
131 if (limiterAmp >= warningAmp) {
132 warnCount++;
133 peakMagnitude = std::max(peakMagnitude,limiterAmp);
134 if (warnCount==nextWarning) {
135 double peakMagnitudeDB = 20.0 * std::log10(peakMagnitude);
136 double warningAmpDB = 20.0 * std::log10(warningAmp);
137 if (warnCount==1) {
138 if (warningAmp == 1.0) {
139 std::cerr << "*** Limiter.cpp: Audio HARD-CLIPPED!\n";
140 fprintf(stderr, "\tReduce your audio input level(s) by %0.1f dB to avoid this.\n", peakMagnitudeDB);
141 } else {
142 fprintf(stderr,
143 "*** Limiter.cpp: Amplitude levels must stay below %0.1f dBFS to avoid compression.\n",
144 warningAmpDB);
145 fprintf(stderr, "\tReduce input level(s) by %0.1f dB to achieve this.\n",
146 peakMagnitudeDB-warningAmpDB);
147 }
148 } else {
149 fprintf(stderr, "\tReduce audio input level(s) by %0.1f dB to avoid limiter compression distortion.\n",
150 peakMagnitudeDB-warningAmpDB);
151 }
152 peakMagnitude = 0.0; // reset for next group measurement
153 if (nextWarning < maxWarningInterval) { // don't let it stop reporting for too long
154 nextWarning *= 10;
155 } else {
156 warnCount=0;
157 }
158 } // warnCount==nextWarning
159 } // above warningAmp
160 } // loop over frames
161 } // checkAmplitudes()
162
163private:
164 float fs;
165 int mNumChannels;
166 int mNumClients;
167 std::vector<limiterdsp*> limiterP;
168 std::vector<APIUI*> limiterUIP;
169#ifdef SINE_TEST
170 std::vector<limitertest*> limiterTestP;
171 std::vector<APIUI*> limiterTestUIP;
172#endif
173 double warningAmp;
174 uint32_t warnCount;
175 double peakMagnitude;
176 uint32_t nextWarning;
177};
178
179#endif
Definition: compressordsp.h:1031
Applies limiter_lad_mono from the faustlibraries distribution, compressors.lib.
Definition: Limiter.h:60
void init(int samplingRate) override
Do proper Initialization of members and class instances. By default this initializes the Sampling Fre...
Definition: Limiter.h:93
void setWarningAmplitude(double wa)
Definition: Limiter.h:118
int getNumOutputs() override
Return Number of Output Channels.
Definition: Limiter.h:115
Limiter(int numchans, int numclients, bool verboseFlag=false)
The class constructor sets the number of channels to limit.
Definition: Limiter.h:63
void compute(int nframes, float **inputs, float **outputs) override
Compute process.
Definition: Limiter.cpp:45
virtual ~Limiter()
The class destructor.
Definition: Limiter.h:84
int getNumInputs() override
Return Number of Input Channels.
Definition: Limiter.h:114
Interface for the process plugins to add to the JACK callback process in JackAudioInterface.
Definition: ProcessPlugin.h:53
virtual void setVerbose(bool v)
Definition: ProcessPlugin.h:86
int fSamplingFreq
Faust Data member, Sampling Rate.
Definition: ProcessPlugin.h:92
virtual void init(int samplingRate)
Do proper Initialization of members and class instances. By default this initializes the Sampling Fre...
Definition: ProcessPlugin.h:78
bool inited
Definition: ProcessPlugin.h:93
Definition: limiterdsp.h:1572
quint32 uint32_t
Typedef for unsigned int. This type is guaranteed to be 32-bit.
Definition: jacktrip_types.h:73