annotate src/rubberband-1.8.1/main/main.cpp @ 83:ae30d91d2ffe

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