Add pre-pad for realtime mode (equivalent to the padding RB does internally in offline mode already)
This commit is contained in:
218
main/main.cpp
218
main/main.cpp
@@ -45,9 +45,6 @@
|
||||
|
||||
#include "../src/base/Profiler.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace RubberBand;
|
||||
|
||||
#ifdef _WIN32
|
||||
using RubberBand::gettimeofday;
|
||||
#endif
|
||||
@@ -57,6 +54,11 @@ using RubberBand::usleep;
|
||||
#define strdup _strdup
|
||||
#endif
|
||||
|
||||
using RubberBand::RubberBandStretcher;
|
||||
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
|
||||
double tempo_convert(const char *str)
|
||||
{
|
||||
char *d = strchr((char *)str, ':');
|
||||
@@ -489,9 +491,6 @@ int main(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ibs = 1024;
|
||||
size_t channels = sfinfo.channels;
|
||||
|
||||
RubberBandStretcher::Options options = 0;
|
||||
if (realtime) options |= RubberBandStretcher::OptionProcessRealTime;
|
||||
if (precise) options |= RubberBandStretcher::OptionStretchPrecise;
|
||||
@@ -569,6 +568,17 @@ int main(int argc, char **argv)
|
||||
float gain = 1.f;
|
||||
bool successful = false;
|
||||
|
||||
const size_t channels = sfinfo.channels;
|
||||
const int bs = 1024;
|
||||
|
||||
float **cbuf = new float *[channels];
|
||||
for (size_t c = 0; c < channels; ++c) {
|
||||
cbuf[c] = new float[bs];
|
||||
}
|
||||
float *ibuf = new float[channels * bs];
|
||||
|
||||
int thisBlockSize;
|
||||
|
||||
while (!successful) { // we may have to repeat with a modified
|
||||
// gain, if clipping occurs
|
||||
successful = true;
|
||||
@@ -577,12 +587,6 @@ int main(int argc, char **argv)
|
||||
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];
|
||||
}
|
||||
|
||||
int frame = 0;
|
||||
int percent = 0;
|
||||
|
||||
@@ -597,19 +601,17 @@ int main(int argc, char **argv)
|
||||
while (frame < sfinfo.frames) {
|
||||
|
||||
int count = -1;
|
||||
|
||||
if ((count = sf_readf_float(sndfile, fbuf, ibs)) <= 0) break;
|
||||
if ((count = sf_readf_float(sndfile, ibuf, bs)) <= 0) break;
|
||||
|
||||
for (size_t c = 0; c < channels; ++c) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
float value = fbuf[i * channels + c];
|
||||
ibuf[c][i] = value;
|
||||
cbuf[c][i] = ibuf[i * channels + c];
|
||||
}
|
||||
}
|
||||
|
||||
bool final = (frame + ibs >= sfinfo.frames);
|
||||
bool final = (frame + bs >= sfinfo.frames);
|
||||
|
||||
ts.study(ibuf, count, final);
|
||||
ts.study(cbuf, count, final);
|
||||
|
||||
int p = int((double(frame) * 100.0) / sfinfo.frames);
|
||||
if (p > percent || frame == 0) {
|
||||
@@ -619,7 +621,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
frame += ibs;
|
||||
frame += bs;
|
||||
}
|
||||
|
||||
if (!quiet) {
|
||||
@@ -642,10 +644,35 @@ int main(int argc, char **argv)
|
||||
countOut = 0;
|
||||
bool clipping = false;
|
||||
|
||||
// The stretcher only pads the start in offline mode; to avoid
|
||||
// a fade in at the start, we pad it manually in RT mode
|
||||
int toDrop = 0;
|
||||
if (realtime) {
|
||||
toDrop = int(ts.getLatency());
|
||||
int toPad = int(round(toDrop * frequencyshift));
|
||||
if (debug > 0) {
|
||||
cerr << "padding start with " << toPad
|
||||
<< " samples in RT mode, will drop " << toDrop
|
||||
<< " at output" << endl;
|
||||
}
|
||||
if (toPad > 0) {
|
||||
for (size_t c = 0; c < channels; ++c) {
|
||||
for (int i = 0; i < bs; ++i) {
|
||||
cbuf[c][i] = 0.f;
|
||||
}
|
||||
}
|
||||
while (toPad > 0) {
|
||||
int p = toPad;
|
||||
if (p > bs) p = bs;
|
||||
ts.process(cbuf, p, false);
|
||||
toPad -= p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (frame < sfinfo.frames) {
|
||||
|
||||
int count = -1;
|
||||
int thisBlockSize = ibs;
|
||||
thisBlockSize = bs;
|
||||
|
||||
while (freqMapItr != freqMap.end()) {
|
||||
size_t nextFreqFrame = freqMapItr->first;
|
||||
@@ -667,7 +694,8 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
if ((count = sf_readf_float(sndfile, fbuf, thisBlockSize)) < 0) {
|
||||
int count = -1;
|
||||
if ((count = sf_readf_float(sndfile, ibuf, thisBlockSize)) < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -675,51 +703,84 @@ int main(int argc, char **argv)
|
||||
|
||||
for (size_t c = 0; c < channels; ++c) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
float value = fbuf[i * channels + c];
|
||||
ibuf[c][i] = value;
|
||||
cbuf[c][i] = ibuf[i * channels + c];
|
||||
}
|
||||
}
|
||||
|
||||
bool final = (frame + thisBlockSize >= sfinfo.frames);
|
||||
|
||||
if (debug > 2) {
|
||||
cerr << "count = " << count << ", ibs = " << thisBlockSize << ", frame = " << frame << ", frames = " << sfinfo.frames << ", final = " << final << endl;
|
||||
cerr << "count = " << count << ", bs = " << thisBlockSize << ", frame = " << frame << ", frames = " << sfinfo.frames << ", final = " << final << endl;
|
||||
}
|
||||
|
||||
ts.process(ibuf, count, final);
|
||||
ts.process(cbuf, count, final);
|
||||
|
||||
int avail = ts.available();
|
||||
if (debug > 1) cerr << "available = " << avail << endl;
|
||||
|
||||
if (avail > 0) {
|
||||
float **obf = new float *[channels];
|
||||
for (size_t i = 0; i < channels; ++i) {
|
||||
obf[i] = new float[avail];
|
||||
int avail;
|
||||
while ((avail = ts.available()) > 0) {
|
||||
if (debug > 1) {
|
||||
cerr << "available = " << avail << endl;
|
||||
}
|
||||
ts.retrieve(obf, avail);
|
||||
countOut += avail;
|
||||
float *fobf = new float[channels * avail];
|
||||
|
||||
thisBlockSize = avail;
|
||||
if (thisBlockSize > bs) {
|
||||
thisBlockSize = bs;
|
||||
}
|
||||
|
||||
if (toDrop > 0) {
|
||||
int dropHere = toDrop;
|
||||
if (dropHere > thisBlockSize) {
|
||||
dropHere = thisBlockSize;
|
||||
}
|
||||
if (debug > 1) {
|
||||
cerr << "toDrop = " << toDrop << ", dropping "
|
||||
<< dropHere << " of " << avail << endl;
|
||||
}
|
||||
ts.retrieve(cbuf, dropHere);
|
||||
toDrop -= dropHere;
|
||||
avail -= dropHere;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (debug > 2) {
|
||||
cerr << "retrieving block of " << thisBlockSize << endl;
|
||||
}
|
||||
ts.retrieve(cbuf, thisBlockSize);
|
||||
|
||||
if (realtime && final) {
|
||||
// (in offline mode the stretcher handles this itself)
|
||||
size_t ideal = size_t(countIn * ratio);
|
||||
if (debug > 2) {
|
||||
cerr << "at end, ideal = " << ideal
|
||||
<< ", countOut = " << countOut
|
||||
<< ", thisBlockSize = " << thisBlockSize << endl;
|
||||
}
|
||||
if (countOut + thisBlockSize > ideal) {
|
||||
thisBlockSize = ideal - countOut;
|
||||
if (debug > 1) {
|
||||
cerr << "truncated final block to " << thisBlockSize
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
countOut += thisBlockSize;
|
||||
|
||||
for (size_t c = 0; c < channels; ++c) {
|
||||
for (int i = 0; i < avail; ++i) {
|
||||
float value = gain * obf[c][i];
|
||||
for (int i = 0; i < thisBlockSize; ++i) {
|
||||
float value = gain * cbuf[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]));
|
||||
gain = (0.999f / fabsf(cbuf[c][i]));
|
||||
}
|
||||
}
|
||||
fobf[i * channels + c] = value;
|
||||
ibuf[i * channels + c] = value;
|
||||
}
|
||||
}
|
||||
sf_writef_float(sndfileOut, fobf, avail);
|
||||
delete[] fobf;
|
||||
for (size_t i = 0; i < channels; ++i) {
|
||||
delete[] obf[i];
|
||||
}
|
||||
delete[] obf;
|
||||
sf_writef_float(sndfileOut, ibuf, thisBlockSize);
|
||||
}
|
||||
|
||||
if (clipping) {
|
||||
@@ -753,7 +814,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
frame += thisBlockSize;
|
||||
frame += count;
|
||||
}
|
||||
|
||||
if (!successful) {
|
||||
@@ -765,48 +826,51 @@ int main(int argc, char **argv)
|
||||
if (!quiet) {
|
||||
cerr << "\r " << endl;
|
||||
}
|
||||
|
||||
int avail;
|
||||
|
||||
while ((avail = ts.available()) >= 0) {
|
||||
|
||||
if (debug > 1) {
|
||||
cerr << "(completing) available = " << avail << endl;
|
||||
}
|
||||
|
||||
if (avail > 0) {
|
||||
float **obf = new float *[channels];
|
||||
for (size_t i = 0; i < channels; ++i) {
|
||||
obf[i] = new float[avail];
|
||||
}
|
||||
ts.retrieve(obf, avail);
|
||||
countOut += avail;
|
||||
float *fobf = new float[channels * avail];
|
||||
for (size_t c = 0; c < channels; ++c) {
|
||||
for (int i = 0; i < avail; ++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;
|
||||
}
|
||||
}
|
||||
|
||||
sf_writef_float(sndfileOut, fobf, avail);
|
||||
delete[] fobf;
|
||||
for (size_t i = 0; i < channels; ++i) {
|
||||
delete[] obf[i];
|
||||
}
|
||||
delete[] obf;
|
||||
if (avail == 0) {
|
||||
if (realtime ||
|
||||
(options & RubberBandStretcher::OptionThreadingNever)) {
|
||||
break;
|
||||
} else {
|
||||
usleep(10000);
|
||||
}
|
||||
}
|
||||
|
||||
delete[] fbuf;
|
||||
|
||||
for (size_t i = 0; i < channels; ++i) delete[] ibuf[i];
|
||||
delete[] ibuf;
|
||||
thisBlockSize = avail;
|
||||
if (thisBlockSize > bs) {
|
||||
thisBlockSize = bs;
|
||||
}
|
||||
|
||||
ts.retrieve(cbuf, thisBlockSize);
|
||||
|
||||
countOut += thisBlockSize;
|
||||
|
||||
for (size_t c = 0; c < channels; ++c) {
|
||||
for (int i = 0; i < thisBlockSize; ++i) {
|
||||
float value = gain * cbuf[c][i];
|
||||
if (value > 1.f) value = 1.f;
|
||||
if (value < -1.f) value = -1.f;
|
||||
ibuf[i * channels + c] = value;
|
||||
}
|
||||
}
|
||||
|
||||
sf_writef_float(sndfileOut, ibuf, thisBlockSize);
|
||||
}
|
||||
}
|
||||
|
||||
delete[] ibuf;
|
||||
|
||||
for (size_t c = 0; c < channels; ++c) {
|
||||
delete[] cbuf[c];
|
||||
}
|
||||
delete[] cbuf;
|
||||
|
||||
sf_close(sndfile);
|
||||
sf_close(sndfileOut);
|
||||
|
||||
@@ -834,7 +898,7 @@ int main(int argc, char **argv)
|
||||
cerr << "elapsed time: " << sec << " sec, in frames/sec: " << countIn/sec << ", out frames/sec: " << countOut/sec << endl;
|
||||
}
|
||||
|
||||
Profiler::dump();
|
||||
RubberBand::Profiler::dump();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user