Chris@45: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@45: Chris@45: /* Chris@45: Rubber Band Library Chris@45: An audio time-stretching and pitch-shifting library. Chris@45: Copyright 2007-2015 Particular Programs Ltd. Chris@45: Chris@45: This program is free software; you can redistribute it and/or Chris@45: modify it under the terms of the GNU General Public License as Chris@45: published by the Free Software Foundation; either version 2 of the Chris@45: License, or (at your option) any later version. See the file Chris@45: COPYING included with this distribution for more information. Chris@45: Chris@45: Alternatively, if you have a valid commercial licence for the Chris@45: Rubber Band Library obtained by agreement with the copyright Chris@45: holders, you may redistribute and/or modify it under the terms Chris@45: described in that licence. Chris@45: Chris@45: If you wish to distribute code using the Rubber Band Library Chris@45: under terms other than those of the GNU General Public License, Chris@45: you must obtain a valid commercial licence before doing so. Chris@45: */ Chris@45: Chris@45: #ifndef _RUBBERBANDSTRETCHER_H_ Chris@45: #define _RUBBERBANDSTRETCHER_H_ Chris@45: Chris@45: #define RUBBERBAND_VERSION "1.8.2" Chris@45: #define RUBBERBAND_API_MAJOR_VERSION 2 Chris@45: #define RUBBERBAND_API_MINOR_VERSION 5 Chris@45: Chris@45: #include Chris@45: #include Chris@45: #include Chris@45: Chris@45: /** Chris@45: * @mainpage RubberBand Chris@45: * Chris@45: * The Rubber Band API is contained in the single class Chris@45: * RubberBand::RubberBandStretcher. Chris@45: * Chris@45: * Threading notes for real-time applications: Chris@45: * Chris@45: * Multiple instances of RubberBandStretcher may be created and used Chris@45: * in separate threads concurrently. However, for any single instance Chris@45: * of RubberBandStretcher, you may not call process() more than once Chris@45: * concurrently, and you may not change the time or pitch ratio while Chris@45: * a process() call is being executed (if the stretcher was created in Chris@45: * "real-time mode"; in "offline mode" you can't change the ratios Chris@45: * during use anyway). Chris@45: * Chris@45: * So you can run process() in its own thread if you like, but if you Chris@45: * want to change ratios dynamically from a different thread, you will Chris@45: * need some form of mutex in your code. Changing the time or pitch Chris@45: * ratio is real-time safe except in extreme circumstances, so for Chris@45: * most applications that may change these dynamically it probably Chris@45: * makes most sense to do so from the same thread as calls process(), Chris@45: * even if that is a real-time thread. Chris@45: */ Chris@45: Chris@45: namespace RubberBand Chris@45: { Chris@45: Chris@45: class RubberBandStretcher Chris@45: { Chris@45: public: Chris@45: /** Chris@45: * Processing options for the timestretcher. The preferred Chris@45: * options should normally be set in the constructor, as a bitwise Chris@45: * OR of the option flags. The default value (DefaultOptions) is Chris@45: * intended to give good results in most situations. Chris@45: * Chris@45: * 1. Flags prefixed \c OptionProcess determine how the timestretcher Chris@45: * will be invoked. These options may not be changed after Chris@45: * construction. Chris@45: * Chris@45: * \li \c OptionProcessOffline - Run the stretcher in offline Chris@45: * mode. In this mode the input data needs to be provided Chris@45: * twice, once to study(), which calculates a stretch profile Chris@45: * for the audio, and once to process(), which stretches it. Chris@45: * Chris@45: * \li \c OptionProcessRealTime - Run the stretcher in real-time Chris@45: * mode. In this mode only process() should be called, and the Chris@45: * stretcher adjusts dynamically in response to the input audio. Chris@45: * Chris@45: * The Process setting is likely to depend on your architecture: Chris@45: * non-real-time operation on seekable files: Offline; real-time Chris@45: * or streaming operation: RealTime. Chris@45: * Chris@45: * 2. Flags prefixed \c OptionStretch control the profile used for Chris@45: * variable timestretching. Rubber Band always adjusts the Chris@45: * stretch profile to minimise stretching of busy broadband Chris@45: * transient sounds, but the degree to which it does so is Chris@45: * adjustable. These options may not be changed after Chris@45: * construction. Chris@45: * Chris@45: * \li \c OptionStretchElastic - Only meaningful in offline Chris@45: * mode, and the default in that mode. The audio will be Chris@45: * stretched at a variable rate, aimed at preserving the quality Chris@45: * of transient sounds as much as possible. The timings of low Chris@45: * activity regions between transients may be less exact than Chris@45: * when the precise flag is set. Chris@45: * Chris@45: * \li \c OptionStretchPrecise - Although still using a variable Chris@45: * stretch rate, the audio will be stretched so as to maintain Chris@45: * as close as possible to a linear stretch ratio throughout. Chris@45: * Timing may be better than when using \c OptionStretchElastic, at Chris@45: * slight cost to the sound quality of transients. This setting Chris@45: * is always used when running in real-time mode. Chris@45: * Chris@45: * 3. Flags prefixed \c OptionTransients control the component Chris@45: * frequency phase-reset mechanism that may be used at transient Chris@45: * points to provide clarity and realism to percussion and other Chris@45: * significant transient sounds. These options may be changed Chris@45: * after construction when running in real-time mode, but not when Chris@45: * running in offline mode. Chris@45: * Chris@45: * \li \c OptionTransientsCrisp - Reset component phases at the Chris@45: * peak of each transient (the start of a significant note or Chris@45: * percussive event). This, the default setting, usually Chris@45: * results in a clear-sounding output; but it is not always Chris@45: * consistent, and may cause interruptions in stable sounds Chris@45: * present at the same time as transient events. The Chris@45: * OptionDetector flags (below) can be used to tune this to some Chris@45: * extent. Chris@45: * Chris@45: * \li \c OptionTransientsMixed - Reset component phases at the Chris@45: * peak of each transient, outside a frequency range typical of Chris@45: * musical fundamental frequencies. The results may be more Chris@45: * regular for mixed stable and percussive notes than Chris@45: * \c OptionTransientsCrisp, but with a "phasier" sound. The Chris@45: * balance may sound very good for certain types of music and Chris@45: * fairly bad for others. Chris@45: * Chris@45: * \li \c OptionTransientsSmooth - Do not reset component phases Chris@45: * at any point. The results will be smoother and more regular Chris@45: * but may be less clear than with either of the other Chris@45: * transients flags. Chris@45: * Chris@45: * 4. Flags prefixed \c OptionDetector control the type of Chris@45: * transient detector used. These options may be changed Chris@45: * after construction when running in real-time mode, but not when Chris@45: * running in offline mode. Chris@45: * Chris@45: * \li \c OptionDetectorCompound - Use a general-purpose Chris@45: * transient detector which is likely to be good for most Chris@45: * situations. This is the default. Chris@45: * Chris@45: * \li \c OptionDetectorPercussive - Detect percussive Chris@45: * transients. Note that this was the default and only option Chris@45: * in Rubber Band versions prior to 1.5. Chris@45: * Chris@45: * \li \c OptionDetectorSoft - Use an onset detector with less Chris@45: * of a bias toward percussive transients. This may give better Chris@45: * results with certain material (e.g. relatively monophonic Chris@45: * piano music). Chris@45: * Chris@45: * 5. Flags prefixed \c OptionPhase control the adjustment of Chris@45: * component frequency phases from one analysis window to the next Chris@45: * during non-transient segments. These options may be changed at Chris@45: * any time. Chris@45: * Chris@45: * \li \c OptionPhaseLaminar - Adjust phases when stretching in Chris@45: * such a way as to try to retain the continuity of phase Chris@45: * relationships between adjacent frequency bins whose phases Chris@45: * are behaving in similar ways. This, the default setting, Chris@45: * should give good results in most situations. Chris@45: * Chris@45: * \li \c OptionPhaseIndependent - Adjust the phase in each Chris@45: * frequency bin independently from its neighbours. This Chris@45: * usually results in a slightly softer, phasier sound. Chris@45: * Chris@45: * 6. Flags prefixed \c OptionThreading control the threading Chris@45: * model of the stretcher. These options may not be changed after Chris@45: * construction. Chris@45: * Chris@45: * \li \c OptionThreadingAuto - Permit the stretcher to Chris@45: * determine its own threading model. Usually this means using Chris@45: * one processing thread per audio channel in offline mode if Chris@45: * the stretcher is able to determine that more than one CPU is Chris@45: * available, and one thread only in realtime mode. This is the Chris@45: * defafult. Chris@45: * Chris@45: * \li \c OptionThreadingNever - Never use more than one thread. Chris@45: * Chris@45: * \li \c OptionThreadingAlways - Use multiple threads in any Chris@45: * situation where \c OptionThreadingAuto would do so, except omit Chris@45: * the check for multiple CPUs and instead assume it to be true. Chris@45: * Chris@45: * 7. Flags prefixed \c OptionWindow control the window size for Chris@45: * FFT processing. The window size actually used will depend on Chris@45: * many factors, but it can be influenced. These options may not Chris@45: * be changed after construction. Chris@45: * Chris@45: * \li \c OptionWindowStandard - Use the default window size. Chris@45: * The actual size will vary depending on other parameters. Chris@45: * This option is expected to produce better results than the Chris@45: * other window options in most situations. Chris@45: * Chris@45: * \li \c OptionWindowShort - Use a shorter window. This may Chris@45: * result in crisper sound for audio that depends strongly on Chris@45: * its timing qualities. Chris@45: * Chris@45: * \li \c OptionWindowLong - Use a longer window. This is Chris@45: * likely to result in a smoother sound at the expense of Chris@45: * clarity and timing. Chris@45: * Chris@45: * 8. Flags prefixed \c OptionSmoothing control the use of Chris@45: * window-presum FFT and time-domain smoothing. These options may Chris@45: * not be changed after construction. Chris@45: * Chris@45: * \li \c OptionSmoothingOff - Do not use time-domain smoothing. Chris@45: * This is the default. Chris@45: * Chris@45: * \li \c OptionSmoothingOn - Use time-domain smoothing. This Chris@45: * will result in a softer sound with some audible artifacts Chris@45: * around sharp transients, but it may be appropriate for longer Chris@45: * stretches of some instruments and can mix well with Chris@45: * OptionWindowShort. Chris@45: * Chris@45: * 9. Flags prefixed \c OptionFormant control the handling of Chris@45: * formant shape (spectral envelope) when pitch-shifting. These Chris@45: * options may be changed at any time. Chris@45: * Chris@45: * \li \c OptionFormantShifted - Apply no special formant Chris@45: * processing. The spectral envelope will be pitch shifted as Chris@45: * normal. This is the default. Chris@45: * Chris@45: * \li \c OptionFormantPreserved - Preserve the spectral Chris@45: * envelope of the unshifted signal. This permits shifting the Chris@45: * note frequency without so substantially affecting the Chris@45: * perceived pitch profile of the voice or instrument. Chris@45: * Chris@45: * 10. Flags prefixed \c OptionPitch control the method used for Chris@45: * pitch shifting. These options may be changed at any time. Chris@45: * They are only effective in realtime mode; in offline mode, the Chris@45: * pitch-shift method is fixed. Chris@45: * Chris@45: * \li \c OptionPitchHighSpeed - Use a method with a CPU cost Chris@45: * that is relatively moderate and predictable. This may Chris@45: * sound less clear than OptionPitchHighQuality, especially Chris@45: * for large pitch shifts. This is the default. Chris@45: Chris@45: * \li \c OptionPitchHighQuality - Use the highest quality Chris@45: * method for pitch shifting. This method has a CPU cost Chris@45: * approximately proportional to the required frequency shift. Chris@45: Chris@45: * \li \c OptionPitchHighConsistency - Use the method that gives Chris@45: * greatest consistency when used to create small variations in Chris@45: * pitch around the 1.0-ratio level. Unlike the previous two Chris@45: * options, this avoids discontinuities when moving across the Chris@45: * 1.0 pitch scale in real-time; it also consumes more CPU than Chris@45: * the others in the case where the pitch scale is exactly 1.0. Chris@45: * Chris@45: * 11. Flags prefixed \c OptionChannels control the method used for Chris@45: * processing two-channel audio. These options may not be changed Chris@45: * after construction. Chris@45: * Chris@45: * \li \c OptionChannelsApart - Each channel is processed Chris@45: * individually, though timing is synchronised and phases are Chris@45: * synchronised at transients (depending on the OptionTransients Chris@45: * setting). This gives the highest quality for the individual Chris@45: * channels but a relative lack of stereo focus and unrealistic Chris@45: * increase in "width". This is the default. Chris@45: * Chris@45: * \li \c OptionChannelsTogether - The first two channels (where Chris@45: * two or more are present) are considered to be a stereo pair Chris@45: * and are processed in mid-side format; mid and side are Chris@45: * processed individually, with timing synchronised and phases Chris@45: * synchronised at transients (depending on the OptionTransients Chris@45: * setting). This usually leads to better focus in the centre Chris@45: * but a loss of stereo space and width. Any channels beyond Chris@45: * the first two are processed individually. Chris@45: */ Chris@45: Chris@45: enum Option { Chris@45: Chris@45: OptionProcessOffline = 0x00000000, Chris@45: OptionProcessRealTime = 0x00000001, Chris@45: Chris@45: OptionStretchElastic = 0x00000000, Chris@45: OptionStretchPrecise = 0x00000010, Chris@45: Chris@45: OptionTransientsCrisp = 0x00000000, Chris@45: OptionTransientsMixed = 0x00000100, Chris@45: OptionTransientsSmooth = 0x00000200, Chris@45: Chris@45: OptionDetectorCompound = 0x00000000, Chris@45: OptionDetectorPercussive = 0x00000400, Chris@45: OptionDetectorSoft = 0x00000800, Chris@45: Chris@45: OptionPhaseLaminar = 0x00000000, Chris@45: OptionPhaseIndependent = 0x00002000, Chris@45: Chris@45: OptionThreadingAuto = 0x00000000, Chris@45: OptionThreadingNever = 0x00010000, Chris@45: OptionThreadingAlways = 0x00020000, Chris@45: Chris@45: OptionWindowStandard = 0x00000000, Chris@45: OptionWindowShort = 0x00100000, Chris@45: OptionWindowLong = 0x00200000, Chris@45: Chris@45: OptionSmoothingOff = 0x00000000, Chris@45: OptionSmoothingOn = 0x00800000, Chris@45: Chris@45: OptionFormantShifted = 0x00000000, Chris@45: OptionFormantPreserved = 0x01000000, Chris@45: Chris@45: OptionPitchHighSpeed = 0x00000000, Chris@45: OptionPitchHighQuality = 0x02000000, Chris@45: OptionPitchHighConsistency = 0x04000000, Chris@45: Chris@45: OptionChannelsApart = 0x00000000, Chris@45: OptionChannelsTogether = 0x10000000, Chris@45: Chris@45: // n.b. Options is int, so we must stop before 0x80000000 Chris@45: }; Chris@45: Chris@45: typedef int Options; Chris@45: Chris@45: enum PresetOption { Chris@45: DefaultOptions = 0x00000000, Chris@45: PercussiveOptions = 0x00102000 Chris@45: }; Chris@45: Chris@45: /** Chris@45: * Construct a time and pitch stretcher object to run at the given Chris@45: * sample rate, with the given number of channels. Processing Chris@45: * options and the time and pitch scaling ratios may be provided. Chris@45: * The time and pitch ratios may be changed after construction, Chris@45: * but most of the options may not. See the option documentation Chris@45: * above for more details. Chris@45: */ Chris@45: RubberBandStretcher(size_t sampleRate, Chris@45: size_t channels, Chris@45: Options options = DefaultOptions, Chris@45: double initialTimeRatio = 1.0, Chris@45: double initialPitchScale = 1.0); Chris@45: ~RubberBandStretcher(); Chris@45: Chris@45: /** Chris@45: * Reset the stretcher's internal buffers. The stretcher should Chris@45: * subsequently behave as if it had just been constructed Chris@45: * (although retaining the current time and pitch ratio). Chris@45: */ Chris@45: void reset(); Chris@45: Chris@45: /** Chris@45: * Set the time ratio for the stretcher. This is the ratio of Chris@45: * stretched to unstretched duration -- not tempo. For example, a Chris@45: * ratio of 2.0 would make the audio twice as long (i.e. halve the Chris@45: * tempo); 0.5 would make it half as long (i.e. double the tempo); Chris@45: * 1.0 would leave the duration unaffected. Chris@45: * Chris@45: * If the stretcher was constructed in Offline mode, the time Chris@45: * ratio is fixed throughout operation; this function may be Chris@45: * called any number of times between construction (or a call to Chris@45: * reset()) and the first call to study() or process(), but may Chris@45: * not be called after study() or process() has been called. Chris@45: * Chris@45: * If the stretcher was constructed in RealTime mode, the time Chris@45: * ratio may be varied during operation; this function may be Chris@45: * called at any time, so long as it is not called concurrently Chris@45: * with process(). You should either call this function from the Chris@45: * same thread as process(), or provide your own mutex or similar Chris@45: * mechanism to ensure that setTimeRatio and process() cannot be Chris@45: * run at once (there is no internal mutex for this purpose). Chris@45: */ Chris@45: void setTimeRatio(double ratio); Chris@45: Chris@45: /** Chris@45: * Set the pitch scaling ratio for the stretcher. This is the Chris@45: * ratio of target frequency to source frequency. For example, a Chris@45: * ratio of 2.0 would shift up by one octave; 0.5 down by one Chris@45: * octave; or 1.0 leave the pitch unaffected. Chris@45: * Chris@45: * To put this in musical terms, a pitch scaling ratio Chris@45: * corresponding to a shift of S equal-tempered semitones (where S Chris@45: * is positive for an upwards shift and negative for downwards) is Chris@45: * pow(2.0, S / 12.0). Chris@45: * Chris@45: * If the stretcher was constructed in Offline mode, the pitch Chris@45: * scaling ratio is fixed throughout operation; this function may Chris@45: * be called any number of times between construction (or a call Chris@45: * to reset()) and the first call to study() or process(), but may Chris@45: * not be called after study() or process() has been called. Chris@45: * Chris@45: * If the stretcher was constructed in RealTime mode, the pitch Chris@45: * scaling ratio may be varied during operation; this function may Chris@45: * be called at any time, so long as it is not called concurrently Chris@45: * with process(). You should either call this function from the Chris@45: * same thread as process(), or provide your own mutex or similar Chris@45: * mechanism to ensure that setPitchScale and process() cannot be Chris@45: * run at once (there is no internal mutex for this purpose). Chris@45: */ Chris@45: void setPitchScale(double scale); Chris@45: Chris@45: /** Chris@45: * Return the last time ratio value that was set (either on Chris@45: * construction or with setTimeRatio()). Chris@45: */ Chris@45: double getTimeRatio() const; Chris@45: Chris@45: /** Chris@45: * Return the last pitch scaling ratio value that was set (either Chris@45: * on construction or with setPitchScale()). Chris@45: */ Chris@45: double getPitchScale() const; Chris@45: Chris@45: /** Chris@45: * Return the processing latency of the stretcher. This is the Chris@45: * number of audio samples that one would have to discard at the Chris@45: * start of the output in order to ensure that the resulting audio Chris@45: * aligned with the input audio at the start. In Offline mode, Chris@45: * latency is automatically adjusted for and the result is zero. Chris@45: * In RealTime mode, the latency may depend on the time and pitch Chris@45: * ratio and other options. Chris@45: */ Chris@45: size_t getLatency() const; Chris@45: Chris@45: /** Chris@45: * Change an OptionTransients configuration setting. This may be Chris@45: * called at any time in RealTime mode. It may not be called in Chris@45: * Offline mode (for which the transients option is fixed on Chris@45: * construction). Chris@45: */ Chris@45: void setTransientsOption(Options options); Chris@45: Chris@45: /** Chris@45: * Change an OptionDetector configuration setting. This may be Chris@45: * called at any time in RealTime mode. It may not be called in Chris@45: * Offline mode (for which the detector option is fixed on Chris@45: * construction). Chris@45: */ Chris@45: void setDetectorOption(Options options); Chris@45: Chris@45: /** Chris@45: * Change an OptionPhase configuration setting. This may be Chris@45: * called at any time in any mode. Chris@45: * Chris@45: * Note that if running multi-threaded in Offline mode, the change Chris@45: * may not take effect immediately if processing is already under Chris@45: * way when this function is called. Chris@45: */ Chris@45: void setPhaseOption(Options options); Chris@45: Chris@45: /** Chris@45: * Change an OptionFormant configuration setting. This may be Chris@45: * called at any time in any mode. Chris@45: * Chris@45: * Note that if running multi-threaded in Offline mode, the change Chris@45: * may not take effect immediately if processing is already under Chris@45: * way when this function is called. Chris@45: */ Chris@45: void setFormantOption(Options options); Chris@45: Chris@45: /** Chris@45: * Change an OptionPitch configuration setting. This may be Chris@45: * called at any time in RealTime mode. It may not be called in Chris@45: * Offline mode (for which the transients option is fixed on Chris@45: * construction). Chris@45: */ Chris@45: void setPitchOption(Options options); Chris@45: Chris@45: /** Chris@45: * Tell the stretcher exactly how many input sample frames it will Chris@45: * receive. This is only useful in Offline mode, when it allows Chris@45: * the stretcher to ensure that the number of output samples is Chris@45: * exactly correct. In RealTime mode no such guarantee is Chris@45: * possible and this value is ignored. Chris@45: * Chris@45: * Note that the value of "samples" refers to the number of audio Chris@45: * sample frames, which may be multi-channel, not the number of Chris@45: * individual samples. (For example, one second of stereo audio Chris@45: * sampled at 44100Hz yields a value of 44100 sample frames, not Chris@45: * 88200.) This rule applies throughout the Rubber Band API. Chris@45: */ Chris@45: void setExpectedInputDuration(size_t samples); Chris@45: Chris@45: /** Chris@45: * Tell the stretcher the maximum number of sample frames that you Chris@45: * will ever be passing in to a single process() call. If you Chris@45: * don't call this, the stretcher will assume that you are calling Chris@45: * getSamplesRequired() at each cycle and are never passing more Chris@45: * samples than are suggested by that function. Chris@45: * Chris@45: * If your application has some external constraint that means you Chris@45: * prefer a fixed block size, then your normal mode of operation Chris@45: * would be to provide that block size to this function; to loop Chris@45: * calling process() with that size of block; after each call to Chris@45: * process(), test whether output has been generated by calling Chris@45: * available(); and, if so, call retrieve() to obtain it. See Chris@45: * getSamplesRequired() for a more suitable operating mode for Chris@45: * applications without such external constraints. Chris@45: * Chris@45: * This function may not be called after the first call to study() Chris@45: * or process(). Chris@45: * Chris@45: * Note that this value is only relevant to process(), not to Chris@45: * study() (to which you may pass any number of samples at a time, Chris@45: * and from which there is no output). Chris@45: * Chris@45: * Note that the value of "samples" refers to the number of audio Chris@45: * sample frames, which may be multi-channel, not the number of Chris@45: * individual samples. (For example, one second of stereo audio Chris@45: * sampled at 44100Hz yields a value of 44100 sample frames, not Chris@45: * 88200.) This rule applies throughout the Rubber Band API. Chris@45: */ Chris@45: void setMaxProcessSize(size_t samples); Chris@45: Chris@45: /** Chris@45: * Ask the stretcher how many audio sample frames should be Chris@45: * provided as input in order to ensure that some more output Chris@45: * becomes available. Chris@45: * Chris@45: * If your application has no particular constraint on processing Chris@45: * block size and you are able to provide any block size as input Chris@45: * for each cycle, then your normal mode of operation would be to Chris@45: * loop querying this function; providing that number of samples Chris@45: * to process(); and reading the output using available() and Chris@45: * retrieve(). See setMaxProcessSize() for a more suitable Chris@45: * operating mode for applications that do have external block Chris@45: * size constraints. Chris@45: * Chris@45: * Note that this value is only relevant to process(), not to Chris@45: * study() (to which you may pass any number of samples at a time, Chris@45: * and from which there is no output). Chris@45: * Chris@45: * Note that the return value refers to the number of audio sample Chris@45: * frames, which may be multi-channel, not the number of Chris@45: * individual samples. (For example, one second of stereo audio Chris@45: * sampled at 44100Hz yields a value of 44100 sample frames, not Chris@45: * 88200.) This rule applies throughout the Rubber Band API. Chris@45: */ Chris@45: size_t getSamplesRequired() const; Chris@45: Chris@45: /** Chris@45: * Provide a set of mappings from "before" to "after" sample Chris@45: * numbers so as to enforce a particular stretch profile. The Chris@45: * argument is a map from audio sample frame number in the source Chris@45: * material, to the corresponding sample frame number in the Chris@45: * stretched output. The mapping should be for key frames only, Chris@45: * with a "reasonable" gap between mapped samples. Chris@45: * Chris@45: * This function cannot be used in RealTime mode. Chris@45: * Chris@45: * This function may not be called after the first call to Chris@45: * process(). It should be called after the time and pitch ratios Chris@45: * have been set; the results of changing the time and pitch Chris@45: * ratios after calling this function are undefined. Calling Chris@45: * reset() will clear this mapping. Chris@45: * Chris@45: * The key frame map only affects points within the material; it Chris@45: * does not determine the overall stretch ratio (that is, the Chris@45: * ratio between the output material's duration and the source Chris@45: * material's duration). You need to provide this ratio Chris@45: * separately to setTimeRatio(), otherwise the results may be Chris@45: * truncated or extended in unexpected ways regardless of the Chris@45: * extent of the frame numbers found in the key frame map. Chris@45: */ Chris@45: void setKeyFrameMap(const std::map &); Chris@45: Chris@45: /** Chris@45: * Provide a block of "samples" sample frames for the stretcher to Chris@45: * study and calculate a stretch profile from. Chris@45: * Chris@45: * This is only meaningful in Offline mode, and is required if Chris@45: * running in that mode. You should pass the entire input through Chris@45: * study() before any process() calls are made, as a sequence of Chris@45: * blocks in individual study() calls, or as a single large block. Chris@45: * Chris@45: * "input" should point to de-interleaved audio data with one Chris@45: * float array per channel. Sample values are conventionally Chris@45: * expected to be in the range -1.0f to +1.0f. "samples" supplies Chris@45: * the number of audio sample frames available in "input". If Chris@45: * "samples" is zero, "input" may be NULL. Chris@45: * Chris@45: * Note that the value of "samples" refers to the number of audio Chris@45: * sample frames, which may be multi-channel, not the number of Chris@45: * individual samples. (For example, one second of stereo audio Chris@45: * sampled at 44100Hz yields a value of 44100 sample frames, not Chris@45: * 88200.) This rule applies throughout the Rubber Band API. Chris@45: * Chris@45: * Set "final" to true if this is the last block of data that will Chris@45: * be provided to study() before the first process() call. Chris@45: */ Chris@45: void study(const float *const *input, size_t samples, bool final); Chris@45: Chris@45: /** Chris@45: * Provide a block of "samples" sample frames for processing. Chris@45: * See also getSamplesRequired() and setMaxProcessSize(). Chris@45: * Chris@45: * "input" should point to de-interleaved audio data with one Chris@45: * float array per channel. Sample values are conventionally Chris@45: * expected to be in the range -1.0f to +1.0f. "samples" supplies Chris@45: * the number of audio sample frames available in "input". Chris@45: * Chris@45: * Note that the value of "samples" refers to the number of audio Chris@45: * sample frames, which may be multi-channel, not the number of Chris@45: * individual samples. (For example, one second of stereo audio Chris@45: * sampled at 44100Hz yields a value of 44100 sample frames, not Chris@45: * 88200.) This rule applies throughout the Rubber Band API. Chris@45: * Chris@45: * Set "final" to true if this is the last block of input data. Chris@45: */ Chris@45: void process(const float *const *input, size_t samples, bool final); Chris@45: Chris@45: /** Chris@45: * Ask the stretcher how many audio sample frames of output data Chris@45: * are available for reading (via retrieve()). Chris@45: * Chris@45: * This function returns 0 if no frames are available: this Chris@45: * usually means more input data needs to be provided, but if the Chris@45: * stretcher is running in threaded mode it may just mean that not Chris@45: * enough data has yet been processed. Call getSamplesRequired() Chris@45: * to discover whether more input is needed. Chris@45: * Chris@45: * Note that the return value refers to the number of audio sample Chris@45: * frames, which may be multi-channel, not the number of Chris@45: * individual samples. (For example, one second of stereo audio Chris@45: * sampled at 44100Hz yields a value of 44100 sample frames, not Chris@45: * 88200.) This rule applies throughout the Rubber Band API. Chris@45: * Chris@45: * This function returns -1 if all data has been fully processed Chris@45: * and all output read, and the stretch process is now finished. Chris@45: */ Chris@45: int available() const; Chris@45: Chris@45: /** Chris@45: * Obtain some processed output data from the stretcher. Up to Chris@45: * "samples" samples will be stored in the output arrays (one per Chris@45: * channel for de-interleaved audio data) pointed to by "output". Chris@45: * The return value is the actual number of sample frames Chris@45: * retrieved. Chris@45: * Chris@45: * Note that the value of "samples" and the return value refer to Chris@45: * the number of audio sample frames, which may be multi-channel, Chris@45: * not the number of individual samples. (For example, one second Chris@45: * of stereo audio sampled at 44100Hz yields a value of 44100 Chris@45: * sample frames, not 88200.) This rule applies throughout the Chris@45: * Rubber Band API. Chris@45: */ Chris@45: size_t retrieve(float *const *output, size_t samples) const; Chris@45: Chris@45: /** Chris@45: * Return the value of internal frequency cutoff value n. Chris@45: * Chris@45: * This function is not for general use. Chris@45: */ Chris@45: float getFrequencyCutoff(int n) const; Chris@45: Chris@45: /** Chris@45: * Set the value of internal frequency cutoff n to f Hz. Chris@45: * Chris@45: * This function is not for general use. Chris@45: */ Chris@45: void setFrequencyCutoff(int n, float f); Chris@45: Chris@45: /** Chris@45: * Retrieve the value of the internal input block increment value. Chris@45: * Chris@45: * This function is provided for diagnostic purposes only. Chris@45: */ Chris@45: size_t getInputIncrement() const; Chris@45: Chris@45: /** Chris@45: * In offline mode, retrieve the sequence of internal block Chris@45: * increments for output, for the entire audio data, provided the Chris@45: * stretch profile has been calculated. In realtime mode, Chris@45: * retrieve any output increments that have accumulated since the Chris@45: * last call to getOutputIncrements, to a limit of 16. Chris@45: * Chris@45: * This function is provided for diagnostic purposes only. Chris@45: */ Chris@45: std::vector getOutputIncrements() const; Chris@45: Chris@45: /** Chris@45: * In offline mode, retrieve the sequence of internal phase reset Chris@45: * detection function values, for the entire audio data, provided Chris@45: * the stretch profile has been calculated. In realtime mode, Chris@45: * retrieve any phase reset points that have accumulated since the Chris@45: * last call to getPhaseResetCurve, to a limit of 16. Chris@45: * Chris@45: * This function is provided for diagnostic purposes only. Chris@45: */ Chris@45: std::vector getPhaseResetCurve() const; Chris@45: Chris@45: /** Chris@45: * In offline mode, retrieve the sequence of internal frames for Chris@45: * which exact timing has been sought, for the entire audio data, Chris@45: * provided the stretch profile has been calculated. In realtime Chris@45: * mode, return an empty sequence. Chris@45: * Chris@45: * This function is provided for diagnostic purposes only. Chris@45: */ Chris@45: std::vector getExactTimePoints() const; Chris@45: Chris@45: /** Chris@45: * Return the number of channels this stretcher was constructed Chris@45: * with. Chris@45: */ Chris@45: size_t getChannelCount() const; Chris@45: Chris@45: /** Chris@45: * Force the stretcher to calculate a stretch profile. Normally Chris@45: * this happens automatically for the first process() call in Chris@45: * offline mode. Chris@45: * Chris@45: * This function is provided for diagnostic purposes only. Chris@45: */ Chris@45: void calculateStretch(); Chris@45: Chris@45: /** Chris@45: * Set the level of debug output. The value may be from 0 (errors Chris@45: * only) to 3 (very verbose, with audible ticks in the output at Chris@45: * phase reset points). The default is whatever has been set Chris@45: * using setDefaultDebugLevel, or 0 if that function has not been Chris@45: * called. Chris@45: */ Chris@45: void setDebugLevel(int level); Chris@45: Chris@45: /** Chris@45: * Set the default level of debug output for subsequently Chris@45: * constructed stretchers. Chris@45: * Chris@45: * @see setDebugLevel Chris@45: */ Chris@45: static void setDefaultDebugLevel(int level); Chris@45: Chris@45: protected: Chris@45: class Impl; Chris@45: Impl *m_d; Chris@45: }; Chris@45: Chris@45: } Chris@45: Chris@45: #endif