annotate osx/include/rubberband/RubberBandStretcher.h @ 168:ceec0dd9ec9c

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 <cannam@all-day-breakfast.com>
date Fri, 07 Feb 2020 11:51:13 +0000
parents 241db1b1eff2
children
rev   line source
matthiasmauch@114 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
matthiasmauch@114 2
matthiasmauch@114 3 /*
matthiasmauch@114 4 Rubber Band Library
matthiasmauch@114 5 An audio time-stretching and pitch-shifting library.
matthiasmauch@114 6 Copyright 2007-2012 Particular Programs Ltd.
matthiasmauch@114 7
matthiasmauch@114 8 This program is free software; you can redistribute it and/or
matthiasmauch@114 9 modify it under the terms of the GNU General Public License as
matthiasmauch@114 10 published by the Free Software Foundation; either version 2 of the
matthiasmauch@114 11 License, or (at your option) any later version. See the file
matthiasmauch@114 12 COPYING included with this distribution for more information.
matthiasmauch@114 13
matthiasmauch@114 14 Alternatively, if you have a valid commercial licence for the
matthiasmauch@114 15 Rubber Band Library obtained by agreement with the copyright
matthiasmauch@114 16 holders, you may redistribute and/or modify it under the terms
matthiasmauch@114 17 described in that licence.
matthiasmauch@114 18
matthiasmauch@114 19 If you wish to distribute code using the Rubber Band Library
matthiasmauch@114 20 under terms other than those of the GNU General Public License,
matthiasmauch@114 21 you must obtain a valid commercial licence before doing so.
matthiasmauch@114 22 */
matthiasmauch@114 23
matthiasmauch@114 24 #ifndef _RUBBERBANDSTRETCHER_H_
matthiasmauch@114 25 #define _RUBBERBANDSTRETCHER_H_
matthiasmauch@114 26
matthiasmauch@114 27 #define RUBBERBAND_VERSION "1.8.1"
matthiasmauch@114 28 #define RUBBERBAND_API_MAJOR_VERSION 2
matthiasmauch@114 29 #define RUBBERBAND_API_MINOR_VERSION 5
matthiasmauch@114 30
matthiasmauch@114 31 #include <vector>
matthiasmauch@114 32 #include <map>
matthiasmauch@114 33 #include <cstddef>
matthiasmauch@114 34
matthiasmauch@114 35 /**
matthiasmauch@114 36 * @mainpage RubberBand
matthiasmauch@114 37 *
matthiasmauch@114 38 * The Rubber Band API is contained in the single class
matthiasmauch@114 39 * RubberBand::RubberBandStretcher.
matthiasmauch@114 40 *
matthiasmauch@114 41 * Threading notes for real-time applications:
matthiasmauch@114 42 *
matthiasmauch@114 43 * Multiple instances of RubberBandStretcher may be created and used
matthiasmauch@114 44 * in separate threads concurrently. However, for any single instance
matthiasmauch@114 45 * of RubberBandStretcher, you may not call process() more than once
matthiasmauch@114 46 * concurrently, and you may not change the time or pitch ratio while
matthiasmauch@114 47 * a process() call is being executed (if the stretcher was created in
matthiasmauch@114 48 * "real-time mode"; in "offline mode" you can't change the ratios
matthiasmauch@114 49 * during use anyway).
matthiasmauch@114 50 *
matthiasmauch@114 51 * So you can run process() in its own thread if you like, but if you
matthiasmauch@114 52 * want to change ratios dynamically from a different thread, you will
matthiasmauch@114 53 * need some form of mutex in your code. Changing the time or pitch
matthiasmauch@114 54 * ratio is real-time safe except in extreme circumstances, so for
matthiasmauch@114 55 * most applications that may change these dynamically it probably
matthiasmauch@114 56 * makes most sense to do so from the same thread as calls process(),
matthiasmauch@114 57 * even if that is a real-time thread.
matthiasmauch@114 58 */
matthiasmauch@114 59
matthiasmauch@114 60 namespace RubberBand
matthiasmauch@114 61 {
matthiasmauch@114 62
matthiasmauch@114 63 class RubberBandStretcher
matthiasmauch@114 64 {
matthiasmauch@114 65 public:
matthiasmauch@114 66 /**
matthiasmauch@114 67 * Processing options for the timestretcher. The preferred
matthiasmauch@114 68 * options should normally be set in the constructor, as a bitwise
matthiasmauch@114 69 * OR of the option flags. The default value (DefaultOptions) is
matthiasmauch@114 70 * intended to give good results in most situations.
matthiasmauch@114 71 *
matthiasmauch@114 72 * 1. Flags prefixed \c OptionProcess determine how the timestretcher
matthiasmauch@114 73 * will be invoked. These options may not be changed after
matthiasmauch@114 74 * construction.
matthiasmauch@114 75 *
matthiasmauch@114 76 * \li \c OptionProcessOffline - Run the stretcher in offline
matthiasmauch@114 77 * mode. In this mode the input data needs to be provided
matthiasmauch@114 78 * twice, once to study(), which calculates a stretch profile
matthiasmauch@114 79 * for the audio, and once to process(), which stretches it.
matthiasmauch@114 80 *
matthiasmauch@114 81 * \li \c OptionProcessRealTime - Run the stretcher in real-time
matthiasmauch@114 82 * mode. In this mode only process() should be called, and the
matthiasmauch@114 83 * stretcher adjusts dynamically in response to the input audio.
matthiasmauch@114 84 *
matthiasmauch@114 85 * The Process setting is likely to depend on your architecture:
matthiasmauch@114 86 * non-real-time operation on seekable files: Offline; real-time
matthiasmauch@114 87 * or streaming operation: RealTime.
matthiasmauch@114 88 *
matthiasmauch@114 89 * 2. Flags prefixed \c OptionStretch control the profile used for
matthiasmauch@114 90 * variable timestretching. Rubber Band always adjusts the
matthiasmauch@114 91 * stretch profile to minimise stretching of busy broadband
matthiasmauch@114 92 * transient sounds, but the degree to which it does so is
matthiasmauch@114 93 * adjustable. These options may not be changed after
matthiasmauch@114 94 * construction.
matthiasmauch@114 95 *
matthiasmauch@114 96 * \li \c OptionStretchElastic - Only meaningful in offline
matthiasmauch@114 97 * mode, and the default in that mode. The audio will be
matthiasmauch@114 98 * stretched at a variable rate, aimed at preserving the quality
matthiasmauch@114 99 * of transient sounds as much as possible. The timings of low
matthiasmauch@114 100 * activity regions between transients may be less exact than
matthiasmauch@114 101 * when the precise flag is set.
matthiasmauch@114 102 *
matthiasmauch@114 103 * \li \c OptionStretchPrecise - Although still using a variable
matthiasmauch@114 104 * stretch rate, the audio will be stretched so as to maintain
matthiasmauch@114 105 * as close as possible to a linear stretch ratio throughout.
matthiasmauch@114 106 * Timing may be better than when using \c OptionStretchElastic, at
matthiasmauch@114 107 * slight cost to the sound quality of transients. This setting
matthiasmauch@114 108 * is always used when running in real-time mode.
matthiasmauch@114 109 *
matthiasmauch@114 110 * 3. Flags prefixed \c OptionTransients control the component
matthiasmauch@114 111 * frequency phase-reset mechanism that may be used at transient
matthiasmauch@114 112 * points to provide clarity and realism to percussion and other
matthiasmauch@114 113 * significant transient sounds. These options may be changed
matthiasmauch@114 114 * after construction when running in real-time mode, but not when
matthiasmauch@114 115 * running in offline mode.
matthiasmauch@114 116 *
matthiasmauch@114 117 * \li \c OptionTransientsCrisp - Reset component phases at the
matthiasmauch@114 118 * peak of each transient (the start of a significant note or
matthiasmauch@114 119 * percussive event). This, the default setting, usually
matthiasmauch@114 120 * results in a clear-sounding output; but it is not always
matthiasmauch@114 121 * consistent, and may cause interruptions in stable sounds
matthiasmauch@114 122 * present at the same time as transient events. The
matthiasmauch@114 123 * OptionDetector flags (below) can be used to tune this to some
matthiasmauch@114 124 * extent.
matthiasmauch@114 125 *
matthiasmauch@114 126 * \li \c OptionTransientsMixed - Reset component phases at the
matthiasmauch@114 127 * peak of each transient, outside a frequency range typical of
matthiasmauch@114 128 * musical fundamental frequencies. The results may be more
matthiasmauch@114 129 * regular for mixed stable and percussive notes than
matthiasmauch@114 130 * \c OptionTransientsCrisp, but with a "phasier" sound. The
matthiasmauch@114 131 * balance may sound very good for certain types of music and
matthiasmauch@114 132 * fairly bad for others.
matthiasmauch@114 133 *
matthiasmauch@114 134 * \li \c OptionTransientsSmooth - Do not reset component phases
matthiasmauch@114 135 * at any point. The results will be smoother and more regular
matthiasmauch@114 136 * but may be less clear than with either of the other
matthiasmauch@114 137 * transients flags.
matthiasmauch@114 138 *
matthiasmauch@114 139 * 4. Flags prefixed \c OptionDetector control the type of
matthiasmauch@114 140 * transient detector used. These options may be changed
matthiasmauch@114 141 * after construction when running in real-time mode, but not when
matthiasmauch@114 142 * running in offline mode.
matthiasmauch@114 143 *
matthiasmauch@114 144 * \li \c OptionDetectorCompound - Use a general-purpose
matthiasmauch@114 145 * transient detector which is likely to be good for most
matthiasmauch@114 146 * situations. This is the default.
matthiasmauch@114 147 *
matthiasmauch@114 148 * \li \c OptionDetectorPercussive - Detect percussive
matthiasmauch@114 149 * transients. Note that this was the default and only option
matthiasmauch@114 150 * in Rubber Band versions prior to 1.5.
matthiasmauch@114 151 *
matthiasmauch@114 152 * \li \c OptionDetectorSoft - Use an onset detector with less
matthiasmauch@114 153 * of a bias toward percussive transients. This may give better
matthiasmauch@114 154 * results with certain material (e.g. relatively monophonic
matthiasmauch@114 155 * piano music).
matthiasmauch@114 156 *
matthiasmauch@114 157 * 5. Flags prefixed \c OptionPhase control the adjustment of
matthiasmauch@114 158 * component frequency phases from one analysis window to the next
matthiasmauch@114 159 * during non-transient segments. These options may be changed at
matthiasmauch@114 160 * any time.
matthiasmauch@114 161 *
matthiasmauch@114 162 * \li \c OptionPhaseLaminar - Adjust phases when stretching in
matthiasmauch@114 163 * such a way as to try to retain the continuity of phase
matthiasmauch@114 164 * relationships between adjacent frequency bins whose phases
matthiasmauch@114 165 * are behaving in similar ways. This, the default setting,
matthiasmauch@114 166 * should give good results in most situations.
matthiasmauch@114 167 *
matthiasmauch@114 168 * \li \c OptionPhaseIndependent - Adjust the phase in each
matthiasmauch@114 169 * frequency bin independently from its neighbours. This
matthiasmauch@114 170 * usually results in a slightly softer, phasier sound.
matthiasmauch@114 171 *
matthiasmauch@114 172 * 6. Flags prefixed \c OptionThreading control the threading
matthiasmauch@114 173 * model of the stretcher. These options may not be changed after
matthiasmauch@114 174 * construction.
matthiasmauch@114 175 *
matthiasmauch@114 176 * \li \c OptionThreadingAuto - Permit the stretcher to
matthiasmauch@114 177 * determine its own threading model. Usually this means using
matthiasmauch@114 178 * one processing thread per audio channel in offline mode if
matthiasmauch@114 179 * the stretcher is able to determine that more than one CPU is
matthiasmauch@114 180 * available, and one thread only in realtime mode. This is the
matthiasmauch@114 181 * defafult.
matthiasmauch@114 182 *
matthiasmauch@114 183 * \li \c OptionThreadingNever - Never use more than one thread.
matthiasmauch@114 184 *
matthiasmauch@114 185 * \li \c OptionThreadingAlways - Use multiple threads in any
matthiasmauch@114 186 * situation where \c OptionThreadingAuto would do so, except omit
matthiasmauch@114 187 * the check for multiple CPUs and instead assume it to be true.
matthiasmauch@114 188 *
matthiasmauch@114 189 * 7. Flags prefixed \c OptionWindow control the window size for
matthiasmauch@114 190 * FFT processing. The window size actually used will depend on
matthiasmauch@114 191 * many factors, but it can be influenced. These options may not
matthiasmauch@114 192 * be changed after construction.
matthiasmauch@114 193 *
matthiasmauch@114 194 * \li \c OptionWindowStandard - Use the default window size.
matthiasmauch@114 195 * The actual size will vary depending on other parameters.
matthiasmauch@114 196 * This option is expected to produce better results than the
matthiasmauch@114 197 * other window options in most situations.
matthiasmauch@114 198 *
matthiasmauch@114 199 * \li \c OptionWindowShort - Use a shorter window. This may
matthiasmauch@114 200 * result in crisper sound for audio that depends strongly on
matthiasmauch@114 201 * its timing qualities.
matthiasmauch@114 202 *
matthiasmauch@114 203 * \li \c OptionWindowLong - Use a longer window. This is
matthiasmauch@114 204 * likely to result in a smoother sound at the expense of
matthiasmauch@114 205 * clarity and timing.
matthiasmauch@114 206 *
matthiasmauch@114 207 * 8. Flags prefixed \c OptionSmoothing control the use of
matthiasmauch@114 208 * window-presum FFT and time-domain smoothing. These options may
matthiasmauch@114 209 * not be changed after construction.
matthiasmauch@114 210 *
matthiasmauch@114 211 * \li \c OptionSmoothingOff - Do not use time-domain smoothing.
matthiasmauch@114 212 * This is the default.
matthiasmauch@114 213 *
matthiasmauch@114 214 * \li \c OptionSmoothingOn - Use time-domain smoothing. This
matthiasmauch@114 215 * will result in a softer sound with some audible artifacts
matthiasmauch@114 216 * around sharp transients, but it may be appropriate for longer
matthiasmauch@114 217 * stretches of some instruments and can mix well with
matthiasmauch@114 218 * OptionWindowShort.
matthiasmauch@114 219 *
matthiasmauch@114 220 * 9. Flags prefixed \c OptionFormant control the handling of
matthiasmauch@114 221 * formant shape (spectral envelope) when pitch-shifting. These
matthiasmauch@114 222 * options may be changed at any time.
matthiasmauch@114 223 *
matthiasmauch@114 224 * \li \c OptionFormantShifted - Apply no special formant
matthiasmauch@114 225 * processing. The spectral envelope will be pitch shifted as
matthiasmauch@114 226 * normal. This is the default.
matthiasmauch@114 227 *
matthiasmauch@114 228 * \li \c OptionFormantPreserved - Preserve the spectral
matthiasmauch@114 229 * envelope of the unshifted signal. This permits shifting the
matthiasmauch@114 230 * note frequency without so substantially affecting the
matthiasmauch@114 231 * perceived pitch profile of the voice or instrument.
matthiasmauch@114 232 *
matthiasmauch@114 233 * 10. Flags prefixed \c OptionPitch control the method used for
matthiasmauch@114 234 * pitch shifting. These options may be changed at any time.
matthiasmauch@114 235 * They are only effective in realtime mode; in offline mode, the
matthiasmauch@114 236 * pitch-shift method is fixed.
matthiasmauch@114 237 *
matthiasmauch@114 238 * \li \c OptionPitchHighSpeed - Use a method with a CPU cost
matthiasmauch@114 239 * that is relatively moderate and predictable. This may
matthiasmauch@114 240 * sound less clear than OptionPitchHighQuality, especially
matthiasmauch@114 241 * for large pitch shifts. This is the default.
matthiasmauch@114 242
matthiasmauch@114 243 * \li \c OptionPitchHighQuality - Use the highest quality
matthiasmauch@114 244 * method for pitch shifting. This method has a CPU cost
matthiasmauch@114 245 * approximately proportional to the required frequency shift.
matthiasmauch@114 246
matthiasmauch@114 247 * \li \c OptionPitchHighConsistency - Use the method that gives
matthiasmauch@114 248 * greatest consistency when used to create small variations in
matthiasmauch@114 249 * pitch around the 1.0-ratio level. Unlike the previous two
matthiasmauch@114 250 * options, this avoids discontinuities when moving across the
matthiasmauch@114 251 * 1.0 pitch scale in real-time; it also consumes more CPU than
matthiasmauch@114 252 * the others in the case where the pitch scale is exactly 1.0.
matthiasmauch@114 253 *
matthiasmauch@114 254 * 11. Flags prefixed \c OptionChannels control the method used for
matthiasmauch@114 255 * processing two-channel audio. These options may not be changed
matthiasmauch@114 256 * after construction.
matthiasmauch@114 257 *
matthiasmauch@114 258 * \li \c OptionChannelsApart - Each channel is processed
matthiasmauch@114 259 * individually, though timing is synchronised and phases are
matthiasmauch@114 260 * synchronised at transients (depending on the OptionTransients
matthiasmauch@114 261 * setting). This gives the highest quality for the individual
matthiasmauch@114 262 * channels but a relative lack of stereo focus and unrealistic
matthiasmauch@114 263 * increase in "width". This is the default.
matthiasmauch@114 264 *
matthiasmauch@114 265 * \li \c OptionChannelsTogether - The first two channels (where
matthiasmauch@114 266 * two or more are present) are considered to be a stereo pair
matthiasmauch@114 267 * and are processed in mid-side format; mid and side are
matthiasmauch@114 268 * processed individually, with timing synchronised and phases
matthiasmauch@114 269 * synchronised at transients (depending on the OptionTransients
matthiasmauch@114 270 * setting). This usually leads to better focus in the centre
matthiasmauch@114 271 * but a loss of stereo space and width. Any channels beyond
matthiasmauch@114 272 * the first two are processed individually.
matthiasmauch@114 273 */
matthiasmauch@114 274
matthiasmauch@114 275 enum Option {
matthiasmauch@114 276
matthiasmauch@114 277 OptionProcessOffline = 0x00000000,
matthiasmauch@114 278 OptionProcessRealTime = 0x00000001,
matthiasmauch@114 279
matthiasmauch@114 280 OptionStretchElastic = 0x00000000,
matthiasmauch@114 281 OptionStretchPrecise = 0x00000010,
matthiasmauch@114 282
matthiasmauch@114 283 OptionTransientsCrisp = 0x00000000,
matthiasmauch@114 284 OptionTransientsMixed = 0x00000100,
matthiasmauch@114 285 OptionTransientsSmooth = 0x00000200,
matthiasmauch@114 286
matthiasmauch@114 287 OptionDetectorCompound = 0x00000000,
matthiasmauch@114 288 OptionDetectorPercussive = 0x00000400,
matthiasmauch@114 289 OptionDetectorSoft = 0x00000800,
matthiasmauch@114 290
matthiasmauch@114 291 OptionPhaseLaminar = 0x00000000,
matthiasmauch@114 292 OptionPhaseIndependent = 0x00002000,
matthiasmauch@114 293
matthiasmauch@114 294 OptionThreadingAuto = 0x00000000,
matthiasmauch@114 295 OptionThreadingNever = 0x00010000,
matthiasmauch@114 296 OptionThreadingAlways = 0x00020000,
matthiasmauch@114 297
matthiasmauch@114 298 OptionWindowStandard = 0x00000000,
matthiasmauch@114 299 OptionWindowShort = 0x00100000,
matthiasmauch@114 300 OptionWindowLong = 0x00200000,
matthiasmauch@114 301
matthiasmauch@114 302 OptionSmoothingOff = 0x00000000,
matthiasmauch@114 303 OptionSmoothingOn = 0x00800000,
matthiasmauch@114 304
matthiasmauch@114 305 OptionFormantShifted = 0x00000000,
matthiasmauch@114 306 OptionFormantPreserved = 0x01000000,
matthiasmauch@114 307
matthiasmauch@114 308 OptionPitchHighSpeed = 0x00000000,
matthiasmauch@114 309 OptionPitchHighQuality = 0x02000000,
matthiasmauch@114 310 OptionPitchHighConsistency = 0x04000000,
matthiasmauch@114 311
matthiasmauch@114 312 OptionChannelsApart = 0x00000000,
matthiasmauch@114 313 OptionChannelsTogether = 0x10000000,
matthiasmauch@114 314
matthiasmauch@114 315 // n.b. Options is int, so we must stop before 0x80000000
matthiasmauch@114 316 };
matthiasmauch@114 317
matthiasmauch@114 318 typedef int Options;
matthiasmauch@114 319
matthiasmauch@114 320 enum PresetOption {
matthiasmauch@114 321 DefaultOptions = 0x00000000,
matthiasmauch@114 322 PercussiveOptions = 0x00102000
matthiasmauch@114 323 };
matthiasmauch@114 324
matthiasmauch@114 325 /**
matthiasmauch@114 326 * Construct a time and pitch stretcher object to run at the given
matthiasmauch@114 327 * sample rate, with the given number of channels. Processing
matthiasmauch@114 328 * options and the time and pitch scaling ratios may be provided.
matthiasmauch@114 329 * The time and pitch ratios may be changed after construction,
matthiasmauch@114 330 * but most of the options may not. See the option documentation
matthiasmauch@114 331 * above for more details.
matthiasmauch@114 332 */
matthiasmauch@114 333 RubberBandStretcher(size_t sampleRate,
matthiasmauch@114 334 size_t channels,
matthiasmauch@114 335 Options options = DefaultOptions,
matthiasmauch@114 336 double initialTimeRatio = 1.0,
matthiasmauch@114 337 double initialPitchScale = 1.0);
matthiasmauch@114 338 ~RubberBandStretcher();
matthiasmauch@114 339
matthiasmauch@114 340 /**
matthiasmauch@114 341 * Reset the stretcher's internal buffers. The stretcher should
matthiasmauch@114 342 * subsequently behave as if it had just been constructed
matthiasmauch@114 343 * (although retaining the current time and pitch ratio).
matthiasmauch@114 344 */
matthiasmauch@114 345 void reset();
matthiasmauch@114 346
matthiasmauch@114 347 /**
matthiasmauch@114 348 * Set the time ratio for the stretcher. This is the ratio of
matthiasmauch@114 349 * stretched to unstretched duration -- not tempo. For example, a
matthiasmauch@114 350 * ratio of 2.0 would make the audio twice as long (i.e. halve the
matthiasmauch@114 351 * tempo); 0.5 would make it half as long (i.e. double the tempo);
matthiasmauch@114 352 * 1.0 would leave the duration unaffected.
matthiasmauch@114 353 *
matthiasmauch@114 354 * If the stretcher was constructed in Offline mode, the time
matthiasmauch@114 355 * ratio is fixed throughout operation; this function may be
matthiasmauch@114 356 * called any number of times between construction (or a call to
matthiasmauch@114 357 * reset()) and the first call to study() or process(), but may
matthiasmauch@114 358 * not be called after study() or process() has been called.
matthiasmauch@114 359 *
matthiasmauch@114 360 * If the stretcher was constructed in RealTime mode, the time
matthiasmauch@114 361 * ratio may be varied during operation; this function may be
matthiasmauch@114 362 * called at any time, so long as it is not called concurrently
matthiasmauch@114 363 * with process(). You should either call this function from the
matthiasmauch@114 364 * same thread as process(), or provide your own mutex or similar
matthiasmauch@114 365 * mechanism to ensure that setTimeRatio and process() cannot be
matthiasmauch@114 366 * run at once (there is no internal mutex for this purpose).
matthiasmauch@114 367 */
matthiasmauch@114 368 void setTimeRatio(double ratio);
matthiasmauch@114 369
matthiasmauch@114 370 /**
matthiasmauch@114 371 * Set the pitch scaling ratio for the stretcher. This is the
matthiasmauch@114 372 * ratio of target frequency to source frequency. For example, a
matthiasmauch@114 373 * ratio of 2.0 would shift up by one octave; 0.5 down by one
matthiasmauch@114 374 * octave; or 1.0 leave the pitch unaffected.
matthiasmauch@114 375 *
matthiasmauch@114 376 * To put this in musical terms, a pitch scaling ratio
matthiasmauch@114 377 * corresponding to a shift of S equal-tempered semitones (where S
matthiasmauch@114 378 * is positive for an upwards shift and negative for downwards) is
matthiasmauch@114 379 * pow(2.0, S / 12.0).
matthiasmauch@114 380 *
matthiasmauch@114 381 * If the stretcher was constructed in Offline mode, the pitch
matthiasmauch@114 382 * scaling ratio is fixed throughout operation; this function may
matthiasmauch@114 383 * be called any number of times between construction (or a call
matthiasmauch@114 384 * to reset()) and the first call to study() or process(), but may
matthiasmauch@114 385 * not be called after study() or process() has been called.
matthiasmauch@114 386 *
matthiasmauch@114 387 * If the stretcher was constructed in RealTime mode, the pitch
matthiasmauch@114 388 * scaling ratio may be varied during operation; this function may
matthiasmauch@114 389 * be called at any time, so long as it is not called concurrently
matthiasmauch@114 390 * with process(). You should either call this function from the
matthiasmauch@114 391 * same thread as process(), or provide your own mutex or similar
matthiasmauch@114 392 * mechanism to ensure that setPitchScale and process() cannot be
matthiasmauch@114 393 * run at once (there is no internal mutex for this purpose).
matthiasmauch@114 394 */
matthiasmauch@114 395 void setPitchScale(double scale);
matthiasmauch@114 396
matthiasmauch@114 397 /**
matthiasmauch@114 398 * Return the last time ratio value that was set (either on
matthiasmauch@114 399 * construction or with setTimeRatio()).
matthiasmauch@114 400 */
matthiasmauch@114 401 double getTimeRatio() const;
matthiasmauch@114 402
matthiasmauch@114 403 /**
matthiasmauch@114 404 * Return the last pitch scaling ratio value that was set (either
matthiasmauch@114 405 * on construction or with setPitchScale()).
matthiasmauch@114 406 */
matthiasmauch@114 407 double getPitchScale() const;
matthiasmauch@114 408
matthiasmauch@114 409 /**
matthiasmauch@114 410 * Return the processing latency of the stretcher. This is the
matthiasmauch@114 411 * number of audio samples that one would have to discard at the
matthiasmauch@114 412 * start of the output in order to ensure that the resulting audio
matthiasmauch@114 413 * aligned with the input audio at the start. In Offline mode,
matthiasmauch@114 414 * latency is automatically adjusted for and the result is zero.
matthiasmauch@114 415 * In RealTime mode, the latency may depend on the time and pitch
matthiasmauch@114 416 * ratio and other options.
matthiasmauch@114 417 */
matthiasmauch@114 418 size_t getLatency() const;
matthiasmauch@114 419
matthiasmauch@114 420 /**
matthiasmauch@114 421 * Change an OptionTransients configuration setting. This may be
matthiasmauch@114 422 * called at any time in RealTime mode. It may not be called in
matthiasmauch@114 423 * Offline mode (for which the transients option is fixed on
matthiasmauch@114 424 * construction).
matthiasmauch@114 425 */
matthiasmauch@114 426 void setTransientsOption(Options options);
matthiasmauch@114 427
matthiasmauch@114 428 /**
matthiasmauch@114 429 * Change an OptionDetector configuration setting. This may be
matthiasmauch@114 430 * called at any time in RealTime mode. It may not be called in
matthiasmauch@114 431 * Offline mode (for which the detector option is fixed on
matthiasmauch@114 432 * construction).
matthiasmauch@114 433 */
matthiasmauch@114 434 void setDetectorOption(Options options);
matthiasmauch@114 435
matthiasmauch@114 436 /**
matthiasmauch@114 437 * Change an OptionPhase configuration setting. This may be
matthiasmauch@114 438 * called at any time in any mode.
matthiasmauch@114 439 *
matthiasmauch@114 440 * Note that if running multi-threaded in Offline mode, the change
matthiasmauch@114 441 * may not take effect immediately if processing is already under
matthiasmauch@114 442 * way when this function is called.
matthiasmauch@114 443 */
matthiasmauch@114 444 void setPhaseOption(Options options);
matthiasmauch@114 445
matthiasmauch@114 446 /**
matthiasmauch@114 447 * Change an OptionFormant configuration setting. This may be
matthiasmauch@114 448 * called at any time in any mode.
matthiasmauch@114 449 *
matthiasmauch@114 450 * Note that if running multi-threaded in Offline mode, the change
matthiasmauch@114 451 * may not take effect immediately if processing is already under
matthiasmauch@114 452 * way when this function is called.
matthiasmauch@114 453 */
matthiasmauch@114 454 void setFormantOption(Options options);
matthiasmauch@114 455
matthiasmauch@114 456 /**
matthiasmauch@114 457 * Change an OptionPitch configuration setting. This may be
matthiasmauch@114 458 * called at any time in RealTime mode. It may not be called in
matthiasmauch@114 459 * Offline mode (for which the transients option is fixed on
matthiasmauch@114 460 * construction).
matthiasmauch@114 461 */
matthiasmauch@114 462 void setPitchOption(Options options);
matthiasmauch@114 463
matthiasmauch@114 464 /**
matthiasmauch@114 465 * Tell the stretcher exactly how many input samples it will
matthiasmauch@114 466 * receive. This is only useful in Offline mode, when it allows
matthiasmauch@114 467 * the stretcher to ensure that the number of output samples is
matthiasmauch@114 468 * exactly correct. In RealTime mode no such guarantee is
matthiasmauch@114 469 * possible and this value is ignored.
matthiasmauch@114 470 */
matthiasmauch@114 471 void setExpectedInputDuration(size_t samples);
matthiasmauch@114 472
matthiasmauch@114 473 /**
matthiasmauch@114 474 * Tell the stretcher the maximum number of sample frames that you
matthiasmauch@114 475 * will ever be passing in to a single process() call. If you
matthiasmauch@114 476 * don't call this, the stretcher will assume that you are calling
matthiasmauch@114 477 * getSamplesRequired() at each cycle and are never passing more
matthiasmauch@114 478 * samples than are suggested by that function.
matthiasmauch@114 479 *
matthiasmauch@114 480 * If your application has some external constraint that means you
matthiasmauch@114 481 * prefer a fixed block size, then your normal mode of operation
matthiasmauch@114 482 * would be to provide that block size to this function; to loop
matthiasmauch@114 483 * calling process() with that size of block; after each call to
matthiasmauch@114 484 * process(), test whether output has been generated by calling
matthiasmauch@114 485 * available(); and, if so, call retrieve() to obtain it. See
matthiasmauch@114 486 * getSamplesRequired() for a more suitable operating mode for
matthiasmauch@114 487 * applications without such external constraints.
matthiasmauch@114 488 *
matthiasmauch@114 489 * This function may not be called after the first call to study()
matthiasmauch@114 490 * or process().
matthiasmauch@114 491 *
matthiasmauch@114 492 * Note that this value is only relevant to process(), not to
matthiasmauch@114 493 * study() (to which you may pass any number of samples at a time,
matthiasmauch@114 494 * and from which there is no output).
matthiasmauch@114 495 */
matthiasmauch@114 496 void setMaxProcessSize(size_t samples);
matthiasmauch@114 497
matthiasmauch@114 498 /**
matthiasmauch@114 499 * Ask the stretcher how many audio sample frames should be
matthiasmauch@114 500 * provided as input in order to ensure that some more output
matthiasmauch@114 501 * becomes available.
matthiasmauch@114 502 *
matthiasmauch@114 503 * If your application has no particular constraint on processing
matthiasmauch@114 504 * block size and you are able to provide any block size as input
matthiasmauch@114 505 * for each cycle, then your normal mode of operation would be to
matthiasmauch@114 506 * loop querying this function; providing that number of samples
matthiasmauch@114 507 * to process(); and reading the output using available() and
matthiasmauch@114 508 * retrieve(). See setMaxProcessSize() for a more suitable
matthiasmauch@114 509 * operating mode for applications that do have external block
matthiasmauch@114 510 * size constraints.
matthiasmauch@114 511 *
matthiasmauch@114 512 * Note that this value is only relevant to process(), not to
matthiasmauch@114 513 * study() (to which you may pass any number of samples at a time,
matthiasmauch@114 514 * and from which there is no output).
matthiasmauch@114 515 */
matthiasmauch@114 516 size_t getSamplesRequired() const;
matthiasmauch@114 517
matthiasmauch@114 518 /**
matthiasmauch@114 519 * Provide a set of mappings from "before" to "after" sample
matthiasmauch@114 520 * numbers so as to enforce a particular stretch profile. The
matthiasmauch@114 521 * argument is a map from audio sample frame number in the source
matthiasmauch@114 522 * material, to the corresponding sample frame number in the
matthiasmauch@114 523 * stretched output. The mapping should be for key frames only,
matthiasmauch@114 524 * with a "reasonable" gap between mapped samples.
matthiasmauch@114 525 *
matthiasmauch@114 526 * This function cannot be used in RealTime mode.
matthiasmauch@114 527 *
matthiasmauch@114 528 * This function may not be called after the first call to
matthiasmauch@114 529 * process(). It should be called after the time and pitch ratios
matthiasmauch@114 530 * have been set; the results of changing the time and pitch
matthiasmauch@114 531 * ratios after calling this function are undefined. Calling
matthiasmauch@114 532 * reset() will clear this mapping.
matthiasmauch@114 533 *
matthiasmauch@114 534 * The key frame map only affects points within the material; it
matthiasmauch@114 535 * does not determine the overall stretch ratio (that is, the
matthiasmauch@114 536 * ratio between the output material's duration and the source
matthiasmauch@114 537 * material's duration). You need to provide this ratio
matthiasmauch@114 538 * separately to setTimeRatio(), otherwise the results may be
matthiasmauch@114 539 * truncated or extended in unexpected ways regardless of the
matthiasmauch@114 540 * extent of the frame numbers found in the key frame map.
matthiasmauch@114 541 */
matthiasmauch@114 542 void setKeyFrameMap(const std::map<size_t, size_t> &);
matthiasmauch@114 543
matthiasmauch@114 544 /**
matthiasmauch@114 545 * Provide a block of "samples" sample frames for the stretcher to
matthiasmauch@114 546 * study and calculate a stretch profile from.
matthiasmauch@114 547 *
matthiasmauch@114 548 * This is only meaningful in Offline mode, and is required if
matthiasmauch@114 549 * running in that mode. You should pass the entire input through
matthiasmauch@114 550 * study() before any process() calls are made, as a sequence of
matthiasmauch@114 551 * blocks in individual study() calls, or as a single large block.
matthiasmauch@114 552 *
matthiasmauch@114 553 * "input" should point to de-interleaved audio data with one
matthiasmauch@114 554 * float array per channel. "samples" supplies the number of
matthiasmauch@114 555 * audio sample frames available in "input". If "samples" is
matthiasmauch@114 556 * zero, "input" may be NULL.
matthiasmauch@114 557 *
matthiasmauch@114 558 * Set "final" to true if this is the last block of data that will
matthiasmauch@114 559 * be provided to study() before the first process() call.
matthiasmauch@114 560 */
matthiasmauch@114 561 void study(const float *const *input, size_t samples, bool final);
matthiasmauch@114 562
matthiasmauch@114 563 /**
matthiasmauch@114 564 * Provide a block of "samples" sample frames for processing.
matthiasmauch@114 565 * See also getSamplesRequired() and setMaxProcessSize().
matthiasmauch@114 566 *
matthiasmauch@114 567 * Set "final" to true if this is the last block of input data.
matthiasmauch@114 568 */
matthiasmauch@114 569 void process(const float *const *input, size_t samples, bool final);
matthiasmauch@114 570
matthiasmauch@114 571 /**
matthiasmauch@114 572 * Ask the stretcher how many audio sample frames of output data
matthiasmauch@114 573 * are available for reading (via retrieve()).
matthiasmauch@114 574 *
matthiasmauch@114 575 * This function returns 0 if no frames are available: this
matthiasmauch@114 576 * usually means more input data needs to be provided, but if the
matthiasmauch@114 577 * stretcher is running in threaded mode it may just mean that not
matthiasmauch@114 578 * enough data has yet been processed. Call getSamplesRequired()
matthiasmauch@114 579 * to discover whether more input is needed.
matthiasmauch@114 580 *
matthiasmauch@114 581 * This function returns -1 if all data has been fully processed
matthiasmauch@114 582 * and all output read, and the stretch process is now finished.
matthiasmauch@114 583 */
matthiasmauch@114 584 int available() const;
matthiasmauch@114 585
matthiasmauch@114 586 /**
matthiasmauch@114 587 * Obtain some processed output data from the stretcher. Up to
matthiasmauch@114 588 * "samples" samples will be stored in the output arrays (one per
matthiasmauch@114 589 * channel for de-interleaved audio data) pointed to by "output".
matthiasmauch@114 590 * The return value is the actual number of sample frames
matthiasmauch@114 591 * retrieved.
matthiasmauch@114 592 */
matthiasmauch@114 593 size_t retrieve(float *const *output, size_t samples) const;
matthiasmauch@114 594
matthiasmauch@114 595 /**
matthiasmauch@114 596 * Return the value of internal frequency cutoff value n.
matthiasmauch@114 597 *
matthiasmauch@114 598 * This function is not for general use.
matthiasmauch@114 599 */
matthiasmauch@114 600 float getFrequencyCutoff(int n) const;
matthiasmauch@114 601
matthiasmauch@114 602 /**
matthiasmauch@114 603 * Set the value of internal frequency cutoff n to f Hz.
matthiasmauch@114 604 *
matthiasmauch@114 605 * This function is not for general use.
matthiasmauch@114 606 */
matthiasmauch@114 607 void setFrequencyCutoff(int n, float f);
matthiasmauch@114 608
matthiasmauch@114 609 /**
matthiasmauch@114 610 * Retrieve the value of the internal input block increment value.
matthiasmauch@114 611 *
matthiasmauch@114 612 * This function is provided for diagnostic purposes only.
matthiasmauch@114 613 */
matthiasmauch@114 614 size_t getInputIncrement() const;
matthiasmauch@114 615
matthiasmauch@114 616 /**
matthiasmauch@114 617 * In offline mode, retrieve the sequence of internal block
matthiasmauch@114 618 * increments for output, for the entire audio data, provided the
matthiasmauch@114 619 * stretch profile has been calculated. In realtime mode,
matthiasmauch@114 620 * retrieve any output increments that have accumulated since the
matthiasmauch@114 621 * last call to getOutputIncrements, to a limit of 16.
matthiasmauch@114 622 *
matthiasmauch@114 623 * This function is provided for diagnostic purposes only.
matthiasmauch@114 624 */
matthiasmauch@114 625 std::vector<int> getOutputIncrements() const;
matthiasmauch@114 626
matthiasmauch@114 627 /**
matthiasmauch@114 628 * In offline mode, retrieve the sequence of internal phase reset
matthiasmauch@114 629 * detection function values, for the entire audio data, provided
matthiasmauch@114 630 * the stretch profile has been calculated. In realtime mode,
matthiasmauch@114 631 * retrieve any phase reset points that have accumulated since the
matthiasmauch@114 632 * last call to getPhaseResetCurve, to a limit of 16.
matthiasmauch@114 633 *
matthiasmauch@114 634 * This function is provided for diagnostic purposes only.
matthiasmauch@114 635 */
matthiasmauch@114 636 std::vector<float> getPhaseResetCurve() const;
matthiasmauch@114 637
matthiasmauch@114 638 /**
matthiasmauch@114 639 * In offline mode, retrieve the sequence of internal frames for
matthiasmauch@114 640 * which exact timing has been sought, for the entire audio data,
matthiasmauch@114 641 * provided the stretch profile has been calculated. In realtime
matthiasmauch@114 642 * mode, return an empty sequence.
matthiasmauch@114 643 *
matthiasmauch@114 644 * This function is provided for diagnostic purposes only.
matthiasmauch@114 645 */
matthiasmauch@114 646 std::vector<int> getExactTimePoints() const;
matthiasmauch@114 647
matthiasmauch@114 648 /**
matthiasmauch@114 649 * Return the number of channels this stretcher was constructed
matthiasmauch@114 650 * with.
matthiasmauch@114 651 */
matthiasmauch@114 652 size_t getChannelCount() const;
matthiasmauch@114 653
matthiasmauch@114 654 /**
matthiasmauch@114 655 * Force the stretcher to calculate a stretch profile. Normally
matthiasmauch@114 656 * this happens automatically for the first process() call in
matthiasmauch@114 657 * offline mode.
matthiasmauch@114 658 *
matthiasmauch@114 659 * This function is provided for diagnostic purposes only.
matthiasmauch@114 660 */
matthiasmauch@114 661 void calculateStretch();
matthiasmauch@114 662
matthiasmauch@114 663 /**
matthiasmauch@114 664 * Set the level of debug output. The value may be from 0 (errors
matthiasmauch@114 665 * only) to 3 (very verbose, with audible ticks in the output at
matthiasmauch@114 666 * phase reset points). The default is whatever has been set
matthiasmauch@114 667 * using setDefaultDebugLevel, or 0 if that function has not been
matthiasmauch@114 668 * called.
matthiasmauch@114 669 */
matthiasmauch@114 670 void setDebugLevel(int level);
matthiasmauch@114 671
matthiasmauch@114 672 /**
matthiasmauch@114 673 * Set the default level of debug output for subsequently
matthiasmauch@114 674 * constructed stretchers.
matthiasmauch@114 675 *
matthiasmauch@114 676 * @see setDebugLevel
matthiasmauch@114 677 */
matthiasmauch@114 678 static void setDefaultDebugLevel(int level);
matthiasmauch@114 679
matthiasmauch@114 680 protected:
matthiasmauch@114 681 class Impl;
matthiasmauch@114 682 Impl *m_d;
matthiasmauch@114 683 };
matthiasmauch@114 684
matthiasmauch@114 685 }
matthiasmauch@114 686
matthiasmauch@114 687 #endif