cannam@95: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ cannam@95: cannam@95: /* cannam@95: Rubber Band Library cannam@95: An audio time-stretching and pitch-shifting library. cannam@95: Copyright 2007-2012 Particular Programs Ltd. cannam@95: cannam@95: This program is free software; you can redistribute it and/or cannam@95: modify it under the terms of the GNU General Public License as cannam@95: published by the Free Software Foundation; either version 2 of the cannam@95: License, or (at your option) any later version. See the file cannam@95: COPYING included with this distribution for more information. cannam@95: cannam@95: Alternatively, if you have a valid commercial licence for the cannam@95: Rubber Band Library obtained by agreement with the copyright cannam@95: holders, you may redistribute and/or modify it under the terms cannam@95: described in that licence. cannam@95: cannam@95: If you wish to distribute code using the Rubber Band Library cannam@95: under terms other than those of the GNU General Public License, cannam@95: you must obtain a valid commercial licence before doing so. cannam@95: */ cannam@95: cannam@95: #include "rubberband/RubberBandStretcher.h" cannam@95: cannam@95: #include cannam@95: #include cannam@95: #include cannam@95: #include cannam@95: #include cannam@95: #include cannam@95: #include cannam@95: cannam@95: #include cannam@95: cannam@95: #include "system/sysutils.h" cannam@95: cannam@95: #ifdef __MSVC__ cannam@95: #include "getopt/getopt.h" cannam@95: #else cannam@95: #include cannam@95: #include cannam@95: #include cannam@95: #endif cannam@95: cannam@95: #include "base/Profiler.h" cannam@95: cannam@95: using namespace std; cannam@95: using namespace RubberBand; cannam@95: cannam@95: #ifdef _WIN32 cannam@95: using RubberBand::gettimeofday; cannam@95: #endif cannam@95: cannam@95: #ifdef __MSVC__ cannam@95: using RubberBand::usleep; cannam@95: #endif cannam@95: cannam@95: double tempo_convert(const char *str) cannam@95: { cannam@95: char *d = strchr((char *)str, ':'); cannam@95: cannam@95: if (!d || !*d) { cannam@95: double m = atof(str); cannam@95: if (m != 0.0) return 1.0 / m; cannam@95: else return 1.0; cannam@95: } cannam@95: cannam@95: char *a = strdup(str); cannam@95: char *b = strdup(d+1); cannam@95: a[d-str] = '\0'; cannam@95: double m = atof(a); cannam@95: double n = atof(b); cannam@95: free(a); cannam@95: free(b); cannam@95: if (n != 0.0 && m != 0.0) return m / n; cannam@95: else return 1.0; cannam@95: } cannam@95: cannam@95: int main(int argc, char **argv) cannam@95: { cannam@95: int c; cannam@95: cannam@95: double ratio = 1.0; cannam@95: double duration = 0.0; cannam@95: double pitchshift = 0.0; cannam@95: double frequencyshift = 1.0; cannam@95: int debug = 0; cannam@95: bool realtime = false; cannam@95: bool precise = true; cannam@95: int threading = 0; cannam@95: bool lamination = true; cannam@95: bool longwin = false; cannam@95: bool shortwin = false; cannam@95: bool smoothing = false; cannam@95: bool hqpitch = false; cannam@95: bool formant = false; cannam@95: bool together = false; cannam@95: bool crispchanged = false; cannam@95: int crispness = -1; cannam@95: bool help = false; cannam@95: bool version = false; cannam@95: bool quiet = false; cannam@95: cannam@95: bool haveRatio = false; cannam@95: cannam@95: std::string mapfile; cannam@95: cannam@95: enum { cannam@95: NoTransients, cannam@95: BandLimitedTransients, cannam@95: Transients cannam@95: } transients = Transients; cannam@95: cannam@95: enum { cannam@95: CompoundDetector, cannam@95: PercussiveDetector, cannam@95: SoftDetector cannam@95: } detector = CompoundDetector; cannam@95: cannam@95: while (1) { cannam@95: int optionIndex = 0; cannam@95: cannam@95: static struct option longOpts[] = { cannam@95: { "help", 0, 0, 'h' }, cannam@95: { "version", 0, 0, 'V' }, cannam@95: { "time", 1, 0, 't' }, cannam@95: { "tempo", 1, 0, 'T' }, cannam@95: { "duration", 1, 0, 'D' }, cannam@95: { "pitch", 1, 0, 'p' }, cannam@95: { "frequency", 1, 0, 'f' }, cannam@95: { "crisp", 1, 0, 'c' }, cannam@95: { "crispness", 1, 0, 'c' }, cannam@95: { "debug", 1, 0, 'd' }, cannam@95: { "realtime", 0, 0, 'R' }, cannam@95: { "loose", 0, 0, 'L' }, cannam@95: { "precise", 0, 0, 'P' }, cannam@95: { "formant", 0, 0, 'F' }, cannam@95: { "no-threads", 0, 0, '0' }, cannam@95: { "no-transients", 0, 0, '1' }, cannam@95: { "no-lamination", 0, 0, '2' }, cannam@95: { "centre-focus", 0, 0, '7' }, cannam@95: { "window-long", 0, 0, '3' }, cannam@95: { "window-short", 0, 0, '4' }, cannam@95: { "bl-transients", 0, 0, '8' }, cannam@95: { "detector-perc", 0, 0, '5' }, cannam@95: { "detector-soft", 0, 0, '6' }, cannam@95: { "smoothing", 0, 0, '9' }, cannam@95: { "pitch-hq", 0, 0, '%' }, cannam@95: { "threads", 0, 0, '@' }, cannam@95: { "quiet", 0, 0, 'q' }, cannam@95: { "timemap", 1, 0, 'M' }, cannam@95: { 0, 0, 0, 0 } cannam@95: }; cannam@95: cannam@95: c = getopt_long(argc, argv, cannam@95: "t:p:d:RLPFc:f:T:D:qhVM:", cannam@95: longOpts, &optionIndex); cannam@95: if (c == -1) break; cannam@95: cannam@95: switch (c) { cannam@95: case 'h': help = true; break; cannam@95: case 'V': version = true; break; cannam@95: case 't': ratio *= atof(optarg); haveRatio = true; break; cannam@95: case 'T': ratio *= tempo_convert(optarg); haveRatio = true; break; cannam@95: case 'D': duration = atof(optarg); haveRatio = true; break; cannam@95: case 'p': pitchshift = atof(optarg); haveRatio = true; break; cannam@95: case 'f': frequencyshift = atof(optarg); haveRatio = true; break; cannam@95: case 'd': debug = atoi(optarg); break; cannam@95: case 'R': realtime = true; break; cannam@95: case 'L': precise = false; break; cannam@95: case 'P': precise = true; break; cannam@95: case 'F': formant = true; break; cannam@95: case '0': threading = 1; break; cannam@95: case '@': threading = 2; break; cannam@95: case '1': transients = NoTransients; crispchanged = true; break; cannam@95: case '2': lamination = false; crispchanged = true; break; cannam@95: case '3': longwin = true; crispchanged = true; break; cannam@95: case '4': shortwin = true; crispchanged = true; break; cannam@95: case '5': detector = PercussiveDetector; crispchanged = true; break; cannam@95: case '6': detector = SoftDetector; crispchanged = true; break; cannam@95: case '7': together = true; break; cannam@95: case '8': transients = BandLimitedTransients; crispchanged = true; break; cannam@95: case '9': smoothing = true; crispchanged = true; break; cannam@95: case '%': hqpitch = true; break; cannam@95: case 'c': crispness = atoi(optarg); break; cannam@95: case 'q': quiet = true; break; cannam@95: case 'M': mapfile = optarg; break; cannam@95: default: help = true; break; cannam@95: } cannam@95: } cannam@95: cannam@95: if (version) { cannam@95: cerr << RUBBERBAND_VERSION << endl; cannam@95: return 0; cannam@95: } cannam@95: cannam@95: if (help || !haveRatio || optind + 2 != argc) { cannam@95: cerr << endl; cannam@95: cerr << "Rubber Band" << endl; cannam@95: cerr << "An audio time-stretching and pitch-shifting library and utility program." << endl; cannam@95: cerr << "Copyright 2007-2012 Particular Programs Ltd." << endl; cannam@95: cerr << endl; cannam@95: cerr << " Usage: " << argv[0] << " [options] " << endl; cannam@95: cerr << endl; cannam@95: cerr << "You must specify at least one of the following time and pitch ratio options." << endl; cannam@95: cerr << endl; cannam@95: cerr << " -t, --time Stretch to X times original duration, or" << endl; cannam@95: cerr << " -T, --tempo Change tempo by multiple X (same as --time 1/X), or" << endl; cannam@95: cerr << " -T, --tempo : Change tempo from X to Y (same as --time X/Y), or" << endl; cannam@95: cerr << " -D, --duration Stretch or squash to make output file X seconds long" << endl; cannam@95: cerr << endl; cannam@95: cerr << " -p, --pitch Raise pitch by X semitones, or" << endl; cannam@95: cerr << " -f, --frequency Change frequency by multiple X" << endl; cannam@95: cerr << endl; cannam@95: cerr << " -M, --timemap Use file F as the source for key frame map" << endl; cannam@95: cerr << endl; cannam@95: cerr << "A map file consists of a series of lines each having two numbers separated" << endl; cannam@95: cerr << "by a single space. These are source and target sample frame numbers for fixed" << endl; cannam@95: cerr << "time points within the audio data, defining a varying stretch factor through" << endl; cannam@95: cerr << "the audio. You must specify an overall stretch factor using e.g. -t as well." << endl; cannam@95: cerr << endl; cannam@95: cerr << "The following options provide a simple way to adjust the sound. See below" << endl; cannam@95: cerr << "for more details." << endl; cannam@95: cerr << endl; cannam@95: cerr << " -c, --crisp Crispness (N = 0,1,2,3,4,5,6); default 5 (see below)" << endl; cannam@95: cerr << " -F, --formant Enable formant preservation when pitch shifting" << endl; cannam@95: cerr << endl; cannam@95: cerr << "The remaining options fine-tune the processing mode and stretch algorithm." << endl; cannam@95: cerr << "These are mostly included for test purposes; the default settings and standard" << endl; cannam@95: cerr << "crispness parameter are intended to provide the best sounding set of options" << endl; cannam@95: cerr << "for most situations. The default is to use none of these options." << endl; cannam@95: cerr << endl; cannam@95: cerr << " -L, --loose Relax timing in hope of better transient preservation" << endl; cannam@95: cerr << " -P, --precise Ignored: The opposite of -L, this is default from 1.6" << endl; cannam@95: cerr << " -R, --realtime Select realtime mode (implies --no-threads)" << endl; cannam@95: cerr << " --no-threads No extra threads regardless of CPU and channel count" << endl; cannam@95: cerr << " --threads Assume multi-CPU even if only one CPU is identified" << endl; cannam@95: cerr << " --no-transients Disable phase resynchronisation at transients" << endl; cannam@95: cerr << " --bl-transients Band-limit phase resync to extreme frequencies" << endl; cannam@95: cerr << " --no-lamination Disable phase lamination" << endl; cannam@95: cerr << " --window-long Use longer processing window (actual size may vary)" << endl; cannam@95: cerr << " --window-short Use shorter processing window" << endl; cannam@95: cerr << " --smoothing Apply window presum and time-domain smoothing" << endl; cannam@95: cerr << " --detector-perc Use percussive transient detector (as in pre-1.5)" << endl; cannam@95: cerr << " --detector-soft Use soft transient detector" << endl; cannam@95: cerr << " --pitch-hq In RT mode, use a slower, higher quality pitch shift" << endl; cannam@95: cerr << " --centre-focus Preserve focus of centre material in stereo" << endl; cannam@95: cerr << " (at a cost in width and individual channel quality)" << endl; cannam@95: cerr << endl; cannam@95: cerr << " -d, --debug Select debug level (N = 0,1,2,3); default 0, full 3" << endl; cannam@95: cerr << " (N.B. debug level 3 includes audible ticks in output)" << endl; cannam@95: cerr << " -q, --quiet Suppress progress output" << endl; cannam@95: cerr << endl; cannam@95: cerr << " -V, --version Show version number and exit" << endl; cannam@95: cerr << " -h, --help Show this help" << endl; cannam@95: cerr << endl; cannam@95: cerr << "\"Crispness\" levels:" << endl; cannam@95: cerr << " -c 0 equivalent to --no-transients --no-lamination --window-long" << endl; cannam@95: cerr << " -c 1 equivalent to --detector-soft --no-lamination --window-long (for piano)" << endl; cannam@95: cerr << " -c 2 equivalent to --no-transients --no-lamination" << endl; cannam@95: cerr << " -c 3 equivalent to --no-transients" << endl; cannam@95: cerr << " -c 4 equivalent to --bl-transients" << endl; cannam@95: cerr << " -c 5 default processing options" << endl; cannam@95: cerr << " -c 6 equivalent to --no-lamination --window-short (may be good for drums)" << endl; cannam@95: cerr << endl; cannam@95: return 2; cannam@95: } cannam@95: cannam@95: if (crispness >= 0 && crispchanged) { cannam@95: cerr << "WARNING: Both crispness option and transients, lamination or window options" << endl; cannam@95: cerr << " provided -- crispness will override these other options" << endl; cannam@95: } cannam@95: cannam@95: switch (crispness) { cannam@95: case -1: crispness = 5; break; cannam@95: case 0: detector = CompoundDetector; transients = NoTransients; lamination = false; longwin = true; shortwin = false; break; cannam@95: case 1: detector = SoftDetector; transients = Transients; lamination = false; longwin = true; shortwin = false; break; cannam@95: case 2: detector = CompoundDetector; transients = NoTransients; lamination = false; longwin = false; shortwin = false; break; cannam@95: case 3: detector = CompoundDetector; transients = NoTransients; lamination = true; longwin = false; shortwin = false; break; cannam@95: case 4: detector = CompoundDetector; transients = BandLimitedTransients; lamination = true; longwin = false; shortwin = false; break; cannam@95: case 5: detector = CompoundDetector; transients = Transients; lamination = true; longwin = false; shortwin = false; break; cannam@95: case 6: detector = CompoundDetector; transients = Transients; lamination = false; longwin = false; shortwin = true; break; cannam@95: }; cannam@95: cannam@95: if (!quiet) { cannam@95: cerr << "Using crispness level: " << crispness << " ("; cannam@95: switch (crispness) { cannam@95: case 0: cerr << "Mushy"; break; cannam@95: case 1: cerr << "Piano"; break; cannam@95: case 2: cerr << "Smooth"; break; cannam@95: case 3: cerr << "Balanced multitimbral mixture"; break; cannam@95: case 4: cerr << "Unpitched percussion with stable notes"; break; cannam@95: case 5: cerr << "Crisp monophonic instrumental"; break; cannam@95: case 6: cerr << "Unpitched solo percussion"; break; cannam@95: } cannam@95: cerr << ")" << endl; cannam@95: } cannam@95: cannam@95: std::map mapping; cannam@95: cannam@95: if (mapfile != "") { cannam@95: std::ifstream ifile(mapfile.c_str()); cannam@95: if (!ifile.is_open()) { cannam@95: cerr << "ERROR: Failed to open time map file \"" << mapfile << "\"" cannam@95: << endl; cannam@95: return 1; cannam@95: } cannam@95: std::string line; cannam@95: int lineno = 0; cannam@95: while (!ifile.eof()) { cannam@95: std::getline(ifile, line); cannam@95: while (line.length() > 0 && line[0] == ' ') line = line.substr(1); cannam@95: if (line == "") { cannam@95: ++lineno; cannam@95: continue; cannam@95: } cannam@95: std::string::size_type i = line.find_first_of(" "); cannam@95: if (i == std::string::npos) { cannam@95: cerr << "ERROR: Time map file \"" << mapfile cannam@95: << "\" is malformed at line " << lineno << endl; cannam@95: return 1; cannam@95: } cannam@95: size_t source = atoi(line.substr(0, i).c_str()); cannam@95: while (i < line.length() && line[i] == ' ') ++i; cannam@95: size_t target = atoi(line.substr(i).c_str()); cannam@95: mapping[source] = target; cannam@95: if (debug > 0) { cannam@95: cerr << "adding mapping from " << source << " to " << target << endl; cannam@95: } cannam@95: ++lineno; cannam@95: } cannam@95: ifile.close(); cannam@95: cannam@95: if (!quiet) { cannam@95: cerr << "Read " << mapping.size() << " line(s) from map file" << endl; cannam@95: } cannam@95: } cannam@95: cannam@95: char *fileName = strdup(argv[optind++]); cannam@95: char *fileNameOut = strdup(argv[optind++]); cannam@95: cannam@95: SNDFILE *sndfile; cannam@95: SNDFILE *sndfileOut; cannam@95: SF_INFO sfinfo; cannam@95: SF_INFO sfinfoOut; cannam@95: memset(&sfinfo, 0, sizeof(SF_INFO)); cannam@95: cannam@95: sndfile = sf_open(fileName, SFM_READ, &sfinfo); cannam@95: if (!sndfile) { cannam@95: cerr << "ERROR: Failed to open input file \"" << fileName << "\": " cannam@95: << sf_strerror(sndfile) << endl; cannam@95: return 1; cannam@95: } cannam@95: cannam@95: if (duration != 0.0) { cannam@95: if (sfinfo.frames == 0 || sfinfo.samplerate == 0) { cannam@95: cerr << "ERROR: File lacks frame count or sample rate in header, cannot use --duration" << endl; cannam@95: return 1; cannam@95: } cannam@95: double induration = double(sfinfo.frames) / double(sfinfo.samplerate); cannam@95: if (induration != 0.0) ratio = duration / induration; cannam@95: } cannam@95: cannam@95: sfinfoOut.channels = sfinfo.channels; cannam@95: sfinfoOut.format = sfinfo.format; cannam@95: sfinfoOut.frames = int(sfinfo.frames * ratio + 0.1); cannam@95: sfinfoOut.samplerate = sfinfo.samplerate; cannam@95: sfinfoOut.sections = sfinfo.sections; cannam@95: sfinfoOut.seekable = sfinfo.seekable; cannam@95: cannam@95: sndfileOut = sf_open(fileNameOut, SFM_WRITE, &sfinfoOut) ; cannam@95: if (!sndfileOut) { cannam@95: cerr << "ERROR: Failed to open output file \"" << fileNameOut << "\" for writing: " cannam@95: << sf_strerror(sndfileOut) << endl; cannam@95: return 1; cannam@95: } cannam@95: cannam@95: int ibs = 1024; cannam@95: size_t channels = sfinfo.channels; cannam@95: cannam@95: RubberBandStretcher::Options options = 0; cannam@95: if (realtime) options |= RubberBandStretcher::OptionProcessRealTime; cannam@95: if (precise) options |= RubberBandStretcher::OptionStretchPrecise; cannam@95: if (!lamination) options |= RubberBandStretcher::OptionPhaseIndependent; cannam@95: if (longwin) options |= RubberBandStretcher::OptionWindowLong; cannam@95: if (shortwin) options |= RubberBandStretcher::OptionWindowShort; cannam@95: if (smoothing) options |= RubberBandStretcher::OptionSmoothingOn; cannam@95: if (formant) options |= RubberBandStretcher::OptionFormantPreserved; cannam@95: if (hqpitch) options |= RubberBandStretcher::OptionPitchHighQuality; cannam@95: if (together) options |= RubberBandStretcher::OptionChannelsTogether; cannam@95: cannam@95: switch (threading) { cannam@95: case 0: cannam@95: options |= RubberBandStretcher::OptionThreadingAuto; cannam@95: break; cannam@95: case 1: cannam@95: options |= RubberBandStretcher::OptionThreadingNever; cannam@95: break; cannam@95: case 2: cannam@95: options |= RubberBandStretcher::OptionThreadingAlways; cannam@95: break; cannam@95: } cannam@95: cannam@95: switch (transients) { cannam@95: case NoTransients: cannam@95: options |= RubberBandStretcher::OptionTransientsSmooth; cannam@95: break; cannam@95: case BandLimitedTransients: cannam@95: options |= RubberBandStretcher::OptionTransientsMixed; cannam@95: break; cannam@95: case Transients: cannam@95: options |= RubberBandStretcher::OptionTransientsCrisp; cannam@95: break; cannam@95: } cannam@95: cannam@95: switch (detector) { cannam@95: case CompoundDetector: cannam@95: options |= RubberBandStretcher::OptionDetectorCompound; cannam@95: break; cannam@95: case PercussiveDetector: cannam@95: options |= RubberBandStretcher::OptionDetectorPercussive; cannam@95: break; cannam@95: case SoftDetector: cannam@95: options |= RubberBandStretcher::OptionDetectorSoft; cannam@95: break; cannam@95: } cannam@95: cannam@95: if (pitchshift != 0.0) { cannam@95: frequencyshift *= pow(2.0, pitchshift / 12); cannam@95: } cannam@95: cannam@95: cerr << "Using time ratio " << ratio; cannam@95: cerr << " and frequency ratio " << frequencyshift << endl; cannam@95: cannam@95: #ifdef _WIN32 cannam@95: RubberBand:: cannam@95: #endif cannam@95: timeval tv; cannam@95: (void)gettimeofday(&tv, 0); cannam@95: cannam@95: RubberBandStretcher::setDefaultDebugLevel(debug); cannam@95: cannam@95: RubberBandStretcher ts(sfinfo.samplerate, channels, options, cannam@95: ratio, frequencyshift); cannam@95: cannam@95: ts.setExpectedInputDuration(sfinfo.frames); cannam@95: cannam@95: float *fbuf = new float[channels * ibs]; cannam@95: float **ibuf = new float *[channels]; cannam@95: for (size_t i = 0; i < channels; ++i) ibuf[i] = new float[ibs]; cannam@95: cannam@95: int frame = 0; cannam@95: int percent = 0; cannam@95: cannam@95: sf_seek(sndfile, 0, SEEK_SET); cannam@95: cannam@95: if (!realtime) { cannam@95: cannam@95: if (!quiet) { cannam@95: cerr << "Pass 1: Studying..." << endl; cannam@95: } cannam@95: cannam@95: while (frame < sfinfo.frames) { cannam@95: cannam@95: int count = -1; cannam@95: cannam@95: if ((count = sf_readf_float(sndfile, fbuf, ibs)) <= 0) break; cannam@95: cannam@95: for (size_t c = 0; c < channels; ++c) { cannam@95: for (int i = 0; i < count; ++i) { cannam@95: float value = fbuf[i * channels + c]; cannam@95: ibuf[c][i] = value; cannam@95: } cannam@95: } cannam@95: cannam@95: bool final = (frame + ibs >= sfinfo.frames); cannam@95: cannam@95: ts.study(ibuf, count, final); cannam@95: cannam@95: int p = int((double(frame) * 100.0) / sfinfo.frames); cannam@95: if (p > percent || frame == 0) { cannam@95: percent = p; cannam@95: if (!quiet) { cannam@95: cerr << "\r" << percent << "% "; cannam@95: } cannam@95: } cannam@95: cannam@95: frame += ibs; cannam@95: } cannam@95: cannam@95: if (!quiet) { cannam@95: cerr << "\rCalculating profile..." << endl; cannam@95: } cannam@95: cannam@95: sf_seek(sndfile, 0, SEEK_SET); cannam@95: } cannam@95: cannam@95: frame = 0; cannam@95: percent = 0; cannam@95: cannam@95: if (!mapping.empty()) { cannam@95: ts.setKeyFrameMap(mapping); cannam@95: } cannam@95: cannam@95: size_t countIn = 0, countOut = 0; cannam@95: cannam@95: while (frame < sfinfo.frames) { cannam@95: cannam@95: int count = -1; cannam@95: cannam@95: if ((count = sf_readf_float(sndfile, fbuf, ibs)) < 0) break; cannam@95: cannam@95: countIn += count; cannam@95: cannam@95: for (size_t c = 0; c < channels; ++c) { cannam@95: for (int i = 0; i < count; ++i) { cannam@95: float value = fbuf[i * channels + c]; cannam@95: ibuf[c][i] = value; cannam@95: } cannam@95: } cannam@95: cannam@95: bool final = (frame + ibs >= sfinfo.frames); cannam@95: cannam@95: if (debug > 2) { cannam@95: cerr << "count = " << count << ", ibs = " << ibs << ", frame = " << frame << ", frames = " << sfinfo.frames << ", final = " << final << endl; cannam@95: } cannam@95: cannam@95: ts.process(ibuf, count, final); cannam@95: cannam@95: int avail = ts.available(); cannam@95: if (debug > 1) cerr << "available = " << avail << endl; cannam@95: cannam@95: if (avail > 0) { cannam@95: float **obf = new float *[channels]; cannam@95: for (size_t i = 0; i < channels; ++i) { cannam@95: obf[i] = new float[avail]; cannam@95: } cannam@95: ts.retrieve(obf, avail); cannam@95: countOut += avail; cannam@95: float *fobf = new float[channels * avail]; cannam@95: for (size_t c = 0; c < channels; ++c) { cannam@95: for (int i = 0; i < avail; ++i) { cannam@95: float value = obf[c][i]; cannam@95: if (value > 1.f) value = 1.f; cannam@95: if (value < -1.f) value = -1.f; cannam@95: fobf[i * channels + c] = value; cannam@95: } cannam@95: } cannam@95: // cout << "fobf mean: "; cannam@95: // double d = 0; cannam@95: // for (int i = 0; i < avail; ++i) { cannam@95: // d += fobf[i]; cannam@95: // } cannam@95: // d /= avail; cannam@95: // cout << d << endl; cannam@95: sf_writef_float(sndfileOut, fobf, avail); cannam@95: delete[] fobf; cannam@95: for (size_t i = 0; i < channels; ++i) { cannam@95: delete[] obf[i]; cannam@95: } cannam@95: delete[] obf; cannam@95: } cannam@95: cannam@95: if (frame == 0 && !realtime && !quiet) { cannam@95: cerr << "Pass 2: Processing..." << endl; cannam@95: } cannam@95: cannam@95: int p = int((double(frame) * 100.0) / sfinfo.frames); cannam@95: if (p > percent || frame == 0) { cannam@95: percent = p; cannam@95: if (!quiet) { cannam@95: cerr << "\r" << percent << "% "; cannam@95: } cannam@95: } cannam@95: cannam@95: frame += ibs; cannam@95: } cannam@95: cannam@95: if (!quiet) { cannam@95: cerr << "\r " << endl; cannam@95: } cannam@95: int avail; cannam@95: cannam@95: while ((avail = ts.available()) >= 0) { cannam@95: cannam@95: if (debug > 1) { cannam@95: cerr << "(completing) available = " << avail << endl; cannam@95: } cannam@95: cannam@95: if (avail > 0) { cannam@95: float **obf = new float *[channels]; cannam@95: for (size_t i = 0; i < channels; ++i) { cannam@95: obf[i] = new float[avail]; cannam@95: } cannam@95: ts.retrieve(obf, avail); cannam@95: countOut += avail; cannam@95: float *fobf = new float[channels * avail]; cannam@95: for (size_t c = 0; c < channels; ++c) { cannam@95: for (int i = 0; i < avail; ++i) { cannam@95: float value = obf[c][i]; cannam@95: if (value > 1.f) value = 1.f; cannam@95: if (value < -1.f) value = -1.f; cannam@95: fobf[i * channels + c] = value; cannam@95: } cannam@95: } cannam@95: cannam@95: sf_writef_float(sndfileOut, fobf, avail); cannam@95: delete[] fobf; cannam@95: for (size_t i = 0; i < channels; ++i) { cannam@95: delete[] obf[i]; cannam@95: } cannam@95: delete[] obf; cannam@95: } else { cannam@95: usleep(10000); cannam@95: } cannam@95: } cannam@95: cannam@95: sf_close(sndfile); cannam@95: sf_close(sndfileOut); cannam@95: cannam@95: if (!quiet) { cannam@95: cannam@95: 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: cannam@95: #ifdef _WIN32 cannam@95: RubberBand:: cannam@95: #endif cannam@95: timeval etv; cannam@95: (void)gettimeofday(&etv, 0); cannam@95: cannam@95: etv.tv_sec -= tv.tv_sec; cannam@95: if (etv.tv_usec < tv.tv_usec) { cannam@95: etv.tv_usec += 1000000; cannam@95: etv.tv_sec -= 1; cannam@95: } cannam@95: etv.tv_usec -= tv.tv_usec; cannam@95: cannam@95: double sec = double(etv.tv_sec) + (double(etv.tv_usec) / 1000000.0); cannam@95: cerr << "elapsed time: " << sec << " sec, in frames/sec: " << countIn/sec << ", out frames/sec: " << countOut/sec << endl; cannam@95: } cannam@95: cannam@95: RubberBand::Profiler::dump(); cannam@95: cannam@95: return 0; cannam@95: } cannam@95: cannam@95: