First cut at freq/pitch map
This commit is contained in:
@@ -201,6 +201,15 @@ int main(int argc, char **argv)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (freqMapFile != "" || pitchMapFile != "") {
|
||||||
|
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;
|
||||||
@@ -228,22 +237,22 @@ int main(int argc, char **argv)
|
|||||||
cerr << " sample frame numbers separated by a single space. These are source and" << 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 << " target frames for fixed time points within the audio data, defining a varying" << endl;
|
||||||
cerr << " stretch factor through the audio." << endl;
|
cerr << " stretch factor through the audio." << endl;
|
||||||
cerr << " You must specify an overall stretch factor using e.g. -t as well." << endl;
|
cerr << " You must specify an overall stretch factor using -t, -T, or -D as well." << endl;
|
||||||
cerr << endl;
|
cerr << endl;
|
||||||
cerr << " --pitchmap <F> Use file F as the source for pitch map" << endl;
|
cerr << " --pitchmap <F> Use file F as the source for pitch map" << endl;
|
||||||
cerr << endl;
|
cerr << endl;
|
||||||
cerr << " A pitch map file contains a series of lines, each with two values: a" << endl;
|
cerr << " A pitch map file contains a series of lines, each with two values: a" << endl;
|
||||||
cerr << " sample frame number and a pitch offset in semitones, separated by a single" << 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 << " space. These specify a varying pitch factor through the audio. The offsets" << endl;
|
||||||
cerr << " are all relative to the initial offset of zero, not to the previous offset." << endl;
|
cerr << " are all relative to an initial offset specified by the pitch or frequency" << endl;
|
||||||
cerr << " This option implies realtime mode (-R)." << endl;
|
cerr << " option, or relative to no shift if neither was specified. Offsets are" << endl;
|
||||||
|
cerr << " not cumulative. This option implies realtime mode (-R)." << endl;
|
||||||
cerr << endl;
|
cerr << endl;
|
||||||
cerr << " --freqmap <F> Use file F as the source for frequency map" << endl;
|
cerr << " --freqmap <F> Use file F as the source for frequency map" << endl;
|
||||||
cerr << endl;
|
cerr << endl;
|
||||||
cerr << " As --pitchmap, except that the second column in the file contains frequency" << 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 << " multipliers rather than pitch offsets (the same as the difference between" << endl;
|
||||||
cerr << " pitch and frequency options above)." << endl;
|
cerr << " pitch and frequency options above). This option implies realtime mode (-R)." << endl;
|
||||||
cerr << " This option implies realtime mode (-R)." << endl;
|
|
||||||
cerr << endl;
|
cerr << endl;
|
||||||
cerr << "The following options provide a simple way to adjust the sound. See below" << 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;
|
||||||
@@ -369,11 +378,16 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::map<size_t, double> freqMap;
|
std::map<size_t, double> freqMap;
|
||||||
if (freqMapFile != "") {
|
if (freqMapFile != "" || pitchMapFile != "") {
|
||||||
std::ifstream ifile(freqMapFile.c_str());
|
std::string file = freqMapFile;
|
||||||
|
bool convertFromPitch = false;
|
||||||
|
if (pitchMapFile != "") {
|
||||||
|
file = pitchMapFile;
|
||||||
|
convertFromPitch = true;
|
||||||
|
}
|
||||||
|
std::ifstream ifile(file.c_str());
|
||||||
if (!ifile.is_open()) {
|
if (!ifile.is_open()) {
|
||||||
cerr << "ERROR: Failed to open frequency map file \""
|
cerr << "ERROR: Failed to open map file \"" << file << "\"" << endl;
|
||||||
<< freqMapFile << "\"" << endl;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
std::string line;
|
std::string line;
|
||||||
@@ -389,13 +403,16 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
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: Frequency map file \"" << freqMapFile
|
cerr << "ERROR: Map file \"" << file
|
||||||
<< "\" 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;
|
||||||
double freq = atof(line.substr(i).c_str());
|
double freq = atof(line.substr(i).c_str());
|
||||||
|
if (convertFromPitch) {
|
||||||
|
freq = pow(2.0, freq / 12.0);
|
||||||
|
}
|
||||||
freqMap[source] = freq;
|
freqMap[source] = freq;
|
||||||
if (debug > 0) {
|
if (debug > 0) {
|
||||||
cerr << "adding mapping for source frame " << source << " of frequency multiplier " << freq << endl;
|
cerr << "adding mapping for source frame " << source << " of frequency multiplier " << freq << endl;
|
||||||
@@ -505,11 +522,16 @@ 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;
|
||||||
|
|
||||||
|
if (freqMap.empty()) {
|
||||||
cerr << " and frequency ratio " << frequencyshift << endl;
|
cerr << " and frequency ratio " << frequencyshift << endl;
|
||||||
|
} else {
|
||||||
|
cerr << " and initial frequency ratio " << frequencyshift << endl;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
RubberBand::
|
RubberBand::
|
||||||
@@ -581,13 +603,34 @@ int main(int argc, char **argv)
|
|||||||
ts.setKeyFrameMap(timeMap);
|
ts.setKeyFrameMap(timeMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::map<size_t, double>::const_iterator freqMapItr = freqMap.begin();
|
||||||
|
|
||||||
size_t countIn = 0, countOut = 0;
|
size_t countIn = 0, countOut = 0;
|
||||||
|
|
||||||
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;
|
||||||
|
if (nextFreqFrame <= countIn) {
|
||||||
|
double s = frequencyshift * freqMapItr->second;
|
||||||
|
if (debug > 0) {
|
||||||
|
cerr << "at frame " << countIn
|
||||||
|
<< " 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;
|
countIn += count;
|
||||||
|
|
||||||
@@ -598,10 +641,10 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool final = (frame + ibs >= sfinfo.frames);
|
bool final = (frame + thisBlockSize >= sfinfo.frames);
|
||||||
|
|
||||||
if (debug > 2) {
|
if (debug > 2) {
|
||||||
cerr << "count = " << count << ", ibs = " << ibs << ", frame = " << frame << ", frames = " << sfinfo.frames << ", final = " << final << endl;
|
cerr << "count = " << count << ", ibs = " << thisBlockSize << ", frame = " << frame << ", frames = " << sfinfo.frames << ", final = " << final << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
ts.process(ibuf, count, final);
|
ts.process(ibuf, count, final);
|
||||||
@@ -652,7 +695,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
frame += ibs;
|
frame += thisBlockSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
|
|||||||
Reference in New Issue
Block a user