Re-apply freqmap, since the merge from default lost it as the commit that removed it was after we branched!

This commit is contained in:
Chris Cannam
2021-03-08 13:14:49 +00:00
parent a88a8520d3
commit a75e6fd678

View File

@@ -105,7 +105,10 @@ int main(int argc, char **argv)
bool haveRatio = false; bool haveRatio = false;
std::string mapfile; std::string timeMapFile;
std::string freqMapFile;
std::string pitchMapFile;
bool freqOrPitchMapSpecified = false;
enum { enum {
NoTransients, NoTransients,
@@ -119,6 +122,8 @@ int main(int argc, char **argv)
SoftDetector SoftDetector
} detector = CompoundDetector; } detector = CompoundDetector;
bool ignoreClipping = false;
while (1) { while (1) {
int optionIndex = 0; int optionIndex = 0;
@@ -151,6 +156,9 @@ int main(int argc, char **argv)
{ "threads", 0, 0, '@' }, { "threads", 0, 0, '@' },
{ "quiet", 0, 0, 'q' }, { "quiet", 0, 0, 'q' },
{ "timemap", 1, 0, 'M' }, { "timemap", 1, 0, 'M' },
{ "freqmap", 1, 0, 'Q' },
{ "pitchmap", 1, 0, 'C' },
{ "ignore-clipping", 0, 0, 'i' },
{ 0, 0, 0, 0 } { 0, 0, 0, 0 }
}; };
@@ -171,7 +179,7 @@ int main(int argc, char **argv)
case 'R': realtime = true; break; case 'R': realtime = true; break;
case 'L': precise = false; break; case 'L': precise = false; break;
case 'P': precise = true; break; case 'P': precise = true; break;
case 'F': formant = true; break; case 'F': formant = true; break;
case '0': threading = 1; break; case '0': threading = 1; break;
case '@': threading = 2; break; case '@': threading = 2; break;
case '1': transients = NoTransients; crispchanged = true; break; case '1': transients = NoTransients; crispchanged = true; break;
@@ -186,7 +194,10 @@ int main(int argc, char **argv)
case '%': hqpitch = true; break; case '%': hqpitch = true; break;
case 'c': crispness = atoi(optarg); break; case 'c': crispness = atoi(optarg); break;
case 'q': quiet = true; break; case 'q': quiet = true; break;
case 'M': mapfile = optarg; break; 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; default: help = true; break;
} }
} }
@@ -196,6 +207,15 @@ int main(int argc, char **argv)
return 0; return 0;
} }
if (freqOrPitchMapSpecified) {
if (freqMapFile != "" && pitchMapFile != "") {
cerr << "ERROR: Please specify either pitch map or frequency map, not both" << endl;
return 1;
}
haveRatio = true;
realtime = true;
}
if (help || !haveRatio || optind + 2 != argc) { if (help || !haveRatio || optind + 2 != argc) {
cerr << endl; cerr << endl;
cerr << "Rubber Band" << endl; cerr << "Rubber Band" << endl;
@@ -214,23 +234,45 @@ int main(int argc, char **argv)
cerr << " -p<X>, --pitch <X> Raise pitch by X semitones, or" << endl; cerr << " -p<X>, --pitch <X> Raise pitch by X semitones, or" << endl;
cerr << " -f<X>, --frequency <X> Change frequency by multiple X" << endl; cerr << " -f<X>, --frequency <X> Change frequency by multiple X" << endl;
cerr << endl; cerr << endl;
cerr << " -M<F>, --timemap <F> Use file F as the source for key frame map" << endl; cerr << "The following options provide ways of making the time and frequency ratios" << endl;
cerr << "change during the audio." << endl;
cerr << endl; cerr << endl;
cerr << "A map file consists of a series of lines each having two numbers separated" << endl; cerr << " -M<F>, --timemap <F> Use file F as the source for time map" << endl;
cerr << "by a single space. These are source and target sample frame numbers for fixed" << endl;
cerr << "time points within the audio data, defining a varying stretch factor through" << endl;
cerr << "the audio. You must specify an overall stretch factor using e.g. -t as well." << endl;
cerr << endl; cerr << endl;
cerr << "The following options provide a simple way to adjust the sound. See below" << endl; cerr << " A time map (or key-frame map) file contains a series of lines, each with two" << endl;
cerr << " sample frame numbers separated by a single space. These are source and" << endl;
cerr << " target frames for fixed time points within the audio data, defining a varying" << endl;
cerr << " stretch factor through the audio. When supplying a time map you must specify" << endl;
cerr << " an overall stretch factor using -t, -T, or -D as well, to determine the" << endl;
cerr << " total output duration." << endl;
cerr << endl;
cerr << " --pitchmap <F> Use file F as the source for pitch map" << endl;
cerr << endl;
cerr << " A pitch map file contains a series of lines, each with two values: the input" << endl;
cerr << " sample frame number and a pitch offset in semitones, separated by a single" << endl;
cerr << " space. These specify a varying pitch factor through the audio. The offsets" << endl;
cerr << " are all relative to an initial offset specified by the pitch or frequency" << endl;
cerr << " option, or relative to no shift if neither was specified. Offsets are" << endl;
cerr << " not cumulative. This option implies realtime mode (-R) and also enables a" << endl;
cerr << " high-consistency pitch shifting mode, appropriate for dynamic pitch changes." << endl;
cerr << " Because of the use of realtime mode, the overall duration will not be exact." << endl;
cerr << endl;
cerr << " --freqmap <F> Use file F as the source for frequency map" << endl;
cerr << endl;
cerr << " As --pitchmap, except that the second column in the file contains frequency" << endl;
cerr << " multipliers rather than pitch offsets (the same as the difference between" << endl;
cerr << " pitch and frequency options above)." << endl;
cerr << endl;
cerr << "The following options provide a simple way to adjust the sound. See below" << endl;
cerr << "for more details." << endl; cerr << "for more details." << endl;
cerr << endl; cerr << endl;
cerr << " -c<N>, --crisp <N> Crispness (N = 0,1,2,3,4,5,6); default 5 (see below)" << endl; cerr << " -c<N>, --crisp <N> Crispness (N = 0,1,2,3,4,5,6); default 5 (see below)" << endl;
cerr << " -F, --formant Enable formant preservation when pitch shifting" << endl; cerr << " -F, --formant Enable formant preservation when pitch shifting" << endl;
cerr << endl; cerr << endl;
cerr << "The remaining options fine-tune the processing mode and stretch algorithm." << endl; cerr << "The remaining options fine-tune the processing mode and stretch algorithm." << endl;
cerr << "These are mostly included for test purposes; the default settings and standard" << endl; cerr << "These are mostly included for test purposes; the default settings and standard" << endl;
cerr << "crispness parameter are intended to provide the best sounding set of options" << endl; cerr << "crispness parameter are intended to provide the best sounding set of options" << endl;
cerr << "for most situations. The default is to use none of these options." << endl; cerr << "for most situations. The default is to use none of these options." << endl;
cerr << endl; cerr << endl;
cerr << " -L, --loose Relax timing in hope of better transient preservation" << endl; cerr << " -L, --loose Relax timing in hope of better transient preservation" << endl;
cerr << " -P, --precise Ignored: The opposite of -L, this is default from 1.6" << endl; cerr << " -P, --precise Ignored: The opposite of -L, this is default from 1.6" << endl;
@@ -248,6 +290,8 @@ int main(int argc, char **argv)
cerr << " --pitch-hq In RT mode, use a slower, higher quality pitch shift" << endl; 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 << " --centre-focus Preserve focus of centre material in stereo" << endl;
cerr << " (at a cost in width and individual channel quality)" << 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 << endl;
cerr << " -d<N>, --debug <N> Select debug level (N = 0,1,2,3); default 0, full 3" << 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; cerr << " (N.B. debug level 3 includes audible ticks in output)" << endl;
@@ -265,7 +309,7 @@ int main(int argc, char **argv)
cerr << " -c 5 default processing options" << endl; cerr << " -c 5 default processing options" << endl;
cerr << " -c 6 equivalent to --no-lamination --window-short (may be good for drums)" << endl; cerr << " -c 6 equivalent to --no-lamination --window-short (may be good for drums)" << endl;
cerr << endl; cerr << endl;
return 2; return 2;
} }
if (ratio <= 0.0) { if (ratio <= 0.0) {
@@ -278,6 +322,12 @@ int main(int argc, char **argv)
cerr << " provided -- crispness will override these other options" << endl; cerr << " provided -- crispness will override these other options" << endl;
} }
if (hqpitch && freqOrPitchMapSpecified) {
cerr << "WARNING: High-quality pitch mode selected, but frequency or pitch map file is" << endl;
cerr << " provided -- pitch mode will be overridden by high-consistency mode" << endl;
hqpitch = false;
}
switch (crispness) { switch (crispness) {
case -1: crispness = 5; break; case -1: crispness = 5; break;
case 0: detector = CompoundDetector; transients = NoTransients; lamination = false; longwin = true; shortwin = false; break; case 0: detector = CompoundDetector; transients = NoTransients; lamination = false; longwin = true; shortwin = false; break;
@@ -303,34 +353,35 @@ int main(int argc, char **argv)
cerr << ")" << endl; cerr << ")" << endl;
} }
std::map<size_t, size_t> mapping; std::map<size_t, size_t> timeMap;
if (timeMapFile != "") {
if (mapfile != "") { std::ifstream ifile(timeMapFile.c_str());
std::ifstream ifile(mapfile.c_str());
if (!ifile.is_open()) { if (!ifile.is_open()) {
cerr << "ERROR: Failed to open time map file \"" << mapfile << "\"" cerr << "ERROR: Failed to open time map file \""
<< endl; << timeMapFile << "\"" << endl;
return 1; return 1;
} }
std::string line; std::string line;
int lineno = 0; int lineno = 0;
while (!ifile.eof()) { while (!ifile.eof()) {
std::getline(ifile, line); std::getline(ifile, line);
while (line.length() > 0 && line[0] == ' ') line = line.substr(1); while (line.length() > 0 && line[0] == ' ') {
line = line.substr(1);
}
if (line == "") { if (line == "") {
++lineno; ++lineno;
continue; continue;
} }
std::string::size_type i = line.find_first_of(" "); std::string::size_type i = line.find_first_of(" ");
if (i == std::string::npos) { if (i == std::string::npos) {
cerr << "ERROR: Time map file \"" << mapfile cerr << "ERROR: Time map file \"" << timeMapFile
<< "\" is malformed at line " << lineno << endl; << "\" is malformed at line " << lineno << endl;
return 1; return 1;
} }
size_t source = atoi(line.substr(0, i).c_str()); size_t source = atoi(line.substr(0, i).c_str());
while (i < line.length() && line[i] == ' ') ++i; while (i < line.length() && line[i] == ' ') ++i;
size_t target = atoi(line.substr(i).c_str()); size_t target = atoi(line.substr(i).c_str());
mapping[source] = target; timeMap[source] = target;
if (debug > 0) { if (debug > 0) {
cerr << "adding mapping from " << source << " to " << target << endl; cerr << "adding mapping from " << source << " to " << target << endl;
} }
@@ -339,7 +390,57 @@ int main(int argc, char **argv)
ifile.close(); ifile.close();
if (!quiet) { if (!quiet) {
cerr << "Read " << mapping.size() << " line(s) from map file" << endl; cerr << "Read " << timeMap.size() << " line(s) from time map file" << endl;
}
}
std::map<size_t, double> freqMap;
if (freqOrPitchMapSpecified) {
std::string file = freqMapFile;
bool convertFromPitch = false;
if (pitchMapFile != "") {
file = pitchMapFile;
convertFromPitch = true;
}
std::ifstream ifile(file.c_str());
if (!ifile.is_open()) {
cerr << "ERROR: Failed to open map file \"" << file << "\"" << endl;
return 1;
}
std::string line;
int lineno = 0;
while (!ifile.eof()) {
std::getline(ifile, line);
while (line.length() > 0 && line[0] == ' ') {
line = line.substr(1);
}
if (line == "") {
++lineno;
continue;
}
std::string::size_type i = line.find_first_of(" ");
if (i == std::string::npos) {
cerr << "ERROR: Map file \"" << file
<< "\" is malformed at line " << lineno << endl;
return 1;
}
size_t source = atoi(line.substr(0, i).c_str());
while (i < line.length() && line[i] == ' ') ++i;
double freq = atof(line.substr(i).c_str());
if (convertFromPitch) {
freq = pow(2.0, freq / 12.0);
}
freqMap[source] = freq;
if (debug > 0) {
cerr << "adding mapping for source frame " << source << " of frequency multiplier " << freq << endl;
}
++lineno;
}
ifile.close();
if (!quiet) {
cerr << "Read " << freqMap.size() << " line(s) from frequency map file" << endl;
} }
} }
@@ -355,9 +456,9 @@ int main(int argc, char **argv)
sndfile = sf_open(fileName, SFM_READ, &sfinfo); sndfile = sf_open(fileName, SFM_READ, &sfinfo);
if (!sndfile) { if (!sndfile) {
cerr << "ERROR: Failed to open input file \"" << fileName << "\": " cerr << "ERROR: Failed to open input file \"" << fileName << "\": "
<< sf_strerror(sndfile) << endl; << sf_strerror(sndfile) << endl;
return 1; return 1;
} }
if (sfinfo.samplerate == 0) { if (sfinfo.samplerate == 0) {
@@ -383,9 +484,9 @@ int main(int argc, char **argv)
sndfileOut = sf_open(fileNameOut, SFM_WRITE, &sfinfoOut) ; sndfileOut = sf_open(fileNameOut, SFM_WRITE, &sfinfoOut) ;
if (!sndfileOut) { if (!sndfileOut) {
cerr << "ERROR: Failed to open output file \"" << fileNameOut << "\" for writing: " cerr << "ERROR: Failed to open output file \"" << fileNameOut << "\" for writing: "
<< sf_strerror(sndfileOut) << endl; << sf_strerror(sndfileOut) << endl;
return 1; return 1;
} }
int ibs = 1024; int ibs = 1024;
@@ -402,6 +503,10 @@ int main(int argc, char **argv)
if (hqpitch) options |= RubberBandStretcher::OptionPitchHighQuality; if (hqpitch) options |= RubberBandStretcher::OptionPitchHighQuality;
if (together) options |= RubberBandStretcher::OptionChannelsTogether; if (together) options |= RubberBandStretcher::OptionChannelsTogether;
if (freqOrPitchMapSpecified) {
options |= RubberBandStretcher::OptionPitchHighConsistency;
}
switch (threading) { switch (threading) {
case 0: case 0:
options |= RubberBandStretcher::OptionThreadingAuto; options |= RubberBandStretcher::OptionThreadingAuto;
@@ -439,46 +544,134 @@ int main(int argc, char **argv)
} }
if (pitchshift != 0.0) { if (pitchshift != 0.0) {
frequencyshift *= pow(2.0, pitchshift / 12); frequencyshift *= pow(2.0, pitchshift / 12.0);
} }
cerr << "Using time ratio " << ratio; cerr << "Using time ratio " << ratio;
cerr << " and frequency ratio " << frequencyshift << endl;
if (!freqOrPitchMapSpecified) {
cerr << " and frequency ratio " << frequencyshift << endl;
} else {
cerr << " and initial frequency ratio " << frequencyshift << endl;
}
#ifdef _WIN32 #ifdef _WIN32
RubberBand:: RubberBand::
#endif #endif
timeval tv; timeval tv;
(void)gettimeofday(&tv, 0); (void)gettimeofday(&tv, 0);
RubberBandStretcher::setDefaultDebugLevel(debug); RubberBandStretcher::setDefaultDebugLevel(debug);
RubberBandStretcher ts(sfinfo.samplerate, channels, options, size_t countIn = 0, countOut = 0;
ratio, frequencyshift);
ts.setExpectedInputDuration(sfinfo.frames); float gain = 1.f;
bool successful = false;
float *fbuf = new float[channels * ibs]; while (!successful) { // we may have to repeat with a modified
float **ibuf = new float *[channels]; // gain, if clipping occurs
for (size_t i = 0; i < channels; ++i) ibuf[i] = new float[ibs]; successful = true;
int frame = 0; RubberBandStretcher ts(sfinfo.samplerate, channels, options,
int percent = 0; ratio, frequencyshift);
ts.setExpectedInputDuration(sfinfo.frames);
sf_seek(sndfile, 0, SEEK_SET); float *fbuf = new float[channels * ibs];
float **ibuf = new float *[channels];
if (!realtime) { for (size_t i = 0; i < channels; ++i) {
ibuf[i] = new float[ibs];
if (!quiet) {
cerr << "Pass 1: Studying..." << endl;
} }
int frame = 0;
int percent = 0;
sf_seek(sndfile, 0, SEEK_SET);
if (!realtime) {
if (!quiet) {
cerr << "Pass 1: Studying..." << endl;
}
while (frame < sfinfo.frames) {
int count = -1;
if ((count = sf_readf_float(sndfile, fbuf, ibs)) <= 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;
}
}
bool final = (frame + ibs >= sfinfo.frames);
ts.study(ibuf, count, final);
int p = int((double(frame) * 100.0) / sfinfo.frames);
if (p > percent || frame == 0) {
percent = p;
if (!quiet) {
cerr << "\r" << percent << "% ";
}
}
frame += ibs;
}
if (!quiet) {
cerr << "\rCalculating profile..." << endl;
}
sf_seek(sndfile, 0, SEEK_SET);
}
frame = 0;
percent = 0;
if (!timeMap.empty()) {
ts.setKeyFrameMap(timeMap);
}
std::map<size_t, double>::const_iterator freqMapItr = freqMap.begin();
countIn = 0;
countOut = 0;
bool clipping = false;
while (frame < sfinfo.frames) { while (frame < sfinfo.frames) {
int count = -1; int count = -1;
int thisBlockSize = ibs;
if ((count = sf_readf_float(sndfile, fbuf, ibs)) <= 0) break; while (freqMapItr != freqMap.end()) {
size_t nextFreqFrame = freqMapItr->first + ts.getLatency();
if (nextFreqFrame <= countIn) {
double s = frequencyshift * freqMapItr->second;
if (debug > 0) {
cerr << "at frame " << countIn
<< " (requested at " << freqMapItr->first
<< " plus latency " << ts.getLatency()
<< ") updating frequency ratio to " << s << endl;
}
ts.setPitchScale(s);
++freqMapItr;
} else {
if (nextFreqFrame < countIn + thisBlockSize) {
thisBlockSize = nextFreqFrame - countIn;
}
break;
}
}
if ((count = sf_readf_float(sndfile, fbuf, thisBlockSize)) < 0) {
break;
}
countIn += count;
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]; float value = fbuf[i * channels + c];
@@ -486,9 +679,70 @@ int main(int argc, char **argv)
} }
} }
bool final = (frame + ibs >= sfinfo.frames); bool final = (frame + thisBlockSize >= sfinfo.frames);
ts.study(ibuf, count, final); if (debug > 2) {
cerr << "count = " << count << ", ibs = " << thisBlockSize << ", frame = " << frame << ", frames = " << sfinfo.frames << ", final = " << final << endl;
}
ts.process(ibuf, 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];
}
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 (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;
}
}
sf_writef_float(sndfileOut, fobf, avail);
delete[] fobf;
for (size_t i = 0; i < channels; ++i) {
delete[] obf[i];
}
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;
}
const float mingain = 0.75f;
if (gain < mingain) {
cerr << "WARNING: Clipped values were implausibly high: "
<< "something wrong with input or process - "
<< "not reducing gain below " << mingain << endl;
gain = mingain;
ignoreClipping = true;
}
successful = false;
break;
}
if (frame == 0 && !realtime && !quiet) {
cerr << "Pass 2: Processing..." << endl;
}
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) {
@@ -498,136 +752,55 @@ int main(int argc, char **argv)
} }
} }
frame += ibs; frame += thisBlockSize;
} }
if (!successful) {
sf_seek(sndfile, 0, SEEK_SET);
sf_seek(sndfileOut, 0, SEEK_SET);
continue;
}
if (!quiet) { if (!quiet) {
cerr << "\rCalculating profile..." << endl; cerr << "\r " << endl;
} }
int avail;
sf_seek(sndfile, 0, SEEK_SET); while ((avail = ts.available()) >= 0) {
}
frame = 0; if (debug > 1) {
percent = 0; cerr << "(completing) available = " << avail << endl;
}
if (!mapping.empty()) {
ts.setKeyFrameMap(mapping); 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;
} else {
usleep(10000);
}
}
} }
size_t countIn = 0, countOut = 0;
while (frame < sfinfo.frames) {
int count = -1;
if ((count = sf_readf_float(sndfile, fbuf, ibs)) < 0) break;
countIn += count;
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;
}
}
bool final = (frame + ibs >= sfinfo.frames);
if (debug > 2) {
cerr << "count = " << count << ", ibs = " << ibs << ", frame = " << frame << ", frames = " << sfinfo.frames << ", final = " << final << endl;
}
ts.process(ibuf, 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];
}
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 = obf[c][i];
if (value > 1.f) value = 1.f;
if (value < -1.f) value = -1.f;
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) {
delete[] obf[i];
}
delete[] obf;
}
if (frame == 0 && !realtime && !quiet) {
cerr << "Pass 2: Processing..." << endl;
}
int p = int((double(frame) * 100.0) / sfinfo.frames);
if (p > percent || frame == 0) {
percent = p;
if (!quiet) {
cerr << "\r" << percent << "% ";
}
}
frame += ibs;
}
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 = 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);
}
}
sf_close(sndfile); sf_close(sndfile);
sf_close(sndfileOut); sf_close(sndfileOut);
@@ -638,7 +811,7 @@ int main(int argc, char **argv)
#ifdef _WIN32 #ifdef _WIN32
RubberBand:: RubberBand::
#endif #endif
timeval etv; timeval etv;
(void)gettimeofday(&etv, 0); (void)gettimeofday(&etv, 0);
etv.tv_sec -= tv.tv_sec; etv.tv_sec -= tv.tv_sec;
@@ -649,10 +822,7 @@ int main(int argc, char **argv)
etv.tv_usec -= tv.tv_usec; etv.tv_usec -= tv.tv_usec;
double sec = double(etv.tv_sec) + (double(etv.tv_usec) / 1000000.0); double sec = double(etv.tv_sec) + (double(etv.tv_usec) / 1000000.0);
cerr << "elapsed time: " << sec cerr << "elapsed time: " << sec << " sec, in frames/sec: " << countIn/sec << ", out frames/sec: " << countOut/sec << endl;
<< " sec, in frames/sec: " << int64_t(round(countIn/sec))
<< ", out frames/sec: " << int64_t(round(countOut/sec))
<< endl;
} }
RubberBand::Profiler::dump(); RubberBand::Profiler::dump();