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