Detect out-of-range samples on output and restart with lower gain

This commit is contained in:
Chris Cannam
2020-09-15 11:43:57 +01:00
parent 732d0ed980
commit 1992688155

View File

@@ -121,6 +121,8 @@ int main(int argc, char **argv)
SoftDetector
} detector = CompoundDetector;
bool ignoreClipping = false;
while (1) {
int optionIndex = 0;
@@ -155,6 +157,7 @@ int main(int argc, char **argv)
{ "timemap", 1, 0, 'M' },
{ "freqmap", 1, 0, 'Q' },
{ "pitchmap", 1, 0, 'C' },
{ "ignore-clipping", 0, 0, 'i' },
{ 0, 0, 0, 0 }
};
@@ -193,6 +196,7 @@ int main(int argc, char **argv)
case 'M': timeMapFile = optarg; break;
case 'Q': freqMapFile = optarg; freqOrPitchMapSpecified = true; break;
case 'C': pitchMapFile = optarg; freqOrPitchMapSpecified = true; break;
case 'i': ignoreClipping = true; break;
default: help = true; break;
}
}
@@ -283,6 +287,8 @@ int main(int argc, char **argv)
cerr << " --pitch-hq In RT mode, use a slower, higher quality pitch shift" << endl;
cerr << " --centre-focus Preserve focus of centre material in stereo" << endl;
cerr << " (at a cost in width and individual channel quality)" << endl;
cerr << " --ignore-clipping Ignore clipping at output; the default is to restart" << endl;
cerr << " with reduced gain if clipping occurs" << endl;
cerr << endl;
cerr << " -d<N>, --debug <N> Select debug level (N = 0,1,2,3); default 0, full 3" << endl;
cerr << " (N.B. debug level 3 includes audible ticks in output)" << endl;
@@ -554,14 +560,24 @@ int main(int argc, char **argv)
RubberBandStretcher::setDefaultDebugLevel(debug);
size_t countIn = 0, countOut = 0;
float gain = 1.f;
bool successful = false;
while (!successful) { // we may have to repeat with a modified
// gain, if clipping occurs
successful = true;
RubberBandStretcher ts(sfinfo.samplerate, channels, options,
ratio, frequencyshift);
ts.setExpectedInputDuration(sfinfo.frames);
float *fbuf = new float[channels * ibs];
float **ibuf = new float *[channels];
for (size_t i = 0; i < channels; ++i) ibuf[i] = new float[ibs];
for (size_t i = 0; i < channels; ++i) {
ibuf[i] = new float[ibs];
}
int frame = 0;
int percent = 0;
@@ -618,7 +634,9 @@ int main(int argc, char **argv)
std::map<size_t, double>::const_iterator freqMapItr = freqMap.begin();
size_t countIn = 0, countOut = 0;
countIn = 0;
countOut = 0;
bool clipping = false;
while (frame < sfinfo.frames) {
@@ -645,7 +663,9 @@ int main(int argc, char **argv)
}
}
if ((count = sf_readf_float(sndfile, fbuf, thisBlockSize)) < 0) break;
if ((count = sf_readf_float(sndfile, fbuf, thisBlockSize)) < 0) {
break;
}
countIn += count;
@@ -677,19 +697,19 @@ int main(int argc, char **argv)
float *fobf = new float[channels * avail];
for (size_t c = 0; c < channels; ++c) {
for (int i = 0; i < avail; ++i) {
float value = obf[c][i];
float value = gain * obf[c][i];
if (ignoreClipping) { // i.e. just clamp, don't bail out
if (value > 1.f) value = 1.f;
if (value < -1.f) value = -1.f;
} else {
if (value >= 1.f || value < -1.f) {
clipping = true;
gain = (0.999f / fabsf(obf[c][i]));
}
}
fobf[i * channels + c] = value;
}
}
// cout << "fobf mean: ";
// double d = 0;
// for (int i = 0; i < avail; ++i) {
// d += fobf[i];
// }
// d /= avail;
// cout << d << endl;
sf_writef_float(sndfileOut, fobf, avail);
delete[] fobf;
for (size_t i = 0; i < channels; ++i) {
@@ -698,6 +718,17 @@ int main(int argc, char **argv)
delete[] obf;
}
if (clipping) {
if (!quiet) {
cerr << "NOTE: Clipping detected at output sample "
<< countOut << ", restarting with "
<< "reduced gain of " << gain
<< " (supply --ignore-clipping to avoid this)" << endl;
}
successful = false;
break;
}
if (frame == 0 && !realtime && !quiet) {
cerr << "Pass 2: Processing..." << endl;
}
@@ -713,6 +744,12 @@ int main(int argc, char **argv)
frame += thisBlockSize;
}
if (!successful) {
sf_seek(sndfile, 0, SEEK_SET);
sf_seek(sndfileOut, 0, SEEK_SET);
continue;
}
if (!quiet) {
cerr << "\r " << endl;
}
@@ -734,7 +771,7 @@ int main(int argc, char **argv)
float *fobf = new float[channels * avail];
for (size_t c = 0; c < channels; ++c) {
for (int i = 0; i < avail; ++i) {
float value = obf[c][i];
float value = gain * obf[c][i];
if (value > 1.f) value = 1.f;
if (value < -1.f) value = -1.f;
fobf[i * channels + c] = value;
@@ -751,6 +788,7 @@ int main(int argc, char **argv)
usleep(10000);
}
}
}
sf_close(sndfile);
sf_close(sndfileOut);