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