annotate src/rubberband-1.8.1/main/main.cpp @ 169:223a55898ab9 tip default

Add null config files
author Chris Cannam <cannam@all-day-breakfast.com>
date Mon, 02 Mar 2020 14:03:47 +0000
parents 89f5e221ed7b
children
rev   line source
cannam@95 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
cannam@95 2
cannam@95 3 /*
cannam@95 4 Rubber Band Library
cannam@95 5 An audio time-stretching and pitch-shifting library.
cannam@95 6 Copyright 2007-2012 Particular Programs Ltd.
cannam@95 7
cannam@95 8 This program is free software; you can redistribute it and/or
cannam@95 9 modify it under the terms of the GNU General Public License as
cannam@95 10 published by the Free Software Foundation; either version 2 of the
cannam@95 11 License, or (at your option) any later version. See the file
cannam@95 12 COPYING included with this distribution for more information.
cannam@95 13
cannam@95 14 Alternatively, if you have a valid commercial licence for the
cannam@95 15 Rubber Band Library obtained by agreement with the copyright
cannam@95 16 holders, you may redistribute and/or modify it under the terms
cannam@95 17 described in that licence.
cannam@95 18
cannam@95 19 If you wish to distribute code using the Rubber Band Library
cannam@95 20 under terms other than those of the GNU General Public License,
cannam@95 21 you must obtain a valid commercial licence before doing so.
cannam@95 22 */
cannam@95 23
cannam@95 24 #include "rubberband/RubberBandStretcher.h"
cannam@95 25
cannam@95 26 #include <iostream>
cannam@95 27 #include <sndfile.h>
cannam@95 28 #include <cmath>
cannam@95 29 #include <time.h>
cannam@95 30 #include <cstdlib>
cannam@95 31 #include <cstring>
cannam@95 32 #include <string>
cannam@95 33
cannam@95 34 #include <fstream>
cannam@95 35
cannam@95 36 #include "system/sysutils.h"
cannam@95 37
cannam@95 38 #ifdef __MSVC__
cannam@95 39 #include "getopt/getopt.h"
cannam@95 40 #else
cannam@95 41 #include <getopt.h>
cannam@95 42 #include <unistd.h>
cannam@95 43 #include <sys/time.h>
cannam@95 44 #endif
cannam@95 45
cannam@95 46 #include "base/Profiler.h"
cannam@95 47
cannam@95 48 using namespace std;
cannam@95 49 using namespace RubberBand;
cannam@95 50
cannam@95 51 #ifdef _WIN32
cannam@95 52 using RubberBand::gettimeofday;
cannam@95 53 #endif
cannam@95 54
cannam@95 55 #ifdef __MSVC__
cannam@95 56 using RubberBand::usleep;
cannam@95 57 #endif
cannam@95 58
cannam@95 59 double tempo_convert(const char *str)
cannam@95 60 {
cannam@95 61 char *d = strchr((char *)str, ':');
cannam@95 62
cannam@95 63 if (!d || !*d) {
cannam@95 64 double m = atof(str);
cannam@95 65 if (m != 0.0) return 1.0 / m;
cannam@95 66 else return 1.0;
cannam@95 67 }
cannam@95 68
cannam@95 69 char *a = strdup(str);
cannam@95 70 char *b = strdup(d+1);
cannam@95 71 a[d-str] = '\0';
cannam@95 72 double m = atof(a);
cannam@95 73 double n = atof(b);
cannam@95 74 free(a);
cannam@95 75 free(b);
cannam@95 76 if (n != 0.0 && m != 0.0) return m / n;
cannam@95 77 else return 1.0;
cannam@95 78 }
cannam@95 79
cannam@95 80 int main(int argc, char **argv)
cannam@95 81 {
cannam@95 82 int c;
cannam@95 83
cannam@95 84 double ratio = 1.0;
cannam@95 85 double duration = 0.0;
cannam@95 86 double pitchshift = 0.0;
cannam@95 87 double frequencyshift = 1.0;
cannam@95 88 int debug = 0;
cannam@95 89 bool realtime = false;
cannam@95 90 bool precise = true;
cannam@95 91 int threading = 0;
cannam@95 92 bool lamination = true;
cannam@95 93 bool longwin = false;
cannam@95 94 bool shortwin = false;
cannam@95 95 bool smoothing = false;
cannam@95 96 bool hqpitch = false;
cannam@95 97 bool formant = false;
cannam@95 98 bool together = false;
cannam@95 99 bool crispchanged = false;
cannam@95 100 int crispness = -1;
cannam@95 101 bool help = false;
cannam@95 102 bool version = false;
cannam@95 103 bool quiet = false;
cannam@95 104
cannam@95 105 bool haveRatio = false;
cannam@95 106
cannam@95 107 std::string mapfile;
cannam@95 108
cannam@95 109 enum {
cannam@95 110 NoTransients,
cannam@95 111 BandLimitedTransients,
cannam@95 112 Transients
cannam@95 113 } transients = Transients;
cannam@95 114
cannam@95 115 enum {
cannam@95 116 CompoundDetector,
cannam@95 117 PercussiveDetector,
cannam@95 118 SoftDetector
cannam@95 119 } detector = CompoundDetector;
cannam@95 120
cannam@95 121 while (1) {
cannam@95 122 int optionIndex = 0;
cannam@95 123
cannam@95 124 static struct option longOpts[] = {
cannam@95 125 { "help", 0, 0, 'h' },
cannam@95 126 { "version", 0, 0, 'V' },
cannam@95 127 { "time", 1, 0, 't' },
cannam@95 128 { "tempo", 1, 0, 'T' },
cannam@95 129 { "duration", 1, 0, 'D' },
cannam@95 130 { "pitch", 1, 0, 'p' },
cannam@95 131 { "frequency", 1, 0, 'f' },
cannam@95 132 { "crisp", 1, 0, 'c' },
cannam@95 133 { "crispness", 1, 0, 'c' },
cannam@95 134 { "debug", 1, 0, 'd' },
cannam@95 135 { "realtime", 0, 0, 'R' },
cannam@95 136 { "loose", 0, 0, 'L' },
cannam@95 137 { "precise", 0, 0, 'P' },
cannam@95 138 { "formant", 0, 0, 'F' },
cannam@95 139 { "no-threads", 0, 0, '0' },
cannam@95 140 { "no-transients", 0, 0, '1' },
cannam@95 141 { "no-lamination", 0, 0, '2' },
cannam@95 142 { "centre-focus", 0, 0, '7' },
cannam@95 143 { "window-long", 0, 0, '3' },
cannam@95 144 { "window-short", 0, 0, '4' },
cannam@95 145 { "bl-transients", 0, 0, '8' },
cannam@95 146 { "detector-perc", 0, 0, '5' },
cannam@95 147 { "detector-soft", 0, 0, '6' },
cannam@95 148 { "smoothing", 0, 0, '9' },
cannam@95 149 { "pitch-hq", 0, 0, '%' },
cannam@95 150 { "threads", 0, 0, '@' },
cannam@95 151 { "quiet", 0, 0, 'q' },
cannam@95 152 { "timemap", 1, 0, 'M' },
cannam@95 153 { 0, 0, 0, 0 }
cannam@95 154 };
cannam@95 155
cannam@95 156 c = getopt_long(argc, argv,
cannam@95 157 "t:p:d:RLPFc:f:T:D:qhVM:",
cannam@95 158 longOpts, &optionIndex);
cannam@95 159 if (c == -1) break;
cannam@95 160
cannam@95 161 switch (c) {
cannam@95 162 case 'h': help = true; break;
cannam@95 163 case 'V': version = true; break;
cannam@95 164 case 't': ratio *= atof(optarg); haveRatio = true; break;
cannam@95 165 case 'T': ratio *= tempo_convert(optarg); haveRatio = true; break;
cannam@95 166 case 'D': duration = atof(optarg); haveRatio = true; break;
cannam@95 167 case 'p': pitchshift = atof(optarg); haveRatio = true; break;
cannam@95 168 case 'f': frequencyshift = atof(optarg); haveRatio = true; break;
cannam@95 169 case 'd': debug = atoi(optarg); break;
cannam@95 170 case 'R': realtime = true; break;
cannam@95 171 case 'L': precise = false; break;
cannam@95 172 case 'P': precise = true; break;
cannam@95 173 case 'F': formant = true; break;
cannam@95 174 case '0': threading = 1; break;
cannam@95 175 case '@': threading = 2; break;
cannam@95 176 case '1': transients = NoTransients; crispchanged = true; break;
cannam@95 177 case '2': lamination = false; crispchanged = true; break;
cannam@95 178 case '3': longwin = true; crispchanged = true; break;
cannam@95 179 case '4': shortwin = true; crispchanged = true; break;
cannam@95 180 case '5': detector = PercussiveDetector; crispchanged = true; break;
cannam@95 181 case '6': detector = SoftDetector; crispchanged = true; break;
cannam@95 182 case '7': together = true; break;
cannam@95 183 case '8': transients = BandLimitedTransients; crispchanged = true; break;
cannam@95 184 case '9': smoothing = true; crispchanged = true; break;
cannam@95 185 case '%': hqpitch = true; break;
cannam@95 186 case 'c': crispness = atoi(optarg); break;
cannam@95 187 case 'q': quiet = true; break;
cannam@95 188 case 'M': mapfile = optarg; break;
cannam@95 189 default: help = true; break;
cannam@95 190 }
cannam@95 191 }
cannam@95 192
cannam@95 193 if (version) {
cannam@95 194 cerr << RUBBERBAND_VERSION << endl;
cannam@95 195 return 0;
cannam@95 196 }
cannam@95 197
cannam@95 198 if (help || !haveRatio || optind + 2 != argc) {
cannam@95 199 cerr << endl;
cannam@95 200 cerr << "Rubber Band" << endl;
cannam@95 201 cerr << "An audio time-stretching and pitch-shifting library and utility program." << endl;
cannam@95 202 cerr << "Copyright 2007-2012 Particular Programs Ltd." << endl;
cannam@95 203 cerr << endl;
cannam@95 204 cerr << " Usage: " << argv[0] << " [options] <infile.wav> <outfile.wav>" << endl;
cannam@95 205 cerr << endl;
cannam@95 206 cerr << "You must specify at least one of the following time and pitch ratio options." << endl;
cannam@95 207 cerr << endl;
cannam@95 208 cerr << " -t<X>, --time <X> Stretch to X times original duration, or" << endl;
cannam@95 209 cerr << " -T<X>, --tempo <X> Change tempo by multiple X (same as --time 1/X), or" << endl;
cannam@95 210 cerr << " -T<X>, --tempo <X>:<Y> Change tempo from X to Y (same as --time X/Y), or" << endl;
cannam@95 211 cerr << " -D<X>, --duration <X> Stretch or squash to make output file X seconds long" << endl;
cannam@95 212 cerr << endl;
cannam@95 213 cerr << " -p<X>, --pitch <X> Raise pitch by X semitones, or" << endl;
cannam@95 214 cerr << " -f<X>, --frequency <X> Change frequency by multiple X" << endl;
cannam@95 215 cerr << endl;
cannam@95 216 cerr << " -M<F>, --timemap <F> Use file F as the source for key frame map" << endl;
cannam@95 217 cerr << endl;
cannam@95 218 cerr << "A map file consists of a series of lines each having two numbers separated" << endl;
cannam@95 219 cerr << "by a single space. These are source and target sample frame numbers for fixed" << endl;
cannam@95 220 cerr << "time points within the audio data, defining a varying stretch factor through" << endl;
cannam@95 221 cerr << "the audio. You must specify an overall stretch factor using e.g. -t as well." << endl;
cannam@95 222 cerr << endl;
cannam@95 223 cerr << "The following options provide a simple way to adjust the sound. See below" << endl;
cannam@95 224 cerr << "for more details." << endl;
cannam@95 225 cerr << endl;
cannam@95 226 cerr << " -c<N>, --crisp <N> Crispness (N = 0,1,2,3,4,5,6); default 5 (see below)" << endl;
cannam@95 227 cerr << " -F, --formant Enable formant preservation when pitch shifting" << endl;
cannam@95 228 cerr << endl;
cannam@95 229 cerr << "The remaining options fine-tune the processing mode and stretch algorithm." << endl;
cannam@95 230 cerr << "These are mostly included for test purposes; the default settings and standard" << endl;
cannam@95 231 cerr << "crispness parameter are intended to provide the best sounding set of options" << endl;
cannam@95 232 cerr << "for most situations. The default is to use none of these options." << endl;
cannam@95 233 cerr << endl;
cannam@95 234 cerr << " -L, --loose Relax timing in hope of better transient preservation" << endl;
cannam@95 235 cerr << " -P, --precise Ignored: The opposite of -L, this is default from 1.6" << endl;
cannam@95 236 cerr << " -R, --realtime Select realtime mode (implies --no-threads)" << endl;
cannam@95 237 cerr << " --no-threads No extra threads regardless of CPU and channel count" << endl;
cannam@95 238 cerr << " --threads Assume multi-CPU even if only one CPU is identified" << endl;
cannam@95 239 cerr << " --no-transients Disable phase resynchronisation at transients" << endl;
cannam@95 240 cerr << " --bl-transients Band-limit phase resync to extreme frequencies" << endl;
cannam@95 241 cerr << " --no-lamination Disable phase lamination" << endl;
cannam@95 242 cerr << " --window-long Use longer processing window (actual size may vary)" << endl;
cannam@95 243 cerr << " --window-short Use shorter processing window" << endl;
cannam@95 244 cerr << " --smoothing Apply window presum and time-domain smoothing" << endl;
cannam@95 245 cerr << " --detector-perc Use percussive transient detector (as in pre-1.5)" << endl;
cannam@95 246 cerr << " --detector-soft Use soft transient detector" << endl;
cannam@95 247 cerr << " --pitch-hq In RT mode, use a slower, higher quality pitch shift" << endl;
cannam@95 248 cerr << " --centre-focus Preserve focus of centre material in stereo" << endl;
cannam@95 249 cerr << " (at a cost in width and individual channel quality)" << endl;
cannam@95 250 cerr << endl;
cannam@95 251 cerr << " -d<N>, --debug <N> Select debug level (N = 0,1,2,3); default 0, full 3" << endl;
cannam@95 252 cerr << " (N.B. debug level 3 includes audible ticks in output)" << endl;
cannam@95 253 cerr << " -q, --quiet Suppress progress output" << endl;
cannam@95 254 cerr << endl;
cannam@95 255 cerr << " -V, --version Show version number and exit" << endl;
cannam@95 256 cerr << " -h, --help Show this help" << endl;
cannam@95 257 cerr << endl;
cannam@95 258 cerr << "\"Crispness\" levels:" << endl;
cannam@95 259 cerr << " -c 0 equivalent to --no-transients --no-lamination --window-long" << endl;
cannam@95 260 cerr << " -c 1 equivalent to --detector-soft --no-lamination --window-long (for piano)" << endl;
cannam@95 261 cerr << " -c 2 equivalent to --no-transients --no-lamination" << endl;
cannam@95 262 cerr << " -c 3 equivalent to --no-transients" << endl;
cannam@95 263 cerr << " -c 4 equivalent to --bl-transients" << endl;
cannam@95 264 cerr << " -c 5 default processing options" << endl;
cannam@95 265 cerr << " -c 6 equivalent to --no-lamination --window-short (may be good for drums)" << endl;
cannam@95 266 cerr << endl;
cannam@95 267 return 2;
cannam@95 268 }
cannam@95 269
cannam@95 270 if (crispness >= 0 && crispchanged) {
cannam@95 271 cerr << "WARNING: Both crispness option and transients, lamination or window options" << endl;
cannam@95 272 cerr << " provided -- crispness will override these other options" << endl;
cannam@95 273 }
cannam@95 274
cannam@95 275 switch (crispness) {
cannam@95 276 case -1: crispness = 5; break;
cannam@95 277 case 0: detector = CompoundDetector; transients = NoTransients; lamination = false; longwin = true; shortwin = false; break;
cannam@95 278 case 1: detector = SoftDetector; transients = Transients; lamination = false; longwin = true; shortwin = false; break;
cannam@95 279 case 2: detector = CompoundDetector; transients = NoTransients; lamination = false; longwin = false; shortwin = false; break;
cannam@95 280 case 3: detector = CompoundDetector; transients = NoTransients; lamination = true; longwin = false; shortwin = false; break;
cannam@95 281 case 4: detector = CompoundDetector; transients = BandLimitedTransients; lamination = true; longwin = false; shortwin = false; break;
cannam@95 282 case 5: detector = CompoundDetector; transients = Transients; lamination = true; longwin = false; shortwin = false; break;
cannam@95 283 case 6: detector = CompoundDetector; transients = Transients; lamination = false; longwin = false; shortwin = true; break;
cannam@95 284 };
cannam@95 285
cannam@95 286 if (!quiet) {
cannam@95 287 cerr << "Using crispness level: " << crispness << " (";
cannam@95 288 switch (crispness) {
cannam@95 289 case 0: cerr << "Mushy"; break;
cannam@95 290 case 1: cerr << "Piano"; break;
cannam@95 291 case 2: cerr << "Smooth"; break;
cannam@95 292 case 3: cerr << "Balanced multitimbral mixture"; break;
cannam@95 293 case 4: cerr << "Unpitched percussion with stable notes"; break;
cannam@95 294 case 5: cerr << "Crisp monophonic instrumental"; break;
cannam@95 295 case 6: cerr << "Unpitched solo percussion"; break;
cannam@95 296 }
cannam@95 297 cerr << ")" << endl;
cannam@95 298 }
cannam@95 299
cannam@95 300 std::map<size_t, size_t> mapping;
cannam@95 301
cannam@95 302 if (mapfile != "") {
cannam@95 303 std::ifstream ifile(mapfile.c_str());
cannam@95 304 if (!ifile.is_open()) {
cannam@95 305 cerr << "ERROR: Failed to open time map file \"" << mapfile << "\""
cannam@95 306 << endl;
cannam@95 307 return 1;
cannam@95 308 }
cannam@95 309 std::string line;
cannam@95 310 int lineno = 0;
cannam@95 311 while (!ifile.eof()) {
cannam@95 312 std::getline(ifile, line);
cannam@95 313 while (line.length() > 0 && line[0] == ' ') line = line.substr(1);
cannam@95 314 if (line == "") {
cannam@95 315 ++lineno;
cannam@95 316 continue;
cannam@95 317 }
cannam@95 318 std::string::size_type i = line.find_first_of(" ");
cannam@95 319 if (i == std::string::npos) {
cannam@95 320 cerr << "ERROR: Time map file \"" << mapfile
cannam@95 321 << "\" is malformed at line " << lineno << endl;
cannam@95 322 return 1;
cannam@95 323 }
cannam@95 324 size_t source = atoi(line.substr(0, i).c_str());
cannam@95 325 while (i < line.length() && line[i] == ' ') ++i;
cannam@95 326 size_t target = atoi(line.substr(i).c_str());
cannam@95 327 mapping[source] = target;
cannam@95 328 if (debug > 0) {
cannam@95 329 cerr << "adding mapping from " << source << " to " << target << endl;
cannam@95 330 }
cannam@95 331 ++lineno;
cannam@95 332 }
cannam@95 333 ifile.close();
cannam@95 334
cannam@95 335 if (!quiet) {
cannam@95 336 cerr << "Read " << mapping.size() << " line(s) from map file" << endl;
cannam@95 337 }
cannam@95 338 }
cannam@95 339
cannam@95 340 char *fileName = strdup(argv[optind++]);
cannam@95 341 char *fileNameOut = strdup(argv[optind++]);
cannam@95 342
cannam@95 343 SNDFILE *sndfile;
cannam@95 344 SNDFILE *sndfileOut;
cannam@95 345 SF_INFO sfinfo;
cannam@95 346 SF_INFO sfinfoOut;
cannam@95 347 memset(&sfinfo, 0, sizeof(SF_INFO));
cannam@95 348
cannam@95 349 sndfile = sf_open(fileName, SFM_READ, &sfinfo);
cannam@95 350 if (!sndfile) {
cannam@95 351 cerr << "ERROR: Failed to open input file \"" << fileName << "\": "
cannam@95 352 << sf_strerror(sndfile) << endl;
cannam@95 353 return 1;
cannam@95 354 }
cannam@95 355
cannam@95 356 if (duration != 0.0) {
cannam@95 357 if (sfinfo.frames == 0 || sfinfo.samplerate == 0) {
cannam@95 358 cerr << "ERROR: File lacks frame count or sample rate in header, cannot use --duration" << endl;
cannam@95 359 return 1;
cannam@95 360 }
cannam@95 361 double induration = double(sfinfo.frames) / double(sfinfo.samplerate);
cannam@95 362 if (induration != 0.0) ratio = duration / induration;
cannam@95 363 }
cannam@95 364
cannam@95 365 sfinfoOut.channels = sfinfo.channels;
cannam@95 366 sfinfoOut.format = sfinfo.format;
cannam@95 367 sfinfoOut.frames = int(sfinfo.frames * ratio + 0.1);
cannam@95 368 sfinfoOut.samplerate = sfinfo.samplerate;
cannam@95 369 sfinfoOut.sections = sfinfo.sections;
cannam@95 370 sfinfoOut.seekable = sfinfo.seekable;
cannam@95 371
cannam@95 372 sndfileOut = sf_open(fileNameOut, SFM_WRITE, &sfinfoOut) ;
cannam@95 373 if (!sndfileOut) {
cannam@95 374 cerr << "ERROR: Failed to open output file \"" << fileNameOut << "\" for writing: "
cannam@95 375 << sf_strerror(sndfileOut) << endl;
cannam@95 376 return 1;
cannam@95 377 }
cannam@95 378
cannam@95 379 int ibs = 1024;
cannam@95 380 size_t channels = sfinfo.channels;
cannam@95 381
cannam@95 382 RubberBandStretcher::Options options = 0;
cannam@95 383 if (realtime) options |= RubberBandStretcher::OptionProcessRealTime;
cannam@95 384 if (precise) options |= RubberBandStretcher::OptionStretchPrecise;
cannam@95 385 if (!lamination) options |= RubberBandStretcher::OptionPhaseIndependent;
cannam@95 386 if (longwin) options |= RubberBandStretcher::OptionWindowLong;
cannam@95 387 if (shortwin) options |= RubberBandStretcher::OptionWindowShort;
cannam@95 388 if (smoothing) options |= RubberBandStretcher::OptionSmoothingOn;
cannam@95 389 if (formant) options |= RubberBandStretcher::OptionFormantPreserved;
cannam@95 390 if (hqpitch) options |= RubberBandStretcher::OptionPitchHighQuality;
cannam@95 391 if (together) options |= RubberBandStretcher::OptionChannelsTogether;
cannam@95 392
cannam@95 393 switch (threading) {
cannam@95 394 case 0:
cannam@95 395 options |= RubberBandStretcher::OptionThreadingAuto;
cannam@95 396 break;
cannam@95 397 case 1:
cannam@95 398 options |= RubberBandStretcher::OptionThreadingNever;
cannam@95 399 break;
cannam@95 400 case 2:
cannam@95 401 options |= RubberBandStretcher::OptionThreadingAlways;
cannam@95 402 break;
cannam@95 403 }
cannam@95 404
cannam@95 405 switch (transients) {
cannam@95 406 case NoTransients:
cannam@95 407 options |= RubberBandStretcher::OptionTransientsSmooth;
cannam@95 408 break;
cannam@95 409 case BandLimitedTransients:
cannam@95 410 options |= RubberBandStretcher::OptionTransientsMixed;
cannam@95 411 break;
cannam@95 412 case Transients:
cannam@95 413 options |= RubberBandStretcher::OptionTransientsCrisp;
cannam@95 414 break;
cannam@95 415 }
cannam@95 416
cannam@95 417 switch (detector) {
cannam@95 418 case CompoundDetector:
cannam@95 419 options |= RubberBandStretcher::OptionDetectorCompound;
cannam@95 420 break;
cannam@95 421 case PercussiveDetector:
cannam@95 422 options |= RubberBandStretcher::OptionDetectorPercussive;
cannam@95 423 break;
cannam@95 424 case SoftDetector:
cannam@95 425 options |= RubberBandStretcher::OptionDetectorSoft;
cannam@95 426 break;
cannam@95 427 }
cannam@95 428
cannam@95 429 if (pitchshift != 0.0) {
cannam@95 430 frequencyshift *= pow(2.0, pitchshift / 12);
cannam@95 431 }
cannam@95 432
cannam@95 433 cerr << "Using time ratio " << ratio;
cannam@95 434 cerr << " and frequency ratio " << frequencyshift << endl;
cannam@95 435
cannam@95 436 #ifdef _WIN32
cannam@95 437 RubberBand::
cannam@95 438 #endif
cannam@95 439 timeval tv;
cannam@95 440 (void)gettimeofday(&tv, 0);
cannam@95 441
cannam@95 442 RubberBandStretcher::setDefaultDebugLevel(debug);
cannam@95 443
cannam@95 444 RubberBandStretcher ts(sfinfo.samplerate, channels, options,
cannam@95 445 ratio, frequencyshift);
cannam@95 446
cannam@95 447 ts.setExpectedInputDuration(sfinfo.frames);
cannam@95 448
cannam@95 449 float *fbuf = new float[channels * ibs];
cannam@95 450 float **ibuf = new float *[channels];
cannam@95 451 for (size_t i = 0; i < channels; ++i) ibuf[i] = new float[ibs];
cannam@95 452
cannam@95 453 int frame = 0;
cannam@95 454 int percent = 0;
cannam@95 455
cannam@95 456 sf_seek(sndfile, 0, SEEK_SET);
cannam@95 457
cannam@95 458 if (!realtime) {
cannam@95 459
cannam@95 460 if (!quiet) {
cannam@95 461 cerr << "Pass 1: Studying..." << endl;
cannam@95 462 }
cannam@95 463
cannam@95 464 while (frame < sfinfo.frames) {
cannam@95 465
cannam@95 466 int count = -1;
cannam@95 467
cannam@95 468 if ((count = sf_readf_float(sndfile, fbuf, ibs)) <= 0) break;
cannam@95 469
cannam@95 470 for (size_t c = 0; c < channels; ++c) {
cannam@95 471 for (int i = 0; i < count; ++i) {
cannam@95 472 float value = fbuf[i * channels + c];
cannam@95 473 ibuf[c][i] = value;
cannam@95 474 }
cannam@95 475 }
cannam@95 476
cannam@95 477 bool final = (frame + ibs >= sfinfo.frames);
cannam@95 478
cannam@95 479 ts.study(ibuf, count, final);
cannam@95 480
cannam@95 481 int p = int((double(frame) * 100.0) / sfinfo.frames);
cannam@95 482 if (p > percent || frame == 0) {
cannam@95 483 percent = p;
cannam@95 484 if (!quiet) {
cannam@95 485 cerr << "\r" << percent << "% ";
cannam@95 486 }
cannam@95 487 }
cannam@95 488
cannam@95 489 frame += ibs;
cannam@95 490 }
cannam@95 491
cannam@95 492 if (!quiet) {
cannam@95 493 cerr << "\rCalculating profile..." << endl;
cannam@95 494 }
cannam@95 495
cannam@95 496 sf_seek(sndfile, 0, SEEK_SET);
cannam@95 497 }
cannam@95 498
cannam@95 499 frame = 0;
cannam@95 500 percent = 0;
cannam@95 501
cannam@95 502 if (!mapping.empty()) {
cannam@95 503 ts.setKeyFrameMap(mapping);
cannam@95 504 }
cannam@95 505
cannam@95 506 size_t countIn = 0, countOut = 0;
cannam@95 507
cannam@95 508 while (frame < sfinfo.frames) {
cannam@95 509
cannam@95 510 int count = -1;
cannam@95 511
cannam@95 512 if ((count = sf_readf_float(sndfile, fbuf, ibs)) < 0) break;
cannam@95 513
cannam@95 514 countIn += count;
cannam@95 515
cannam@95 516 for (size_t c = 0; c < channels; ++c) {
cannam@95 517 for (int i = 0; i < count; ++i) {
cannam@95 518 float value = fbuf[i * channels + c];
cannam@95 519 ibuf[c][i] = value;
cannam@95 520 }
cannam@95 521 }
cannam@95 522
cannam@95 523 bool final = (frame + ibs >= sfinfo.frames);
cannam@95 524
cannam@95 525 if (debug > 2) {
cannam@95 526 cerr << "count = " << count << ", ibs = " << ibs << ", frame = " << frame << ", frames = " << sfinfo.frames << ", final = " << final << endl;
cannam@95 527 }
cannam@95 528
cannam@95 529 ts.process(ibuf, count, final);
cannam@95 530
cannam@95 531 int avail = ts.available();
cannam@95 532 if (debug > 1) cerr << "available = " << avail << endl;
cannam@95 533
cannam@95 534 if (avail > 0) {
cannam@95 535 float **obf = new float *[channels];
cannam@95 536 for (size_t i = 0; i < channels; ++i) {
cannam@95 537 obf[i] = new float[avail];
cannam@95 538 }
cannam@95 539 ts.retrieve(obf, avail);
cannam@95 540 countOut += avail;
cannam@95 541 float *fobf = new float[channels * avail];
cannam@95 542 for (size_t c = 0; c < channels; ++c) {
cannam@95 543 for (int i = 0; i < avail; ++i) {
cannam@95 544 float value = obf[c][i];
cannam@95 545 if (value > 1.f) value = 1.f;
cannam@95 546 if (value < -1.f) value = -1.f;
cannam@95 547 fobf[i * channels + c] = value;
cannam@95 548 }
cannam@95 549 }
cannam@95 550 // cout << "fobf mean: ";
cannam@95 551 // double d = 0;
cannam@95 552 // for (int i = 0; i < avail; ++i) {
cannam@95 553 // d += fobf[i];
cannam@95 554 // }
cannam@95 555 // d /= avail;
cannam@95 556 // cout << d << endl;
cannam@95 557 sf_writef_float(sndfileOut, fobf, avail);
cannam@95 558 delete[] fobf;
cannam@95 559 for (size_t i = 0; i < channels; ++i) {
cannam@95 560 delete[] obf[i];
cannam@95 561 }
cannam@95 562 delete[] obf;
cannam@95 563 }
cannam@95 564
cannam@95 565 if (frame == 0 && !realtime && !quiet) {
cannam@95 566 cerr << "Pass 2: Processing..." << endl;
cannam@95 567 }
cannam@95 568
cannam@95 569 int p = int((double(frame) * 100.0) / sfinfo.frames);
cannam@95 570 if (p > percent || frame == 0) {
cannam@95 571 percent = p;
cannam@95 572 if (!quiet) {
cannam@95 573 cerr << "\r" << percent << "% ";
cannam@95 574 }
cannam@95 575 }
cannam@95 576
cannam@95 577 frame += ibs;
cannam@95 578 }
cannam@95 579
cannam@95 580 if (!quiet) {
cannam@95 581 cerr << "\r " << endl;
cannam@95 582 }
cannam@95 583 int avail;
cannam@95 584
cannam@95 585 while ((avail = ts.available()) >= 0) {
cannam@95 586
cannam@95 587 if (debug > 1) {
cannam@95 588 cerr << "(completing) available = " << avail << endl;
cannam@95 589 }
cannam@95 590
cannam@95 591 if (avail > 0) {
cannam@95 592 float **obf = new float *[channels];
cannam@95 593 for (size_t i = 0; i < channels; ++i) {
cannam@95 594 obf[i] = new float[avail];
cannam@95 595 }
cannam@95 596 ts.retrieve(obf, avail);
cannam@95 597 countOut += avail;
cannam@95 598 float *fobf = new float[channels * avail];
cannam@95 599 for (size_t c = 0; c < channels; ++c) {
cannam@95 600 for (int i = 0; i < avail; ++i) {
cannam@95 601 float value = obf[c][i];
cannam@95 602 if (value > 1.f) value = 1.f;
cannam@95 603 if (value < -1.f) value = -1.f;
cannam@95 604 fobf[i * channels + c] = value;
cannam@95 605 }
cannam@95 606 }
cannam@95 607
cannam@95 608 sf_writef_float(sndfileOut, fobf, avail);
cannam@95 609 delete[] fobf;
cannam@95 610 for (size_t i = 0; i < channels; ++i) {
cannam@95 611 delete[] obf[i];
cannam@95 612 }
cannam@95 613 delete[] obf;
cannam@95 614 } else {
cannam@95 615 usleep(10000);
cannam@95 616 }
cannam@95 617 }
cannam@95 618
cannam@95 619 sf_close(sndfile);
cannam@95 620 sf_close(sndfileOut);
cannam@95 621
cannam@95 622 if (!quiet) {
cannam@95 623
cannam@95 624 cerr << "in: " << countIn << ", out: " << countOut << ", ratio: " << float(countOut)/float(countIn) << ", ideal output: " << lrint(countIn * ratio) << ", error: " << abs(lrint(countIn * ratio) - int(countOut)) << endl;
cannam@95 625
cannam@95 626 #ifdef _WIN32
cannam@95 627 RubberBand::
cannam@95 628 #endif
cannam@95 629 timeval etv;
cannam@95 630 (void)gettimeofday(&etv, 0);
cannam@95 631
cannam@95 632 etv.tv_sec -= tv.tv_sec;
cannam@95 633 if (etv.tv_usec < tv.tv_usec) {
cannam@95 634 etv.tv_usec += 1000000;
cannam@95 635 etv.tv_sec -= 1;
cannam@95 636 }
cannam@95 637 etv.tv_usec -= tv.tv_usec;
cannam@95 638
cannam@95 639 double sec = double(etv.tv_sec) + (double(etv.tv_usec) / 1000000.0);
cannam@95 640 cerr << "elapsed time: " << sec << " sec, in frames/sec: " << countIn/sec << ", out frames/sec: " << countOut/sec << endl;
cannam@95 641 }
cannam@95 642
cannam@95 643 RubberBand::Profiler::dump();
cannam@95 644
cannam@95 645 return 0;
cannam@95 646 }
cannam@95 647
cannam@95 648