SoundTouch.h (15020B)
1 ////////////////////////////////////////////////////////////////////////////// 2 /// 3 /// SoundTouch - main class for tempo/pitch/rate adjusting routines. 4 /// 5 /// Notes: 6 /// - Initialize the SoundTouch object instance by setting up the sound stream 7 /// parameters with functions 'setSampleRate' and 'setChannels', then set 8 /// desired tempo/pitch/rate settings with the corresponding functions. 9 /// 10 /// - The SoundTouch class behaves like a first-in-first-out pipeline: The 11 /// samples that are to be processed are fed into one of the pipe by calling 12 /// function 'putSamples', while the ready processed samples can be read 13 /// from the other end of the pipeline with function 'receiveSamples'. 14 /// 15 /// - The SoundTouch processing classes require certain sized 'batches' of 16 /// samples in order to process the sound. For this reason the classes buffer 17 /// incoming samples until there are enough of samples available for 18 /// processing, then they carry out the processing step and consequently 19 /// make the processed samples available for outputting. 20 /// 21 /// - For the above reason, the processing routines introduce a certain 22 /// 'latency' between the input and output, so that the samples input to 23 /// SoundTouch may not be immediately available in the output, and neither 24 /// the amount of outputtable samples may not immediately be in direct 25 /// relationship with the amount of previously input samples. 26 /// 27 /// - The tempo/pitch/rate control parameters can be altered during processing. 28 /// Please notice though that they aren't currently protected by semaphores, 29 /// so in multi-thread application external semaphore protection may be 30 /// required. 31 /// 32 /// - This class utilizes classes 'TDStretch' for tempo change (without modifying 33 /// pitch) and 'RateTransposer' for changing the playback rate (that is, both 34 /// tempo and pitch in the same ratio) of the sound. The third available control 35 /// 'pitch' (change pitch but maintain tempo) is produced by a combination of 36 /// combining the two other controls. 37 /// 38 /// Author : Copyright (c) Olli Parviainen 39 /// Author e-mail : oparviai 'at' iki.fi 40 /// SoundTouch WWW: http://www.surina.net/soundtouch 41 /// 42 //////////////////////////////////////////////////////////////////////////////// 43 // 44 // License : 45 // 46 // SoundTouch audio processing library 47 // Copyright (c) Olli Parviainen 48 // 49 // This library is free software; you can redistribute it and/or 50 // modify it under the terms of the GNU Lesser General Public 51 // License as published by the Free Software Foundation; either 52 // version 2.1 of the License, or (at your option) any later version. 53 // 54 // This library is distributed in the hope that it will be useful, 55 // but WITHOUT ANY WARRANTY; without even the implied warranty of 56 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 57 // Lesser General Public License for more details. 58 // 59 // You should have received a copy of the GNU Lesser General Public 60 // License along with this library; if not, write to the Free Software 61 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 62 // 63 //////////////////////////////////////////////////////////////////////////////// 64 65 #ifndef SoundTouch_H 66 #define SoundTouch_H 67 68 #include "FIFOSamplePipe.h" 69 #include "STTypes.h" 70 71 namespace soundtouch 72 { 73 74 /// Soundtouch library version string 75 #define SOUNDTOUCH_VERSION "2.2" 76 77 /// SoundTouch library version id 78 #define SOUNDTOUCH_VERSION_ID (20200) 79 80 // 81 // Available setting IDs for the 'setSetting' & 'get_setting' functions: 82 83 /// Enable/disable anti-alias filter in pitch transposer (0 = disable) 84 #define SETTING_USE_AA_FILTER 0 85 86 /// Pitch transposer anti-alias filter length (8 .. 128 taps, default = 32) 87 #define SETTING_AA_FILTER_LENGTH 1 88 89 /// Enable/disable quick seeking algorithm in tempo changer routine 90 /// (enabling quick seeking lowers CPU utilization but causes a minor sound 91 /// quality compromising) 92 #define SETTING_USE_QUICKSEEK 2 93 94 /// Time-stretch algorithm single processing sequence length in milliseconds. This determines 95 /// to how long sequences the original sound is chopped in the time-stretch algorithm. 96 /// See "STTypes.h" or README for more information. 97 #define SETTING_SEQUENCE_MS 3 98 99 /// Time-stretch algorithm seeking window length in milliseconds for algorithm that finds the 100 /// best possible overlapping location. This determines from how wide window the algorithm 101 /// may look for an optimal joining location when mixing the sound sequences back together. 102 /// See "STTypes.h" or README for more information. 103 #define SETTING_SEEKWINDOW_MS 4 104 105 /// Time-stretch algorithm overlap length in milliseconds. When the chopped sound sequences 106 /// are mixed back together, to form a continuous sound stream, this parameter defines over 107 /// how long period the two consecutive sequences are let to overlap each other. 108 /// See "STTypes.h" or README for more information. 109 #define SETTING_OVERLAP_MS 5 110 111 112 /// Call "getSetting" with this ID to query processing sequence size in samples. 113 /// This value gives approximate value of how many input samples you'll need to 114 /// feed into SoundTouch after initial buffering to get out a new batch of 115 /// output samples. 116 /// 117 /// This value does not include initial buffering at beginning of a new processing 118 /// stream, use SETTING_INITIAL_LATENCY to get the initial buffering size. 119 /// 120 /// Notices: 121 /// - This is read-only parameter, i.e. setSetting ignores this parameter 122 /// - This parameter value is not constant but change depending on 123 /// tempo/pitch/rate/samplerate settings. 124 #define SETTING_NOMINAL_INPUT_SEQUENCE 6 125 126 127 /// Call "getSetting" with this ID to query nominal average processing output 128 /// size in samples. This value tells approcimate value how many output samples 129 /// SoundTouch outputs once it does DSP processing run for a batch of input samples. 130 /// 131 /// Notices: 132 /// - This is read-only parameter, i.e. setSetting ignores this parameter 133 /// - This parameter value is not constant but change depending on 134 /// tempo/pitch/rate/samplerate settings. 135 #define SETTING_NOMINAL_OUTPUT_SEQUENCE 7 136 137 138 /// Call "getSetting" with this ID to query initial processing latency, i.e. 139 /// approx. how many samples you'll need to enter to SoundTouch pipeline before 140 /// you can expect to get first batch of ready output samples out. 141 /// 142 /// After the first output batch, you can then expect to get approx. 143 /// SETTING_NOMINAL_OUTPUT_SEQUENCE ready samples out for every 144 /// SETTING_NOMINAL_INPUT_SEQUENCE samples that you enter into SoundTouch. 145 /// 146 /// Example: 147 /// processing with parameter -tempo=5 148 /// => initial latency = 5509 samples 149 /// input sequence = 4167 samples 150 /// output sequence = 3969 samples 151 /// 152 /// Accordingly, you can expect to feed in approx. 5509 samples at beginning of 153 /// the stream, and then you'll get out the first 3969 samples. After that, for 154 /// every approx. 4167 samples that you'll put in, you'll receive again approx. 155 /// 3969 samples out. 156 /// 157 /// This also means that average latency during stream processing is 158 /// INITIAL_LATENCY-OUTPUT_SEQUENCE/2, in the above example case 5509-3969/2 159 /// = 3524 samples 160 /// 161 /// Notices: 162 /// - This is read-only parameter, i.e. setSetting ignores this parameter 163 /// - This parameter value is not constant but change depending on 164 /// tempo/pitch/rate/samplerate settings. 165 #define SETTING_INITIAL_LATENCY 8 166 167 168 class SoundTouch : public FIFOProcessor 169 { 170 private: 171 /// Rate transposer class instance 172 class RateTransposer *pRateTransposer; 173 174 /// Time-stretch class instance 175 class TDStretch *pTDStretch; 176 177 /// Virtual pitch parameter. Effective rate & tempo are calculated from these parameters. 178 double virtualRate; 179 180 /// Virtual pitch parameter. Effective rate & tempo are calculated from these parameters. 181 double virtualTempo; 182 183 /// Virtual pitch parameter. Effective rate & tempo are calculated from these parameters. 184 double virtualPitch; 185 186 /// Flag: Has sample rate been set? 187 bool bSrateSet; 188 189 /// Accumulator for how many samples in total will be expected as output vs. samples put in, 190 /// considering current processing settings. 191 double samplesExpectedOut; 192 193 /// Accumulator for how many samples in total have been read out from the processing so far 194 long samplesOutput; 195 196 /// Calculates effective rate & tempo valuescfrom 'virtualRate', 'virtualTempo' and 197 /// 'virtualPitch' parameters. 198 void calcEffectiveRateAndTempo(); 199 200 protected : 201 /// Number of channels 202 uint channels; 203 204 /// Effective 'rate' value calculated from 'virtualRate', 'virtualTempo' and 'virtualPitch' 205 double rate; 206 207 /// Effective 'tempo' value calculated from 'virtualRate', 'virtualTempo' and 'virtualPitch' 208 double tempo; 209 210 public: 211 SoundTouch(); 212 virtual ~SoundTouch(); 213 214 /// Get SoundTouch library version string 215 static const char *getVersionString(); 216 217 /// Get SoundTouch library version Id 218 static uint getVersionId(); 219 220 /// Sets new rate control value. Normal rate = 1.0, smaller values 221 /// represent slower rate, larger faster rates. 222 void setRate(double newRate); 223 224 /// Sets new tempo control value. Normal tempo = 1.0, smaller values 225 /// represent slower tempo, larger faster tempo. 226 void setTempo(double newTempo); 227 228 /// Sets new rate control value as a difference in percents compared 229 /// to the original rate (-50 .. +100 %) 230 void setRateChange(double newRate); 231 232 /// Sets new tempo control value as a difference in percents compared 233 /// to the original tempo (-50 .. +100 %) 234 void setTempoChange(double newTempo); 235 236 /// Sets new pitch control value. Original pitch = 1.0, smaller values 237 /// represent lower pitches, larger values higher pitch. 238 void setPitch(double newPitch); 239 240 /// Sets pitch change in octaves compared to the original pitch 241 /// (-1.00 .. +1.00) 242 void setPitchOctaves(double newPitch); 243 244 /// Sets pitch change in semi-tones compared to the original pitch 245 /// (-12 .. +12) 246 void setPitchSemiTones(int newPitch); 247 void setPitchSemiTones(double newPitch); 248 249 /// Sets the number of channels, 1 = mono, 2 = stereo 250 void setChannels(uint numChannels); 251 252 /// Sets sample rate. 253 void setSampleRate(uint srate); 254 255 /// Get ratio between input and output audio durations, useful for calculating 256 /// processed output duration: if you'll process a stream of N samples, then 257 /// you can expect to get out N * getInputOutputSampleRatio() samples. 258 /// 259 /// This ratio will give accurate target duration ratio for a full audio track, 260 /// given that the the whole track is processed with same processing parameters. 261 /// 262 /// If this ratio is applied to calculate intermediate offsets inside a processing 263 /// stream, then this ratio is approximate and can deviate +- some tens of milliseconds 264 /// from ideal offset, yet by end of the audio stream the duration ratio will become 265 /// exact. 266 /// 267 /// Example: if processing with parameters "-tempo=15 -pitch=-3", the function 268 /// will return value 0.8695652... Now, if processing an audio stream whose duration 269 /// is exactly one million audio samples, then you can expect the processed 270 /// output duration be 0.869565 * 1000000 = 869565 samples. 271 double getInputOutputSampleRatio(); 272 273 /// Flushes the last samples from the processing pipeline to the output. 274 /// Clears also the internal processing buffers. 275 // 276 /// Note: This function is meant for extracting the last samples of a sound 277 /// stream. This function may introduce additional blank samples in the end 278 /// of the sound stream, and thus it's not recommended to call this function 279 /// in the middle of a sound stream. 280 void flush(); 281 282 /// Adds 'numSamples' pcs of samples from the 'samples' memory position into 283 /// the input of the object. Notice that sample rate _has_to_ be set before 284 /// calling this function, otherwise throws a runtime_error exception. 285 virtual void putSamples( 286 const SAMPLETYPE *samples, ///< Pointer to sample buffer. 287 uint numSamples ///< Number of samples in buffer. Notice 288 ///< that in case of stereo-sound a single sample 289 ///< contains data for both channels. 290 ); 291 292 /// Output samples from beginning of the sample buffer. Copies requested samples to 293 /// output buffer and removes them from the sample buffer. If there are less than 294 /// 'numsample' samples in the buffer, returns all that available. 295 /// 296 /// \return Number of samples returned. 297 virtual uint receiveSamples(SAMPLETYPE *output, ///< Buffer where to copy output samples. 298 uint maxSamples ///< How many samples to receive at max. 299 ); 300 301 /// Adjusts book-keeping so that given number of samples are removed from beginning of the 302 /// sample buffer without copying them anywhere. 303 /// 304 /// Used to reduce the number of samples in the buffer when accessing the sample buffer directly 305 /// with 'ptrBegin' function. 306 virtual uint receiveSamples(uint maxSamples ///< Remove this many samples from the beginning of pipe. 307 ); 308 309 /// Clears all the samples in the object's output and internal processing 310 /// buffers. 311 virtual void clear(); 312 313 /// Changes a setting controlling the processing system behaviour. See the 314 /// 'SETTING_...' defines for available setting ID's. 315 /// 316 /// \return 'true' if the setting was successfully changed 317 bool setSetting(int settingId, ///< Setting ID number. see SETTING_... defines. 318 int value ///< New setting value. 319 ); 320 321 /// Reads a setting controlling the processing system behaviour. See the 322 /// 'SETTING_...' defines for available setting ID's. 323 /// 324 /// \return the setting value. 325 int getSetting(int settingId ///< Setting ID number, see SETTING_... defines. 326 ) const; 327 328 /// Returns number of samples currently unprocessed. 329 virtual uint numUnprocessedSamples() const; 330 331 /// Return number of channels 332 uint numChannels() const 333 { 334 return channels; 335 } 336 337 /// Other handy functions that are implemented in the ancestor classes (see 338 /// classes 'FIFOProcessor' and 'FIFOSamplePipe') 339 /// 340 /// - receiveSamples() : Use this function to receive 'ready' processed samples from SoundTouch. 341 /// - numSamples() : Get number of 'ready' samples that can be received with 342 /// function 'receiveSamples()' 343 /// - isEmpty() : Returns nonzero if there aren't any 'ready' samples. 344 /// - clear() : Clears all samples from ready/processing buffers. 345 }; 346 347 } 348 #endif