SoundTouch.cpp   SoundTouch.cpp 
skipping to change at line 44 skipping to change at line 44
/// tempo and pitch in the same ratio) of the sound. The third available control /// tempo and pitch in the same ratio) of the sound. The third available control
/// 'pitch' (change pitch but maintain tempo) is produced by a combinatio n of /// 'pitch' (change pitch but maintain tempo) is produced by a combinatio n of
/// combining the two other controls. /// combining the two other controls.
/// ///
/// Author : Copyright (c) Olli Parviainen /// Author : Copyright (c) Olli Parviainen
/// Author e-mail : oparviai 'at' iki.fi /// Author e-mail : oparviai 'at' iki.fi
/// SoundTouch WWW: http://www.surina.net/soundtouch /// SoundTouch WWW: http://www.surina.net/soundtouch
/// ///
/////////////////////////////////////////////////////////////////////////// ///// /////////////////////////////////////////////////////////////////////////// /////
// //
// Last changed : $Date: 2014-10-08 15:26:57 +0000 (Wed, 08 Oct 2014) $ // Last changed : $Date: 2015-07-26 17:45:48 +0300 (Sun, 26 Jul 2015) $
// File revision : $Revision: 4 $ // File revision : $Revision: 4 $
// //
// $Id: SoundTouch.cpp 201 2014-10-08 15:26:57Z oparviai $ // $Id: SoundTouch.cpp 225 2015-07-26 14:45:48Z oparviai $
// //
/////////////////////////////////////////////////////////////////////////// ///// /////////////////////////////////////////////////////////////////////////// /////
// //
// License : // License :
// //
// SoundTouch audio processing library // SoundTouch audio processing library
// Copyright (c) Olli Parviainen // Copyright (c) Olli Parviainen
// //
// This library is free software; you can redistribute it and/or // This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public // modify it under the terms of the GNU Lesser General Public
skipping to change at line 111 skipping to change at line 111
setOutPipe(pTDStretch); setOutPipe(pTDStretch);
rate = tempo = 0; rate = tempo = 0;
virtualPitch = virtualPitch =
virtualRate = virtualRate =
virtualTempo = 1.0; virtualTempo = 1.0;
calcEffectiveRateAndTempo(); calcEffectiveRateAndTempo();
samplesExpectedOut = 0;
samplesOutput = 0;
channels = 0; channels = 0;
bSrateSet = false; bSrateSet = false;
} }
SoundTouch::~SoundTouch() SoundTouch::~SoundTouch()
{ {
delete pRateTransposer; delete pRateTransposer;
delete pTDStretch; delete pTDStretch;
} }
skipping to change at line 150 skipping to change at line 153
//ST_THROW_RT_ERROR("Illegal number of channels"); //ST_THROW_RT_ERROR("Illegal number of channels");
return; return;
}*/ }*/
channels = numChannels; channels = numChannels;
pRateTransposer->setChannels((int)numChannels); pRateTransposer->setChannels((int)numChannels);
pTDStretch->setChannels((int)numChannels); pTDStretch->setChannels((int)numChannels);
} }
// Sets new rate control value. Normal rate = 1.0, smaller values // Sets new rate control value. Normal rate = 1.0, smaller values
// represent slower rate, larger faster rates. // represent slower rate, larger faster rates.
void SoundTouch::setRate(float newRate) void SoundTouch::setRate(double newRate)
{ {
virtualRate = newRate; virtualRate = newRate;
calcEffectiveRateAndTempo(); calcEffectiveRateAndTempo();
} }
// Sets new rate control value as a difference in percents compared // Sets new rate control value as a difference in percents compared
// to the original rate (-50 .. +100 %) // to the original rate (-50 .. +100 %)
void SoundTouch::setRateChange(float newRate) void SoundTouch::setRateChange(double newRate)
{ {
virtualRate = 1.0f + 0.01f * newRate; virtualRate = 1.0 + 0.01 * newRate;
calcEffectiveRateAndTempo(); calcEffectiveRateAndTempo();
} }
// Sets new tempo control value. Normal tempo = 1.0, smaller values // Sets new tempo control value. Normal tempo = 1.0, smaller values
// represent slower tempo, larger faster tempo. // represent slower tempo, larger faster tempo.
void SoundTouch::setTempo(float newTempo) void SoundTouch::setTempo(double newTempo)
{ {
virtualTempo = newTempo; virtualTempo = newTempo;
calcEffectiveRateAndTempo(); calcEffectiveRateAndTempo();
} }
// Sets new tempo control value as a difference in percents compared // Sets new tempo control value as a difference in percents compared
// to the original tempo (-50 .. +100 %) // to the original tempo (-50 .. +100 %)
void SoundTouch::setTempoChange(float newTempo) void SoundTouch::setTempoChange(double newTempo)
{ {
virtualTempo = 1.0f + 0.01f * newTempo; virtualTempo = 1.0 + 0.01 * newTempo;
calcEffectiveRateAndTempo(); calcEffectiveRateAndTempo();
} }
// Sets new pitch control value. Original pitch = 1.0, smaller values // Sets new pitch control value. Original pitch = 1.0, smaller values
// represent lower pitches, larger values higher pitch. // represent lower pitches, larger values higher pitch.
void SoundTouch::setPitch(float newPitch) void SoundTouch::setPitch(double newPitch)
{ {
virtualPitch = newPitch; virtualPitch = newPitch;
calcEffectiveRateAndTempo(); calcEffectiveRateAndTempo();
} }
// Sets pitch change in octaves compared to the original pitch // Sets pitch change in octaves compared to the original pitch
// (-1.00 .. +1.00) // (-1.00 .. +1.00)
void SoundTouch::setPitchOctaves(float newPitch) void SoundTouch::setPitchOctaves(double newPitch)
{ {
virtualPitch = (float)exp(0.69314718056f * newPitch); virtualPitch = exp(0.69314718056 * newPitch);
calcEffectiveRateAndTempo(); calcEffectiveRateAndTempo();
} }
// Sets pitch change in semi-tones compared to the original pitch // Sets pitch change in semi-tones compared to the original pitch
// (-12 .. +12) // (-12 .. +12)
void SoundTouch::setPitchSemiTones(int newPitch) void SoundTouch::setPitchSemiTones(int newPitch)
{ {
setPitchOctaves((float)newPitch / 12.0f); setPitchOctaves((double)newPitch / 12.0);
} }
void SoundTouch::setPitchSemiTones(float newPitch) void SoundTouch::setPitchSemiTones(double newPitch)
{ {
setPitchOctaves(newPitch / 12.0f); setPitchOctaves(newPitch / 12.0);
} }
// Calculates 'effective' rate and tempo values from the // Calculates 'effective' rate and tempo values from the
// nominal control values. // nominal control values.
void SoundTouch::calcEffectiveRateAndTempo() void SoundTouch::calcEffectiveRateAndTempo()
{ {
float oldTempo = tempo; double oldTempo = tempo;
float oldRate = rate; double oldRate = rate;
tempo = virtualTempo / virtualPitch; tempo = virtualTempo / virtualPitch;
rate = virtualPitch * virtualRate; rate = virtualPitch * virtualRate;
if (!TEST_FLOAT_EQUAL(rate,oldRate)) pRateTransposer->setRate(rate); if (!TEST_FLOAT_EQUAL(rate,oldRate)) pRateTransposer->setRate(rate);
if (!TEST_FLOAT_EQUAL(tempo, oldTempo)) pTDStretch->setTempo(tempo); if (!TEST_FLOAT_EQUAL(tempo, oldTempo)) pTDStretch->setTempo(tempo);
#ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER #ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER
if (rate <= 1.0f) if (rate <= 1.0f)
{ {
if (output != pTDStretch) if (output != pTDStretch)
{ {
FIFOSamplePipe *tempoOut; FIFOSamplePipe *tempoOut;
assert(output == pRateTransposer); assert(output == pRateTransposer);
// move samples in the current output buffer to the output of p TDStretch // move samples in the current output buffer to the output of p TDStretch
skipping to change at line 293 skipping to change at line 296
assert(output == pTDStretch); assert(output == pTDStretch);
if (pRateTransposer->isEmpty() == 0) if (pRateTransposer->isEmpty() == 0)
{ {
// yet flush the last samples in the pitch transposer buffer // yet flush the last samples in the pitch transposer buffer
// (may happen if 'rate' changes from a non-zero value to zero) // (may happen if 'rate' changes from a non-zero value to zero)
pTDStretch->moveSamples(*pRateTransposer); pTDStretch->moveSamples(*pRateTransposer);
} }
pTDStretch->putSamples(samples, nSamples); pTDStretch->putSamples(samples, nSamples);
} }
*/ */
// accumulate how many samples are expected out from processing, giv
en the current
// processing setting
samplesExpectedOut += (double)nSamples / ((double)rate * (double)tem
po);
#ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER #ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER
else if (rate <= 1.0f) if (rate <= 1.0f)
{ {
// transpose the rate down, output the transposed sound to tempo ch anger buffer // transpose the rate down, output the transposed sound to tempo ch anger buffer
assert(output == pTDStretch); assert(output == pTDStretch);
pRateTransposer->putSamples(samples, nSamples); pRateTransposer->putSamples(samples, nSamples);
pTDStretch->moveSamples(*pRateTransposer); pTDStretch->moveSamples(*pRateTransposer);
} }
else else
#endif #endif
{ {
// evaluate the tempo changer, then transpose the rate up, // evaluate the tempo changer, then transpose the rate up,
skipping to change at line 321 skipping to change at line 329
// Flushes the last samples from the processing pipeline to the output. // Flushes the last samples from the processing pipeline to the output.
// Clears also the internal processing buffers. // Clears also the internal processing buffers.
// //
// Note: This function is meant for extracting the last samples of a sound // Note: This function is meant for extracting the last samples of a sound
// stream. This function may introduce additional blank samples in the end // stream. This function may introduce additional blank samples in the end
// of the sound stream, and thus it's not recommended to call this function // of the sound stream, and thus it's not recommended to call this function
// in the middle of a sound stream. // in the middle of a sound stream.
void SoundTouch::flush() void SoundTouch::flush()
{ {
int i; int i;
int nUnprocessed; int numStillExpected;
int nOut; SAMPLETYPE *buff = new SAMPLETYPE[128 * channels];
SAMPLETYPE *buff = new SAMPLETYPE[64 * channels];
// check how many samples still await processing, and scale
// that by tempo & rate to get expected output sample count
nUnprocessed = numUnprocessedSamples();
nUnprocessed = (int)((double)nUnprocessed / (tempo * rate) + 0.5);
nOut = numSamples(); // ready samples currently in buffer ... // how many samples are still expected to output
nOut += nUnprocessed; // ... and how many we expect there to be i numStillExpected = (int)((long)(samplesExpectedOut + 0.5) - samplesO
n the end utput);
memset(buff, 0, 64 * channels * sizeof(SAMPLETYPE)); memset(buff, 0, 128 * channels * sizeof(SAMPLETYPE));
// "Push" the last active samples out from the processing pipeline by // "Push" the last active samples out from the processing pipeline by
// feeding blank samples into the processing pipeline until new, // feeding blank samples into the processing pipeline until new,
// processed samples appear in the output (not however, more than // processed samples appear in the output (not however, more than
// 8ksamples in any case) // 24ksamples in any case)
for (i = 0; i < 128; i ++) for (i = 0; (numStillExpected > (int)numSamples()) && (i < 200); i +
{ +)
putSamples(buff, 64); {
if ((int)numSamples() >= nOut) putSamples(buff, 128);
{ }
// Enough new samples have appeared into the output!
// As samples come from processing with bigger chunks, now trun
cate it
// back to maximum "nOut" samples to improve duration accuracy
adjustAmountOfSamples(nOut);
// finish adjustAmountOfSamples(numStillExpected);
break;
}
}
delete[] buff; delete[] buff;
// Clear working buffers // Clear input buffers
pRateTransposer->clear(); // pRateTransposer->clearInput();
pTDStretch->clearInput(); pTDStretch->clearInput();
// yet leave the 'tempoChanger' output intouched as that's where the // yet leave the output intouched as that's where the
// flushed samples are! // flushed samples are!
} }
// Changes a setting controlling the processing system behaviour. See the // Changes a setting controlling the processing system behaviour. See the
// 'SETTING_...' defines for available setting ID's. // 'SETTING_...' defines for available setting ID's.
bool SoundTouch::setSetting(int settingId, int value) bool SoundTouch::setSetting(int settingId, int value)
{ {
int sampleRate, sequenceMs, seekWindowMs, overlapMs; int sampleRate, sequenceMs, seekWindowMs, overlapMs;
// read current tdstretch routine parameters // read current tdstretch routine parameters
skipping to change at line 454 skipping to change at line 448
default : default :
return 0; return 0;
} }
} }
// Clears all the samples in the object's output and internal processing // Clears all the samples in the object's output and internal processing
// buffers. // buffers.
void SoundTouch::clear() void SoundTouch::clear()
{ {
samplesExpectedOut = 0;
pRateTransposer->clear(); pRateTransposer->clear();
pTDStretch->clear(); pTDStretch->clear();
} }
/// Returns number of samples currently unprocessed. /// Returns number of samples currently unprocessed.
uint SoundTouch::numUnprocessedSamples() const uint SoundTouch::numUnprocessedSamples() const
{ {
FIFOSamplePipe * psp; FIFOSamplePipe * psp;
if (pTDStretch) if (pTDStretch)
{ {
psp = pTDStretch->getInput(); psp = pTDStretch->getInput();
if (psp) if (psp)
{ {
return psp->numSamples(); return psp->numSamples();
} }
} }
return 0; return 0;
} }
/// Output samples from beginning of the sample buffer. Copies requested sa
mples to
/// output buffer and removes them from the sample buffer. If there are les
s than
/// 'numsample' samples in the buffer, returns all that available.
///
/// \return Number of samples returned.
uint SoundTouch::receiveSamples(SAMPLETYPE *output, uint maxSamples)
{
uint ret = FIFOProcessor::receiveSamples(output, maxSamples);
samplesOutput += (long)ret;
return ret;
}
/// Adjusts book-keeping so that given number of samples are removed from b
eginning of the
/// sample buffer without copying them anywhere.
///
/// Used to reduce the number of samples in the buffer when accessing the s
ample buffer directly
/// with 'ptrBegin' function.
uint SoundTouch::receiveSamples(uint maxSamples)
{
uint ret = FIFOProcessor::receiveSamples(maxSamples);
samplesOutput += (long)ret;
return ret;
}
 End of changes. 29 change blocks. 
50 lines changed or deleted 47 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/