Update from main repo.
* Add a more reliable transient detection mode, and make the mode selectable using OptionDetectorXXX flags -- the new method is the default * Band-limit transient detectors to avoid being distracted by inaudible garbage * Add a key-frame mapping facility for variable stretch ratio management during offline stretches
This commit is contained in:
127
main/main.cpp
127
main/main.cpp
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
An audio time-stretching and pitch-shifting library.
|
||||
Copyright 2007-2009 Chris Cannam.
|
||||
Copyright 2007-2010 Chris Cannam.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
@@ -20,6 +20,9 @@
|
||||
#include <time.h>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "system/sysutils.h"
|
||||
|
||||
@@ -87,12 +90,20 @@ int main(int argc, char **argv)
|
||||
|
||||
bool haveRatio = false;
|
||||
|
||||
std::string mapfile;
|
||||
|
||||
enum {
|
||||
NoTransients,
|
||||
BandLimitedTransients,
|
||||
Transients
|
||||
} transients = Transients;
|
||||
|
||||
enum {
|
||||
CompoundDetector,
|
||||
PercussiveDetector,
|
||||
SoftDetector
|
||||
} detector = CompoundDetector;
|
||||
|
||||
while (1) {
|
||||
int optionIndex = 0;
|
||||
|
||||
@@ -116,13 +127,18 @@ int main(int argc, char **argv)
|
||||
{ "window-long", 0, 0, '3' },
|
||||
{ "window-short", 0, 0, '4' },
|
||||
{ "bl-transients", 0, 0, '8' },
|
||||
{ "detector-perc", 0, 0, '5' },
|
||||
{ "detector-soft", 0, 0, '6' },
|
||||
{ "pitch-hq", 0, 0, '%' },
|
||||
{ "threads", 0, 0, '@' },
|
||||
{ "quiet", 0, 0, 'q' },
|
||||
{ "timemap", 1, 0, 'M' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
c = getopt_long(argc, argv, "t:p:d:RPFc:f:T:D:qhV", longOpts, &optionIndex);
|
||||
c = getopt_long(argc, argv,
|
||||
"t:p:d:RPFc:f:T:D:qhVM:",
|
||||
longOpts, &optionIndex);
|
||||
if (c == -1) break;
|
||||
|
||||
switch (c) {
|
||||
@@ -143,10 +159,13 @@ int main(int argc, char **argv)
|
||||
case '2': lamination = false; crispchanged = true; break;
|
||||
case '3': longwin = true; crispchanged = true; break;
|
||||
case '4': shortwin = true; crispchanged = true; break;
|
||||
case '5': detector = PercussiveDetector; crispchanged = true; break;
|
||||
case '6': detector = SoftDetector; crispchanged = true; break;
|
||||
case '8': transients = BandLimitedTransients; crispchanged = true; break;
|
||||
case '%': hqpitch = true; break;
|
||||
case 'c': crispness = atoi(optarg); break;
|
||||
case 'q': quiet = true; break;
|
||||
case 'M': mapfile = optarg; break;
|
||||
default: help = true; break;
|
||||
}
|
||||
}
|
||||
@@ -160,7 +179,7 @@ int main(int argc, char **argv)
|
||||
cerr << endl;
|
||||
cerr << "Rubber Band" << endl;
|
||||
cerr << "An audio time-stretching and pitch-shifting library and utility program." << endl;
|
||||
cerr << "Copyright 2009 Chris Cannam. Distributed under the GNU General Public License." << endl;
|
||||
cerr << "Copyright 2010 Chris Cannam. Distributed under the GNU General Public License." << endl;
|
||||
cerr << endl;
|
||||
cerr << " Usage: " << argv[0] << " [options] <infile.wav> <outfile.wav>" << endl;
|
||||
cerr << endl;
|
||||
@@ -174,10 +193,17 @@ int main(int argc, char **argv)
|
||||
cerr << " -p<X>, --pitch <X> Raise pitch by X semitones, or" << endl;
|
||||
cerr << " -f<X>, --frequency <X> Change frequency by multiple X" << endl;
|
||||
cerr << endl;
|
||||
cerr << " -M<F>, --timemap <F> Use file F as the source for key frame map" << endl;
|
||||
cerr << endl;
|
||||
cerr << "A map file consists of a series of lines each having two numbers separated" << 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 << "The following options provide a simple way to adjust the sound. See below" << endl;
|
||||
cerr << "for more details." << endl;
|
||||
cerr << endl;
|
||||
cerr << " -c<N>, --crisp <N> Crispness (N = 0,1,2,3,4,5); default 4 (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 << endl;
|
||||
cerr << "The remaining options fine-tune the processing mode and stretch algorithm." << endl;
|
||||
@@ -194,6 +220,8 @@ int main(int argc, char **argv)
|
||||
cerr << " --no-lamination Disable phase lamination" << endl;
|
||||
cerr << " --window-long Use longer processing window (actual size may vary)" << endl;
|
||||
cerr << " --window-short Use shorter processing window" << endl;
|
||||
cerr << " --detector-perc Use percussive transient detector (as in pre-1.5)" << endl;
|
||||
cerr << " --detector-soft Use soft transient detector" << endl;
|
||||
cerr << " --pitch-hq In RT mode, use a slower, higher quality pitch shift" << endl;
|
||||
cerr << endl;
|
||||
cerr << " -d<N>, --debug <N> Select debug level (N = 0,1,2,3); default 0, full 3" << endl;
|
||||
@@ -205,11 +233,12 @@ int main(int argc, char **argv)
|
||||
cerr << endl;
|
||||
cerr << "\"Crispness\" levels:" << endl;
|
||||
cerr << " -c 0 equivalent to --no-transients --no-lamination --window-long" << endl;
|
||||
cerr << " -c 1 equivalent to --no-transients --no-lamination" << endl;
|
||||
cerr << " -c 2 equivalent to --no-transients" << endl;
|
||||
cerr << " -c 3 equivalent to --bl-transients" << endl;
|
||||
cerr << " -c 4 default processing options" << endl;
|
||||
cerr << " -c 5 equivalent to --no-lamination --window-short (may be good for drums)" << endl;
|
||||
cerr << " -c 1 equivalent to --detector-soft --no-lamination --window-long (for piano)" << endl;
|
||||
cerr << " -c 2 equivalent to --no-transients --no-lamination" << endl;
|
||||
cerr << " -c 3 equivalent to --no-transients" << endl;
|
||||
cerr << " -c 4 equivalent to --bl-transients" << endl;
|
||||
cerr << " -c 5 default processing options" << endl;
|
||||
cerr << " -c 6 equivalent to --no-lamination --window-short (may be good for drums)" << endl;
|
||||
cerr << endl;
|
||||
return 2;
|
||||
}
|
||||
@@ -220,28 +249,68 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
switch (crispness) {
|
||||
case -1: crispness = 4; break;
|
||||
case 0: transients = NoTransients; lamination = false; longwin = true; shortwin = false; break;
|
||||
case 1: transients = NoTransients; lamination = false; longwin = false; shortwin = false; break;
|
||||
case 2: transients = NoTransients; lamination = true; longwin = false; shortwin = false; break;
|
||||
case 3: transients = BandLimitedTransients; lamination = true; longwin = false; shortwin = false; break;
|
||||
case 4: transients = Transients; lamination = true; longwin = false; shortwin = false; break;
|
||||
case 5: transients = Transients; lamination = false; longwin = false; shortwin = true; break;
|
||||
case -1: crispness = 5; break;
|
||||
case 0: detector = CompoundDetector; transients = NoTransients; lamination = false; longwin = true; shortwin = false; break;
|
||||
case 1: detector = SoftDetector; transients = Transients; lamination = false; longwin = true; shortwin = false; break;
|
||||
case 2: detector = CompoundDetector; transients = NoTransients; lamination = false; longwin = false; shortwin = false; break;
|
||||
case 3: detector = CompoundDetector; transients = NoTransients; lamination = true; longwin = false; shortwin = false; break;
|
||||
case 4: detector = CompoundDetector; transients = BandLimitedTransients; lamination = true; longwin = false; shortwin = false; break;
|
||||
case 5: detector = CompoundDetector; transients = Transients; lamination = true; longwin = false; shortwin = false; break;
|
||||
case 6: detector = CompoundDetector; transients = Transients; lamination = false; longwin = false; shortwin = true; break;
|
||||
};
|
||||
|
||||
if (!quiet) {
|
||||
cerr << "Using crispness level: " << crispness << " (";
|
||||
switch (crispness) {
|
||||
case 0: cerr << "Mushy"; break;
|
||||
case 1: cerr << "Smooth"; break;
|
||||
case 2: cerr << "Balanced multitimbral mixture"; break;
|
||||
case 3: cerr << "Unpitched percussion with stable notes"; break;
|
||||
case 4: cerr << "Crisp monophonic instrumental"; break;
|
||||
case 5: cerr << "Unpitched solo percussion"; break;
|
||||
case 1: cerr << "Piano"; break;
|
||||
case 2: cerr << "Smooth"; break;
|
||||
case 3: cerr << "Balanced multitimbral mixture"; break;
|
||||
case 4: cerr << "Unpitched percussion with stable notes"; break;
|
||||
case 5: cerr << "Crisp monophonic instrumental"; break;
|
||||
case 6: cerr << "Unpitched solo percussion"; break;
|
||||
}
|
||||
cerr << ")" << endl;
|
||||
}
|
||||
|
||||
std::map<size_t, size_t> mapping;
|
||||
|
||||
if (mapfile != "") {
|
||||
std::ifstream ifile(mapfile.c_str());
|
||||
if (!ifile.is_open()) {
|
||||
cerr << "ERROR: Failed to open time map file \"" << mapfile << "\""
|
||||
<< 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: Time map file \"" << mapfile
|
||||
<< "\" 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;
|
||||
size_t target = atoi(line.substr(i).c_str());
|
||||
mapping[source] = target;
|
||||
cerr << "adding mapping from " << source << " to " << target << endl;
|
||||
++lineno;
|
||||
}
|
||||
ifile.close();
|
||||
|
||||
if (!quiet) {
|
||||
cerr << "Read " << mapping.size() << " line(s) from map file" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
char *fileName = strdup(argv[optind++]);
|
||||
char *fileNameOut = strdup(argv[optind++]);
|
||||
|
||||
@@ -317,6 +386,18 @@ int main(int argc, char **argv)
|
||||
break;
|
||||
}
|
||||
|
||||
switch (detector) {
|
||||
case CompoundDetector:
|
||||
options |= RubberBandStretcher::OptionDetectorCompound;
|
||||
break;
|
||||
case PercussiveDetector:
|
||||
options |= RubberBandStretcher::OptionDetectorPercussive;
|
||||
break;
|
||||
case SoftDetector:
|
||||
options |= RubberBandStretcher::OptionDetectorSoft;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pitchshift != 0.0) {
|
||||
frequencyshift *= pow(2.0, pitchshift / 12);
|
||||
}
|
||||
@@ -389,6 +470,10 @@ int main(int argc, char **argv)
|
||||
|
||||
frame = 0;
|
||||
percent = 0;
|
||||
|
||||
if (!mapping.empty()) {
|
||||
ts.setKeyFrameMap(mapping);
|
||||
}
|
||||
|
||||
size_t countIn = 0, countOut = 0;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user