|
MythTV
0.26-pre
|
00001 00002 00003 00004 00005 00006 00007 00008 00009 00010 00011 00012 00013 00014 00015 00016 00017 00018 00019 00020 00021 00022 00023 00024 00025 00026 00027 00028 00029 00030 00031 00032 00033 00034 00035 00036 00037 00038 00039 00040 00041 00042 00043 // 00044 // Last changed : $Date$ 00045 // File revision : $Revision$ 00046 // 00047 // $Id$ 00048 // 00050 // 00051 // License : 00052 // 00053 // SoundTouch audio processing library 00054 // Copyright (c) Olli Parviainen 00055 // 00056 // This library is free software; you can redistribute it and/or 00057 // modify it under the terms of the GNU Lesser General Public 00058 // License as published by the Free Software Foundation; either 00059 // version 2.1 of the License, or (at your option) any later version. 00060 // 00061 // This library is distributed in the hope that it will be useful, 00062 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00063 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00064 // Lesser General Public License for more details. 00065 // 00066 // You should have received a copy of the GNU Lesser General Public 00067 // License along with this library; if not, write to the Free Software 00068 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00069 // 00071 00072 #include <assert.h> 00073 #include <stdlib.h> 00074 #include <memory.h> 00075 #include <math.h> 00076 #include <stdexcept> 00077 #include <stdio.h> 00078 00079 #include "SoundTouch.h" 00080 #include "TDStretch.h" 00081 #include "RateTransposer.h" 00082 #include "cpu_detect.h" 00083 00084 using namespace soundtouch; 00085 00087 extern "C" void soundtouch_ac_test() 00088 { 00089 printf("SoundTouch Version: %s\n",SOUNDTOUCH_VERSION); 00090 } 00091 00092 00093 SoundTouch::SoundTouch() 00094 { 00095 // Initialize rate transposer and tempo changer instances 00096 00097 pRateTransposer = RateTransposer::newInstance(); 00098 pTDStretch = TDStretch::newInstance(); 00099 00100 setOutPipe(pTDStretch); 00101 00102 rate = tempo = 0; 00103 00104 virtualPitch = 00105 virtualRate = 00106 virtualTempo = 1.0; 00107 00108 calcEffectiveRateAndTempo(); 00109 00110 channels = 0; 00111 bSrateSet = FALSE; 00112 } 00113 00114 00115 00116 SoundTouch::~SoundTouch() 00117 { 00118 delete pRateTransposer; 00119 delete pTDStretch; 00120 } 00121 00122 00123 00125 const char *SoundTouch::getVersionString() 00126 { 00127 static const char *_version = SOUNDTOUCH_VERSION; 00128 00129 return _version; 00130 } 00131 00132 00134 uint SoundTouch::getVersionId() 00135 { 00136 return SOUNDTOUCH_VERSION_ID; 00137 } 00138 00139 00140 // Sets the number of channels, 1 = mono, 2 = stereo 00141 void SoundTouch::setChannels(uint numChannels) 00142 { 00143 #ifdef MULTICHANNEL 00144 if (numChannels < 1 || numChannels > MULTICHANNEL) 00145 #else 00146 if (numChannels != 1 && numChannels != 2) 00147 #endif 00148 { 00149 throw std::runtime_error("Illegal number of channels"); 00150 } 00151 channels = numChannels; 00152 pRateTransposer->setChannels(numChannels); 00153 pTDStretch->setChannels(numChannels); 00154 } 00155 00156 00157 00158 // Sets new rate control value. Normal rate = 1.0, smaller values 00159 // represent slower rate, larger faster rates. 00160 void SoundTouch::setRate(float newRate) 00161 { 00162 virtualRate = newRate; 00163 calcEffectiveRateAndTempo(); 00164 } 00165 00166 00167 00168 // Sets new rate control value as a difference in percents compared 00169 // to the original rate (-50 .. +100 %) 00170 void SoundTouch::setRateChange(float newRate) 00171 { 00172 virtualRate = 1.0f + 0.01f * newRate; 00173 calcEffectiveRateAndTempo(); 00174 } 00175 00176 00177 00178 // Sets new tempo control value. Normal tempo = 1.0, smaller values 00179 // represent slower tempo, larger faster tempo. 00180 void SoundTouch::setTempo(float newTempo) 00181 { 00182 virtualTempo = newTempo; 00183 calcEffectiveRateAndTempo(); 00184 } 00185 00186 00187 00188 // Sets new tempo control value as a difference in percents compared 00189 // to the original tempo (-50 .. +100 %) 00190 void SoundTouch::setTempoChange(float newTempo) 00191 { 00192 virtualTempo = 1.0f + 0.01f * newTempo; 00193 calcEffectiveRateAndTempo(); 00194 } 00195 00196 00197 00198 // Sets new pitch control value. Original pitch = 1.0, smaller values 00199 // represent lower pitches, larger values higher pitch. 00200 void SoundTouch::setPitch(float newPitch) 00201 { 00202 virtualPitch = newPitch; 00203 calcEffectiveRateAndTempo(); 00204 } 00205 00206 00207 00208 // Sets pitch change in octaves compared to the original pitch 00209 // (-1.00 .. +1.00) 00210 void SoundTouch::setPitchOctaves(float newPitch) 00211 { 00212 virtualPitch = (float)exp(0.69314718056f * newPitch); 00213 calcEffectiveRateAndTempo(); 00214 } 00215 00216 00217 00218 // Sets pitch change in semi-tones compared to the original pitch 00219 // (-12 .. +12) 00220 void SoundTouch::setPitchSemiTones(int newPitch) 00221 { 00222 setPitchOctaves((float)newPitch / 12.0f); 00223 } 00224 00225 00226 00227 void SoundTouch::setPitchSemiTones(float newPitch) 00228 { 00229 setPitchOctaves(newPitch / 12.0f); 00230 } 00231 00232 00233 // Calculates 'effective' rate and tempo values from the 00234 // nominal control values. 00235 void SoundTouch::calcEffectiveRateAndTempo() 00236 { 00237 float oldTempo = tempo; 00238 float oldRate = rate; 00239 00240 tempo = virtualTempo / virtualPitch; 00241 rate = virtualPitch * virtualRate; 00242 00243 if (rate != oldRate) pRateTransposer->setRate(rate); 00244 if (tempo != oldTempo) pTDStretch->setTempo(tempo); 00245 00246 if (rate > 1.0f) 00247 { 00248 if (output != pRateTransposer) 00249 { 00250 FIFOSamplePipe *transOut; 00251 00252 assert(output == pTDStretch); 00253 // move samples in the current output buffer to the output of pRateTransposer 00254 transOut = pRateTransposer->getOutput(); 00255 transOut->moveSamples(*output); 00256 // move samples in tempo changer's input to pitch transposer's input 00257 pRateTransposer->moveSamples(*pTDStretch->getInput()); 00258 00259 output = pRateTransposer; 00260 } 00261 } 00262 else 00263 { 00264 if (output != pTDStretch) 00265 { 00266 FIFOSamplePipe *tempoOut; 00267 00268 assert(output == pRateTransposer); 00269 // move samples in the current output buffer to the output of pTDStretch 00270 tempoOut = pTDStretch->getOutput(); 00271 tempoOut->moveSamples(*output); 00272 // move samples in pitch transposer's store buffer to tempo changer's input 00273 pTDStretch->moveSamples(*pRateTransposer->getStore()); 00274 00275 output = pTDStretch; 00276 00277 } 00278 } 00279 } 00280 00281 00282 // Sets sample rate. 00283 void SoundTouch::setSampleRate(uint srate) 00284 { 00285 bSrateSet = TRUE; 00286 // set sample rate, leave other tempo changer parameters as they are. 00287 pTDStretch->setParameters(srate); 00288 } 00289 00290 00291 // Adds 'numSamples' pcs of samples from the 'samples' memory position into 00292 // the input of the object. 00293 void SoundTouch::putSamples(const SAMPLETYPE *samples, uint numSamples) 00294 { 00295 if (bSrateSet == FALSE) 00296 { 00297 throw std::runtime_error("SoundTouch : Sample rate not defined"); 00298 } 00299 else if (channels == 0) 00300 { 00301 throw std::runtime_error("SoundTouch : Number of channels not defined"); 00302 } 00303 00304 // Transpose the rate of the new samples if necessary 00305 /* Bypass the nominal setting - can introduce a click in sound when tempo/pitch control crosses the nominal value... 00306 */ 00307 // NOTE: Removed the bypass change in soundtouch 1.3.1 for MythTV, this 00308 // caused clipping for Cougar with our MMX implementation. -- dtk 00309 if (rate == 1.0f) 00310 { 00311 // The rate value is same as the original, simply evaluate the tempo changer. 00312 assert(output == pTDStretch); 00313 if (pRateTransposer->isEmpty() == 0) 00314 { 00315 // yet flush the last samples in the pitch transposer buffer 00316 // (may happen if 'rate' changes from a non-zero value to zero) 00317 pTDStretch->moveSamples(*pRateTransposer); 00318 } 00319 pTDStretch->putSamples(samples, numSamples); 00320 } 00321 else if (rate <= 1.0f) 00322 { 00323 // transpose the rate down, output the transposed sound to tempo changer buffer 00324 assert(output == pTDStretch); 00325 pRateTransposer->putSamples(samples, numSamples); 00326 pTDStretch->moveSamples(*pRateTransposer); 00327 } 00328 else 00329 { 00330 assert(rate > 1.0f); 00331 // evaluate the tempo changer, then transpose the rate up, 00332 assert(output == pRateTransposer); 00333 pTDStretch->putSamples(samples, numSamples); 00334 pRateTransposer->moveSamples(*pTDStretch); 00335 } 00336 } 00337 00338 00339 // Flushes the last samples from the processing pipeline to the output. 00340 // Clears also the internal processing buffers. 00341 // 00342 // Note: This function is meant for extracting the last samples of a sound 00343 // stream. This function may introduce additional blank samples in the end 00344 // of the sound stream, and thus it's not recommended to call this function 00345 // in the middle of a sound stream. 00346 void SoundTouch::flush() 00347 { 00348 int i; 00349 uint nOut; 00350 SAMPLETYPE buff[128]; 00351 00352 nOut = numSamples(); 00353 00354 memset(buff, 0, 128 * sizeof(SAMPLETYPE)); 00355 // "Push" the last active samples out from the processing pipeline by 00356 // feeding blank samples into the processing pipeline until new, 00357 // processed samples appear in the output (not however, more than 00358 // 8ksamples in any case) 00359 for (i = 0; i < 128; i ++) 00360 { 00361 putSamples(buff, 64); 00362 if (numSamples() != nOut) break; // new samples have appeared in the output! 00363 } 00364 00365 // Clear working buffers 00366 pRateTransposer->clear(); 00367 pTDStretch->clearInput(); 00368 // yet leave the 'tempoChanger' output intouched as that's where the 00369 // flushed samples are! 00370 } 00371 00372 00373 // Changes a setting controlling the processing system behaviour. See the 00374 // 'SETTING_...' defines for available setting ID's. 00375 BOOL SoundTouch::setSetting(uint settingId, uint value) 00376 { 00377 uint sampleRate, sequenceMs, seekWindowMs, overlapMs; 00378 00379 // read current tdstretch routine parameters 00380 pTDStretch->getParameters(&sampleRate, &sequenceMs, &seekWindowMs, &overlapMs); 00381 00382 switch (settingId) 00383 { 00384 case SETTING_USE_AA_FILTER : 00385 // enables / disabless anti-alias filter 00386 pRateTransposer->enableAAFilter((value != 0) ? TRUE : FALSE); 00387 return TRUE; 00388 00389 case SETTING_AA_FILTER_LENGTH : 00390 // sets anti-alias filter length 00391 pRateTransposer->getAAFilter()->setLength(value); 00392 return TRUE; 00393 00394 case SETTING_USE_QUICKSEEK : 00395 // enables / disables tempo routine quick seeking algorithm 00396 pTDStretch->enableQuickSeek((value != 0) ? TRUE : FALSE); 00397 return TRUE; 00398 00399 case SETTING_SEQUENCE_MS: 00400 // change time-stretch sequence duration parameter 00401 pTDStretch->setParameters(sampleRate, value, seekWindowMs, overlapMs); 00402 return TRUE; 00403 00404 case SETTING_SEEKWINDOW_MS: 00405 // change time-stretch seek window length parameter 00406 pTDStretch->setParameters(sampleRate, sequenceMs, value, overlapMs); 00407 return TRUE; 00408 00409 case SETTING_OVERLAP_MS: 00410 // change time-stretch overlap length parameter 00411 pTDStretch->setParameters(sampleRate, sequenceMs, seekWindowMs, value); 00412 return TRUE; 00413 00414 default : 00415 return FALSE; 00416 } 00417 } 00418 00419 00420 // Reads a setting controlling the processing system behaviour. See the 00421 // 'SETTING_...' defines for available setting ID's. 00422 // 00423 // Returns the setting value. 00424 uint SoundTouch::getSetting(uint settingId) const 00425 { 00426 uint temp; 00427 00428 switch (settingId) 00429 { 00430 case SETTING_USE_AA_FILTER : 00431 return pRateTransposer->isAAFilterEnabled(); 00432 00433 case SETTING_AA_FILTER_LENGTH : 00434 return pRateTransposer->getAAFilter()->getLength(); 00435 00436 case SETTING_USE_QUICKSEEK : 00437 return pTDStretch->isQuickSeekEnabled(); 00438 00439 case SETTING_SEQUENCE_MS: 00440 pTDStretch->getParameters(NULL, &temp, NULL, NULL); 00441 return temp; 00442 00443 case SETTING_SEEKWINDOW_MS: 00444 pTDStretch->getParameters(NULL, NULL, &temp, NULL); 00445 return temp; 00446 00447 case SETTING_OVERLAP_MS: 00448 pTDStretch->getParameters(NULL, NULL, NULL, &temp); 00449 return temp; 00450 00451 default : 00452 return 0; 00453 } 00454 } 00455 00456 00457 // Clears all the samples in the object's output and internal processing 00458 // buffers. 00459 void SoundTouch::clear() 00460 { 00461 pRateTransposer->clear(); 00462 pTDStretch->clear(); 00463 } 00464 00465 00466 00468 uint SoundTouch::numUnprocessedSamples() const 00469 { 00470 FIFOSamplePipe * psp; 00471 if (pTDStretch) 00472 { 00473 psp = pTDStretch->getInput(); 00474 if (psp) 00475 { 00476 return psp->numSamples(); 00477 } 00478 } 00479 return 0; 00480 }
1.7.6.1