mirror of https://github.com/PCSX2/pcsx2.git
Update SoundTouch lib to v2.0.0
This commit is contained in:
parent
96b412ebb8
commit
574e0a7531
|
@ -26,10 +26,10 @@
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Last changed : $Date: 2012-08-30 22:53:44 +0300 (Thu, 30 Aug 2012) $
|
// Last changed : $Date: 2016-01-12 19:24:46 +0200 (ti, 12 tammi 2016) $
|
||||||
// File revision : $Revision: 4 $
|
// File revision : $Revision: 4 $
|
||||||
//
|
//
|
||||||
// $Id: BPMDetect.h 150 2012-08-30 19:53:44Z oparviai $
|
// $Id: BPMDetect.h 239 2016-01-12 17:24:46Z oparviai $
|
||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
@ -77,12 +77,6 @@ protected:
|
||||||
/// Auto-correlation accumulator bins.
|
/// Auto-correlation accumulator bins.
|
||||||
float *xcorr;
|
float *xcorr;
|
||||||
|
|
||||||
/// Amplitude envelope sliding average approximation level accumulator
|
|
||||||
double envelopeAccu;
|
|
||||||
|
|
||||||
/// RMS volume sliding average approximation level accumulator
|
|
||||||
double RMSVolumeAccu;
|
|
||||||
|
|
||||||
/// Sample average counter.
|
/// Sample average counter.
|
||||||
int decimateCount;
|
int decimateCount;
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Last changed : $Date: 2014-01-05 23:40:22 +0200 (Sun, 05 Jan 2014) $
|
// Last changed : $Date: 2014-01-05 23:40:22 +0200 (su, 05 tammi 2014) $
|
||||||
// File revision : $Revision: 4 $
|
// File revision : $Revision: 4 $
|
||||||
//
|
//
|
||||||
// $Id: FIFOSampleBuffer.h 177 2014-01-05 21:40:22Z oparviai $
|
// $Id: FIFOSampleBuffer.h 177 2014-01-05 21:40:22Z oparviai $
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Last changed : $Date: 2012-06-13 22:29:53 +0300 (Wed, 13 Jun 2012) $
|
// Last changed : $Date: 2012-06-13 22:29:53 +0300 (ke, 13 kesä 2012) $
|
||||||
// File revision : $Revision: 4 $
|
// File revision : $Revision: 4 $
|
||||||
//
|
//
|
||||||
// $Id: FIFOSamplePipe.h 143 2012-06-13 19:29:53Z oparviai $
|
// $Id: FIFOSamplePipe.h 143 2012-06-13 19:29:53Z oparviai $
|
||||||
|
|
|
@ -8,10 +8,10 @@
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Last changed : $Date: 2015-05-18 18:25:07 +0300 (Mon, 18 May 2015) $
|
// Last changed : $Date: 2017-07-30 12:28:06 +0300 (su, 30 heinä 2017) $
|
||||||
// File revision : $Revision: 3 $
|
// File revision : $Revision: 3 $
|
||||||
//
|
//
|
||||||
// $Id: STTypes.h 215 2015-05-18 15:25:07Z oparviai $
|
// $Id: STTypes.h 252 2017-07-30 09:28:06Z oparviai $
|
||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
@ -143,8 +143,10 @@ namespace soundtouch
|
||||||
#endif // SOUNDTOUCH_FLOAT_SAMPLES
|
#endif // SOUNDTOUCH_FLOAT_SAMPLES
|
||||||
|
|
||||||
#ifdef SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS
|
#ifdef SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS
|
||||||
// Allow MMX optimizations
|
// Allow MMX optimizations (not available in X64 mode)
|
||||||
#define SOUNDTOUCH_ALLOW_MMX 1
|
#if (!_M_X64)
|
||||||
|
#define SOUNDTOUCH_ALLOW_MMX 1
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -41,10 +41,10 @@
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Last changed : $Date: 2015-09-20 10:38:32 +0300 (Sun, 20 Sep 2015) $
|
// Last changed : $Date: 2017-07-30 12:35:00 +0300 (su, 30 heinä 2017) $
|
||||||
// File revision : $Revision: 4 $
|
// File revision : $Revision: 4 $
|
||||||
//
|
//
|
||||||
// $Id: SoundTouch.h 230 2015-09-20 07:38:32Z oparviai $
|
// $Id: SoundTouch.h 253 2017-07-30 09:35:00Z oparviai $
|
||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
@ -79,10 +79,10 @@ namespace soundtouch
|
||||||
{
|
{
|
||||||
|
|
||||||
/// Soundtouch library version string
|
/// Soundtouch library version string
|
||||||
#define SOUNDTOUCH_VERSION "1.9.2"
|
#define SOUNDTOUCH_VERSION "2.0.0"
|
||||||
|
|
||||||
/// SoundTouch library version id
|
/// SoundTouch library version id
|
||||||
#define SOUNDTOUCH_VERSION_ID (10902)
|
#define SOUNDTOUCH_VERSION_ID (20000)
|
||||||
|
|
||||||
//
|
//
|
||||||
// Available setting IDs for the 'setSetting' & 'get_setting' functions:
|
// Available setting IDs for the 'setSetting' & 'get_setting' functions:
|
||||||
|
@ -116,17 +116,19 @@ namespace soundtouch
|
||||||
#define SETTING_OVERLAP_MS 5
|
#define SETTING_OVERLAP_MS 5
|
||||||
|
|
||||||
|
|
||||||
/// Call "getSetting" with this ID to query nominal average processing sequence
|
/// Call "getSetting" with this ID to query processing sequence size in samples.
|
||||||
/// size in samples. This value tells approcimate value how many input samples
|
/// This value gives approximate value of how many input samples you'll need to
|
||||||
/// SoundTouch needs to gather before it does DSP processing run for the sample batch.
|
/// feed into SoundTouch after initial buffering to get out a new batch of
|
||||||
|
/// output samples.
|
||||||
|
///
|
||||||
|
/// This value does not include initial buffering at beginning of a new processing
|
||||||
|
/// stream, use SETTING_INITIAL_LATENCY to get the initial buffering size.
|
||||||
///
|
///
|
||||||
/// Notices:
|
/// Notices:
|
||||||
/// - This is read-only parameter, i.e. setSetting ignores this parameter
|
/// - This is read-only parameter, i.e. setSetting ignores this parameter
|
||||||
/// - Returned value is approximate average value, exact processing batch
|
/// - This parameter value is not constant but change depending on
|
||||||
/// size may wary from time to time
|
|
||||||
/// - This parameter value is not constant but may change depending on
|
|
||||||
/// tempo/pitch/rate/samplerate settings.
|
/// tempo/pitch/rate/samplerate settings.
|
||||||
#define SETTING_NOMINAL_INPUT_SEQUENCE 6
|
#define SETTING_NOMINAL_INPUT_SEQUENCE 6
|
||||||
|
|
||||||
|
|
||||||
/// Call "getSetting" with this ID to query nominal average processing output
|
/// Call "getSetting" with this ID to query nominal average processing output
|
||||||
|
@ -135,11 +137,40 @@ namespace soundtouch
|
||||||
///
|
///
|
||||||
/// Notices:
|
/// Notices:
|
||||||
/// - This is read-only parameter, i.e. setSetting ignores this parameter
|
/// - This is read-only parameter, i.e. setSetting ignores this parameter
|
||||||
/// - Returned value is approximate average value, exact processing batch
|
/// - This parameter value is not constant but change depending on
|
||||||
/// size may wary from time to time
|
|
||||||
/// - This parameter value is not constant but may change depending on
|
|
||||||
/// tempo/pitch/rate/samplerate settings.
|
/// tempo/pitch/rate/samplerate settings.
|
||||||
#define SETTING_NOMINAL_OUTPUT_SEQUENCE 7
|
#define SETTING_NOMINAL_OUTPUT_SEQUENCE 7
|
||||||
|
|
||||||
|
|
||||||
|
/// Call "getSetting" with this ID to query initial processing latency, i.e.
|
||||||
|
/// approx. how many samples you'll need to enter to SoundTouch pipeline before
|
||||||
|
/// you can expect to get first batch of ready output samples out.
|
||||||
|
///
|
||||||
|
/// After the first output batch, you can then expect to get approx.
|
||||||
|
/// SETTING_NOMINAL_OUTPUT_SEQUENCE ready samples out for every
|
||||||
|
/// SETTING_NOMINAL_INPUT_SEQUENCE samples that you enter into SoundTouch.
|
||||||
|
///
|
||||||
|
/// Example:
|
||||||
|
/// processing with parameter -tempo=5
|
||||||
|
/// => initial latency = 5509 samples
|
||||||
|
/// input sequence = 4167 samples
|
||||||
|
/// output sequence = 3969 samples
|
||||||
|
///
|
||||||
|
/// Accordingly, you can expect to feed in approx. 5509 samples at beginning of
|
||||||
|
/// the stream, and then you'll get out the first 3969 samples. After that, for
|
||||||
|
/// every approx. 4167 samples that you'll put in, you'll receive again approx.
|
||||||
|
/// 3969 samples out.
|
||||||
|
///
|
||||||
|
/// This also means that average latency during stream processing is
|
||||||
|
/// INITIAL_LATENCY-OUTPUT_SEQUENCE/2, in the above example case 5509-3969/2
|
||||||
|
/// = 3524 samples
|
||||||
|
///
|
||||||
|
/// Notices:
|
||||||
|
/// - This is read-only parameter, i.e. setSetting ignores this parameter
|
||||||
|
/// - This parameter value is not constant but change depending on
|
||||||
|
/// tempo/pitch/rate/samplerate settings.
|
||||||
|
#define SETTING_INITIAL_LATENCY 8
|
||||||
|
|
||||||
|
|
||||||
class SoundTouch : public FIFOProcessor
|
class SoundTouch : public FIFOProcessor
|
||||||
{
|
{
|
||||||
|
@ -228,6 +259,24 @@ public:
|
||||||
/// Sets sample rate.
|
/// Sets sample rate.
|
||||||
void setSampleRate(uint srate);
|
void setSampleRate(uint srate);
|
||||||
|
|
||||||
|
/// Get ratio between input and output audio durations, useful for calculating
|
||||||
|
/// processed output duration: if you'll process a stream of N samples, then
|
||||||
|
/// you can expect to get out N * getInputOutputSampleRatio() samples.
|
||||||
|
///
|
||||||
|
/// This ratio will give accurate target duration ratio for a full audio track,
|
||||||
|
/// given that the the whole track is processed with same processing parameters.
|
||||||
|
///
|
||||||
|
/// If this ratio is applied to calculate intermediate offsets inside a processing
|
||||||
|
/// stream, then this ratio is approximate and can deviate +- some tens of milliseconds
|
||||||
|
/// from ideal offset, yet by end of the audio stream the duration ratio will become
|
||||||
|
/// exact.
|
||||||
|
///
|
||||||
|
/// Example: if processing with parameters "-tempo=15 -pitch=-3", the function
|
||||||
|
/// will return value 0.8695652... Now, if processing an audio stream whose duration
|
||||||
|
/// is exactly one million audio samples, then you can expect the processed
|
||||||
|
/// output duration be 0.869565 * 1000000 = 869565 samples.
|
||||||
|
double getInputOutputSampleRatio();
|
||||||
|
|
||||||
/// 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.
|
||||||
//
|
//
|
||||||
|
@ -286,6 +335,11 @@ public:
|
||||||
/// Returns number of samples currently unprocessed.
|
/// Returns number of samples currently unprocessed.
|
||||||
virtual uint numUnprocessedSamples() const;
|
virtual uint numUnprocessedSamples() const;
|
||||||
|
|
||||||
|
/// Return number of channels
|
||||||
|
uint numChannels() const
|
||||||
|
{
|
||||||
|
return channels;
|
||||||
|
}
|
||||||
|
|
||||||
/// Other handy functions that are implemented in the ancestor classes (see
|
/// Other handy functions that are implemented in the ancestor classes (see
|
||||||
/// classes 'FIFOProcessor' and 'FIFOSamplePipe')
|
/// classes 'FIFOProcessor' and 'FIFOSamplePipe')
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Last changed : $Date: 2014-10-05 19:20:24 +0300 (Sun, 05 Oct 2014) $
|
// Last changed : $Date: 2014-10-05 19:20:24 +0300 (su, 05 loka 2014) $
|
||||||
// File revision : $Revision: 4 $
|
// File revision : $Revision: 4 $
|
||||||
//
|
//
|
||||||
// $Id: WavFile.cpp 200 2014-10-05 16:20:24Z oparviai $
|
// $Id: WavFile.cpp 200 2014-10-05 16:20:24Z oparviai $
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Last changed : $Date: 2014-10-05 19:20:24 +0300 (Sun, 05 Oct 2014) $
|
// Last changed : $Date: 2014-10-05 19:20:24 +0300 (su, 05 loka 2014) $
|
||||||
// File revision : $Revision: 4 $
|
// File revision : $Revision: 4 $
|
||||||
//
|
//
|
||||||
// $Id: WavFile.h 200 2014-10-05 16:20:24Z oparviai $
|
// $Id: WavFile.h 200 2014-10-05 16:20:24Z oparviai $
|
||||||
|
|
|
@ -12,10 +12,10 @@
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Last changed : $Date: 2014-01-05 23:40:22 +0200 (Sun, 05 Jan 2014) $
|
// Last changed : $Date: 2016-01-12 19:26:21 +0200 (ti, 12 tammi 2016) $
|
||||||
// File revision : $Revision: 4 $
|
// File revision : $Revision: 4 $
|
||||||
//
|
//
|
||||||
// $Id: AAFilter.cpp 177 2014-01-05 21:40:22Z oparviai $
|
// $Id: AAFilter.cpp 240 2016-01-12 17:26:21Z oparviai $
|
||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
@ -49,7 +49,7 @@
|
||||||
|
|
||||||
using namespace soundtouch;
|
using namespace soundtouch;
|
||||||
|
|
||||||
#define PI 3.141592655357989
|
#define PI 3.14159265358979323846
|
||||||
#define TWOPI (2 * PI)
|
#define TWOPI (2 * PI)
|
||||||
|
|
||||||
// define this to save AA filter coefficients to a file
|
// define this to save AA filter coefficients to a file
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Last changed : $Date: 2014-01-07 21:41:23 +0200 (Tue, 07 Jan 2014) $
|
// Last changed : $Date: 2014-01-07 21:41:23 +0200 (ti, 07 tammi 2014) $
|
||||||
// File revision : $Revision: 4 $
|
// File revision : $Revision: 4 $
|
||||||
//
|
//
|
||||||
// $Id: AAFilter.h 187 2014-01-07 19:41:23Z oparviai $
|
// $Id: AAFilter.h 187 2014-01-07 19:41:23Z oparviai $
|
||||||
|
|
|
@ -26,10 +26,10 @@
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Last changed : $Date: 2015-02-21 23:24:29 +0200 (Sat, 21 Feb 2015) $
|
// Last changed : $Date: 2016-01-05 22:59:57 +0200 (ti, 05 tammi 2016) $
|
||||||
// File revision : $Revision: 4 $
|
// File revision : $Revision: 4 $
|
||||||
//
|
//
|
||||||
// $Id: BPMDetect.cpp 202 2015-02-21 21:24:29Z oparviai $
|
// $Id: BPMDetect.cpp 237 2016-01-05 20:59:57Z oparviai $
|
||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
@ -67,13 +67,18 @@ using namespace soundtouch;
|
||||||
#define INPUT_BLOCK_SAMPLES 2048
|
#define INPUT_BLOCK_SAMPLES 2048
|
||||||
#define DECIMATED_BLOCK_SAMPLES 256
|
#define DECIMATED_BLOCK_SAMPLES 256
|
||||||
|
|
||||||
/// decay constant for calculating RMS volume sliding average approximation
|
/// Target sample rate after decimation
|
||||||
/// (time constant is about 10 sec)
|
const int target_srate = 1000;
|
||||||
const float avgdecay = 0.99986f;
|
|
||||||
|
|
||||||
/// Normalization coefficient for calculating RMS sliding average approximation.
|
/// XCorr update sequence size, update in about 200msec chunks
|
||||||
const float avgnorm = (1 - avgdecay);
|
const int xcorr_update_sequence = 200;
|
||||||
|
|
||||||
|
/// XCorr decay time constant, decay to half in 30 seconds
|
||||||
|
/// If it's desired to have the system adapt quicker to beat rate
|
||||||
|
/// changes within a continuing music stream, then the
|
||||||
|
/// 'xcorr_decay_time_constant' value can be reduced, yet that
|
||||||
|
/// can increase possibility of glitches in bpm detection.
|
||||||
|
const double xcorr_decay_time_constant = 30.0;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -115,21 +120,8 @@ BPMDetect::BPMDetect(int numChannels, int aSampleRate)
|
||||||
decimateSum = 0;
|
decimateSum = 0;
|
||||||
decimateCount = 0;
|
decimateCount = 0;
|
||||||
|
|
||||||
envelopeAccu = 0;
|
|
||||||
|
|
||||||
// Initialize RMS volume accumulator to RMS level of 1500 (out of 32768) that's
|
|
||||||
// safe initial RMS signal level value for song data. This value is then adapted
|
|
||||||
// to the actual level during processing.
|
|
||||||
#ifdef SOUNDTOUCH_INTEGER_SAMPLES
|
|
||||||
// integer samples
|
|
||||||
RMSVolumeAccu = (1500 * 1500) / avgnorm;
|
|
||||||
#else
|
|
||||||
// float samples, scaled to range [-1..+1[
|
|
||||||
RMSVolumeAccu = (0.045f * 0.045f) / avgnorm;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// choose decimation factor so that result is approx. 1000 Hz
|
// choose decimation factor so that result is approx. 1000 Hz
|
||||||
decimateBy = sampleRate / 1000;
|
decimateBy = sampleRate / target_srate;
|
||||||
assert(decimateBy > 0);
|
assert(decimateBy > 0);
|
||||||
assert(INPUT_BLOCK_SAMPLES < decimateBy * DECIMATED_BLOCK_SAMPLES);
|
assert(INPUT_BLOCK_SAMPLES < decimateBy * DECIMATED_BLOCK_SAMPLES);
|
||||||
|
|
||||||
|
@ -226,6 +218,10 @@ void BPMDetect::updateXCorr(int process_samples)
|
||||||
assert(buffer->numSamples() >= (uint)(process_samples + windowLen));
|
assert(buffer->numSamples() >= (uint)(process_samples + windowLen));
|
||||||
|
|
||||||
pBuffer = buffer->ptrBegin();
|
pBuffer = buffer->ptrBegin();
|
||||||
|
|
||||||
|
// calculate decay factor for xcorr filtering
|
||||||
|
float xcorr_decay = (float)pow(0.5, 1.0 / (xcorr_decay_time_constant * target_srate / process_samples));
|
||||||
|
|
||||||
#pragma omp parallel for
|
#pragma omp parallel for
|
||||||
for (offs = windowStart; offs < windowLen; offs ++)
|
for (offs = windowStart; offs < windowLen; offs ++)
|
||||||
{
|
{
|
||||||
|
@ -237,51 +233,9 @@ void BPMDetect::updateXCorr(int process_samples)
|
||||||
{
|
{
|
||||||
sum += pBuffer[i] * pBuffer[i + offs]; // scaling the sub-result shouldn't be necessary
|
sum += pBuffer[i] * pBuffer[i + offs]; // scaling the sub-result shouldn't be necessary
|
||||||
}
|
}
|
||||||
// xcorr[offs] *= xcorr_decay; // decay 'xcorr' here with suitable coefficients
|
xcorr[offs] *= xcorr_decay; // decay 'xcorr' here with suitable time constant.
|
||||||
// if it's desired that the system adapts automatically to
|
|
||||||
// various bpms, e.g. in processing continouos music stream.
|
|
||||||
// The 'xcorr_decay' should be a value that's smaller than but
|
|
||||||
// close to one, and should also depend on 'process_samples' value.
|
|
||||||
|
|
||||||
xcorr[offs] += (float)sum;
|
xcorr[offs] += (float)fabs(sum);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Calculates envelope of the sample data
|
|
||||||
void BPMDetect::calcEnvelope(SAMPLETYPE *samples, int numsamples)
|
|
||||||
{
|
|
||||||
const static double decay = 0.7f; // decay constant for smoothing the envelope
|
|
||||||
const static double norm = (1 - decay);
|
|
||||||
|
|
||||||
int i;
|
|
||||||
LONG_SAMPLETYPE out;
|
|
||||||
double val;
|
|
||||||
|
|
||||||
for (i = 0; i < numsamples; i ++)
|
|
||||||
{
|
|
||||||
// calc average RMS volume
|
|
||||||
RMSVolumeAccu *= avgdecay;
|
|
||||||
val = (float)fabs((float)samples[i]);
|
|
||||||
RMSVolumeAccu += val * val;
|
|
||||||
|
|
||||||
// cut amplitudes that are below cutoff ~2 times RMS volume
|
|
||||||
// (we're interested in peak values, not the silent moments)
|
|
||||||
if (val < 0.5 * sqrt(RMSVolumeAccu * avgnorm))
|
|
||||||
{
|
|
||||||
val = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// smooth amplitude envelope
|
|
||||||
envelopeAccu *= decay;
|
|
||||||
envelopeAccu += val;
|
|
||||||
out = (LONG_SAMPLETYPE)(envelopeAccu * norm);
|
|
||||||
|
|
||||||
#ifdef SOUNDTOUCH_INTEGER_SAMPLES
|
|
||||||
// cut peaks (shouldn't be necessary though)
|
|
||||||
if (out > 32767) out = 32767;
|
|
||||||
#endif // SOUNDTOUCH_INTEGER_SAMPLES
|
|
||||||
samples[i] = (SAMPLETYPE)out;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,23 +258,16 @@ void BPMDetect::inputSamples(const SAMPLETYPE *samples, int numSamples)
|
||||||
samples += block * channels;
|
samples += block * channels;
|
||||||
numSamples -= block;
|
numSamples -= block;
|
||||||
|
|
||||||
// envelope new samples and add them to buffer
|
|
||||||
calcEnvelope(decimated, decSamples);
|
|
||||||
buffer->putSamples(decimated, decSamples);
|
buffer->putSamples(decimated, decSamples);
|
||||||
}
|
}
|
||||||
|
|
||||||
// when the buffer has enought samples for processing...
|
// when the buffer has enought samples for processing...
|
||||||
if ((int)buffer->numSamples() > windowLen)
|
while ((int)buffer->numSamples() >= windowLen + xcorr_update_sequence)
|
||||||
{
|
{
|
||||||
int processLength;
|
|
||||||
|
|
||||||
// how many samples are processed
|
|
||||||
processLength = (int)buffer->numSamples() - windowLen;
|
|
||||||
|
|
||||||
// ... calculate autocorrelations for oldest samples...
|
// ... calculate autocorrelations for oldest samples...
|
||||||
updateXCorr(processLength);
|
updateXCorr(xcorr_update_sequence);
|
||||||
// ... and remove them from the buffer
|
// ... and remove these from the buffer
|
||||||
buffer->receiveSamples(processLength);
|
buffer->receiveSamples(xcorr_update_sequence);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Last changed : $Date: 2012-11-08 20:53:01 +0200 (Thu, 08 Nov 2012) $
|
// Last changed : $Date: 2012-11-08 20:53:01 +0200 (to, 08 marras 2012) $
|
||||||
// File revision : $Revision: 4 $
|
// File revision : $Revision: 4 $
|
||||||
//
|
//
|
||||||
// $Id: FIFOSampleBuffer.cpp 160 2012-11-08 18:53:01Z oparviai $
|
// $Id: FIFOSampleBuffer.cpp 160 2012-11-08 18:53:01Z oparviai $
|
||||||
|
|
|
@ -2,19 +2,25 @@
|
||||||
///
|
///
|
||||||
/// General FIR digital filter routines with MMX optimization.
|
/// General FIR digital filter routines with MMX optimization.
|
||||||
///
|
///
|
||||||
/// Note : MMX optimized functions reside in a separate, platform-specific file,
|
/// Notes : MMX optimized functions reside in a separate, platform-specific file,
|
||||||
/// e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp'
|
/// e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp'
|
||||||
///
|
///
|
||||||
|
/// This source file contains OpenMP optimizations that allow speeding up the
|
||||||
|
/// corss-correlation algorithm by executing it in several threads / CPU cores
|
||||||
|
/// in parallel. See the following article link for more detailed discussion
|
||||||
|
/// about SoundTouch OpenMP optimizations:
|
||||||
|
/// http://www.softwarecoven.com/parallel-computing-in-embedded-mobile-devices
|
||||||
|
///
|
||||||
/// 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: 2015-02-21 23:24:29 +0200 (Sat, 21 Feb 2015) $
|
// Last changed : $Date: 2015-11-05 19:46:08 +0200 (to, 05 marras 2015) $
|
||||||
// File revision : $Revision: 4 $
|
// File revision : $Revision: 4 $
|
||||||
//
|
//
|
||||||
// $Id: FIRFilter.cpp 202 2015-02-21 21:24:29Z oparviai $
|
// $Id: FIRFilter.cpp 234 2015-11-05 17:46:08Z oparviai $
|
||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Last changed : $Date: 2015-02-21 23:24:29 +0200 (Sat, 21 Feb 2015) $
|
// Last changed : $Date: 2015-02-21 23:24:29 +0200 (la, 21 helmi 2015) $
|
||||||
// File revision : $Revision: 4 $
|
// File revision : $Revision: 4 $
|
||||||
//
|
//
|
||||||
// $Id: FIRFilter.h 202 2015-02-21 21:24:29Z oparviai $
|
// $Id: FIRFilter.h 202 2015-02-21 21:24:29Z oparviai $
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Last changed : $Date: 2015-05-18 18:22:02 +0300 (Mon, 18 May 2015) $
|
// Last changed : $Date: 2015-05-18 18:22:02 +0300 (ma, 18 touko 2015) $
|
||||||
// File revision : $Revision: 4 $
|
// File revision : $Revision: 4 $
|
||||||
//
|
//
|
||||||
// $Id: PeakFinder.cpp 213 2015-05-18 15:22:02Z oparviai $
|
// $Id: PeakFinder.cpp 213 2015-05-18 15:22:02Z oparviai $
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Last changed : $Date: 2011-12-30 22:33:46 +0200 (Fri, 30 Dec 2011) $
|
// Last changed : $Date: 2011-12-30 22:33:46 +0200 (pe, 30 joulu 2011) $
|
||||||
// File revision : $Revision: 4 $
|
// File revision : $Revision: 4 $
|
||||||
//
|
//
|
||||||
// $Id: PeakFinder.h 132 2011-12-30 20:33:46Z oparviai $
|
// $Id: PeakFinder.h 132 2011-12-30 20:33:46Z oparviai $
|
||||||
|
|
|
@ -10,10 +10,10 @@
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Last changed : $Date: 2015-07-26 17:45:48 +0300 (Sun, 26 Jul 2015) $
|
// Last changed : $Date: 2016-10-15 22:34:59 +0300 (la, 15 loka 2016) $
|
||||||
// File revision : $Revision: 4 $
|
// File revision : $Revision: 4 $
|
||||||
//
|
//
|
||||||
// $Id: RateTransposer.cpp 225 2015-07-26 14:45:48Z oparviai $
|
// $Id: RateTransposer.cpp 243 2016-10-15 19:34:59Z oparviai $
|
||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
@ -208,6 +208,13 @@ int RateTransposer::isEmpty() const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Return approximate initial input-output latency
|
||||||
|
int RateTransposer::getLatency() const
|
||||||
|
{
|
||||||
|
return (bUseAAFilter) ? pAAFilter->getLength() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// TransposerBase - Base class for interpolation
|
// TransposerBase - Base class for interpolation
|
||||||
|
|
|
@ -14,10 +14,10 @@
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Last changed : $Date: 2015-07-26 17:45:48 +0300 (Sun, 26 Jul 2015) $
|
// Last changed : $Date: 2016-10-15 22:34:59 +0300 (la, 15 loka 2016) $
|
||||||
// File revision : $Revision: 4 $
|
// File revision : $Revision: 4 $
|
||||||
//
|
//
|
||||||
// $Id: RateTransposer.h 225 2015-07-26 14:45:48Z oparviai $
|
// $Id: RateTransposer.h 243 2016-10-15 19:34:59Z oparviai $
|
||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
@ -172,6 +172,9 @@ public:
|
||||||
|
|
||||||
/// Returns nonzero if there aren't any samples available for outputting.
|
/// Returns nonzero if there aren't any samples available for outputting.
|
||||||
int isEmpty() const;
|
int isEmpty() const;
|
||||||
|
|
||||||
|
/// Return approximate initial input-output latency
|
||||||
|
int getLatency() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,10 +41,10 @@
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Last changed : $Date: 2015-07-26 17:45:48 +0300 (Sun, 26 Jul 2015) $
|
// Last changed : $Date: 2016-10-15 22:34:59 +0300 (la, 15 loka 2016) $
|
||||||
// File revision : $Revision: 4 $
|
// File revision : $Revision: 4 $
|
||||||
//
|
//
|
||||||
// $Id: SoundTouch.cpp 225 2015-07-26 14:45:48Z oparviai $
|
// $Id: SoundTouch.cpp 243 2016-10-15 19:34:59Z oparviai $
|
||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
@ -110,8 +110,8 @@ SoundTouch::SoundTouch()
|
||||||
|
|
||||||
calcEffectiveRateAndTempo();
|
calcEffectiveRateAndTempo();
|
||||||
|
|
||||||
samplesExpectedOut = 0;
|
samplesExpectedOut = 0;
|
||||||
samplesOutput = 0;
|
samplesOutput = 0;
|
||||||
|
|
||||||
channels = 0;
|
channels = 0;
|
||||||
bSrateSet = false;
|
bSrateSet = false;
|
||||||
|
@ -149,7 +149,7 @@ void SoundTouch::setChannels(uint numChannels)
|
||||||
/*if (numChannels != 1 && numChannels != 2)
|
/*if (numChannels != 1 && numChannels != 2)
|
||||||
{
|
{
|
||||||
//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);
|
||||||
|
@ -240,11 +240,11 @@ void SoundTouch::calcEffectiveRateAndTempo()
|
||||||
double oldTempo = tempo;
|
double oldTempo = tempo;
|
||||||
double 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)
|
||||||
|
@ -321,9 +321,9 @@ void SoundTouch::putSamples(const SAMPLETYPE *samples, uint nSamples)
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// accumulate how many samples are expected out from processing, given the current
|
// accumulate how many samples are expected out from processing, given the current
|
||||||
// processing setting
|
// processing setting
|
||||||
samplesExpectedOut += (double)nSamples / ((double)rate * (double)tempo);
|
samplesExpectedOut += (double)nSamples / ((double)rate * (double)tempo);
|
||||||
|
|
||||||
#ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER
|
#ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER
|
||||||
if (rate <= 1.0f)
|
if (rate <= 1.0f)
|
||||||
|
@ -354,23 +354,24 @@ void SoundTouch::putSamples(const SAMPLETYPE *samples, uint nSamples)
|
||||||
void SoundTouch::flush()
|
void SoundTouch::flush()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int numStillExpected;
|
int numStillExpected;
|
||||||
SAMPLETYPE *buff = new SAMPLETYPE[128 * channels];
|
SAMPLETYPE *buff = new SAMPLETYPE[128 * channels];
|
||||||
|
|
||||||
// how many samples are still expected to output
|
// how many samples are still expected to output
|
||||||
numStillExpected = (int)((long)(samplesExpectedOut + 0.5) - samplesOutput);
|
numStillExpected = (int)((long)(samplesExpectedOut + 0.5) - samplesOutput);
|
||||||
|
if (numStillExpected < 0) numStillExpected = 0;
|
||||||
|
|
||||||
memset(buff, 0, 128 * 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
|
||||||
// 24ksamples in any case)
|
// 24ksamples in any case)
|
||||||
for (i = 0; (numStillExpected > (int)numSamples()) && (i < 200); i ++)
|
for (i = 0; (numStillExpected > (int)numSamples()) && (i < 200); i ++)
|
||||||
{
|
{
|
||||||
putSamples(buff, 128);
|
putSamples(buff, 128);
|
||||||
}
|
}
|
||||||
|
|
||||||
adjustAmountOfSamples(numStillExpected);
|
adjustAmountOfSamples(numStillExpected);
|
||||||
|
|
||||||
delete[] buff;
|
delete[] buff;
|
||||||
|
|
||||||
|
@ -446,7 +447,7 @@ int SoundTouch::getSetting(int settingId) const
|
||||||
return pRateTransposer->getAAFilter()->getLength();
|
return pRateTransposer->getAAFilter()->getLength();
|
||||||
|
|
||||||
case SETTING_USE_QUICKSEEK :
|
case SETTING_USE_QUICKSEEK :
|
||||||
return (uint) pTDStretch->isQuickSeekEnabled();
|
return (uint)pTDStretch->isQuickSeekEnabled();
|
||||||
|
|
||||||
case SETTING_SEQUENCE_MS:
|
case SETTING_SEQUENCE_MS:
|
||||||
pTDStretch->getParameters(NULL, &temp, NULL, NULL);
|
pTDStretch->getParameters(NULL, &temp, NULL, NULL);
|
||||||
|
@ -460,23 +461,65 @@ int SoundTouch::getSetting(int settingId) const
|
||||||
pTDStretch->getParameters(NULL, NULL, NULL, &temp);
|
pTDStretch->getParameters(NULL, NULL, NULL, &temp);
|
||||||
return temp;
|
return temp;
|
||||||
|
|
||||||
case SETTING_NOMINAL_INPUT_SEQUENCE :
|
case SETTING_NOMINAL_INPUT_SEQUENCE :
|
||||||
return pTDStretch->getInputSampleReq();
|
{
|
||||||
|
int size = pTDStretch->getInputSampleReq();
|
||||||
|
|
||||||
case SETTING_NOMINAL_OUTPUT_SEQUENCE :
|
#ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER
|
||||||
return pTDStretch->getOutputBatchSize();
|
if (rate <= 1.0)
|
||||||
|
{
|
||||||
|
// transposing done before timestretch, which impacts latency
|
||||||
|
return (int)(size * rate + 0.5);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
default :
|
case SETTING_NOMINAL_OUTPUT_SEQUENCE :
|
||||||
|
{
|
||||||
|
int size = pTDStretch->getOutputBatchSize();
|
||||||
|
|
||||||
|
if (rate > 1.0)
|
||||||
|
{
|
||||||
|
// transposing done after timestretch, which impacts latency
|
||||||
|
return (int)(size / rate + 0.5);
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SETTING_INITIAL_LATENCY:
|
||||||
|
{
|
||||||
|
double latency = pTDStretch->getLatency();
|
||||||
|
int latency_tr = pRateTransposer->getLatency();
|
||||||
|
|
||||||
|
#ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER
|
||||||
|
if (rate <= 1.0)
|
||||||
|
{
|
||||||
|
// transposing done before timestretch, which impacts latency
|
||||||
|
latency = (latency + latency_tr) * rate;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
latency += (double)latency_tr / rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int)(latency + 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
samplesExpectedOut = 0;
|
||||||
|
samplesOutput = 0;
|
||||||
pRateTransposer->clear();
|
pRateTransposer->clear();
|
||||||
pTDStretch->clear();
|
pTDStretch->clear();
|
||||||
}
|
}
|
||||||
|
@ -507,9 +550,9 @@ uint SoundTouch::numUnprocessedSamples() const
|
||||||
/// \return Number of samples returned.
|
/// \return Number of samples returned.
|
||||||
uint SoundTouch::receiveSamples(SAMPLETYPE *output, uint maxSamples)
|
uint SoundTouch::receiveSamples(SAMPLETYPE *output, uint maxSamples)
|
||||||
{
|
{
|
||||||
uint ret = FIFOProcessor::receiveSamples(output, maxSamples);
|
uint ret = FIFOProcessor::receiveSamples(output, maxSamples);
|
||||||
samplesOutput += (long)ret;
|
samplesOutput += (long)ret;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -520,7 +563,16 @@ uint SoundTouch::receiveSamples(SAMPLETYPE *output, uint maxSamples)
|
||||||
/// with 'ptrBegin' function.
|
/// with 'ptrBegin' function.
|
||||||
uint SoundTouch::receiveSamples(uint maxSamples)
|
uint SoundTouch::receiveSamples(uint maxSamples)
|
||||||
{
|
{
|
||||||
uint ret = FIFOProcessor::receiveSamples(maxSamples);
|
uint ret = FIFOProcessor::receiveSamples(maxSamples);
|
||||||
samplesOutput += (long)ret;
|
samplesOutput += (long)ret;
|
||||||
return ret;
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Get ratio between input and output audio durations, useful for calculating
|
||||||
|
/// processed output duration: if you'll process a stream of N samples, then
|
||||||
|
/// you can expect to get out N * getInputOutputSampleRatio() samples.
|
||||||
|
double SoundTouch::getInputOutputSampleRatio()
|
||||||
|
{
|
||||||
|
return 1.0 / (tempo * rate);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,14 @@
|
||||||
/// while maintaining the original pitch by using a time domain WSOLA-like
|
/// while maintaining the original pitch by using a time domain WSOLA-like
|
||||||
/// method with several performance-increasing tweaks.
|
/// method with several performance-increasing tweaks.
|
||||||
///
|
///
|
||||||
/// Note : MMX optimized functions reside in a separate, platform-specific
|
/// Notes : MMX optimized functions reside in a separate, platform-specific
|
||||||
/// file, e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp'
|
/// file, e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp'.
|
||||||
|
///
|
||||||
|
/// This source file contains OpenMP optimizations that allow speeding up the
|
||||||
|
/// corss-correlation algorithm by executing it in several threads / CPU cores
|
||||||
|
/// in parallel. See the following article link for more detailed discussion
|
||||||
|
/// about SoundTouch OpenMP optimizations:
|
||||||
|
/// http://www.softwarecoven.com/parallel-computing-in-embedded-mobile-devices
|
||||||
///
|
///
|
||||||
/// Author : Copyright (c) Olli Parviainen
|
/// Author : Copyright (c) Olli Parviainen
|
||||||
/// Author e-mail : oparviai 'at' iki.fi
|
/// Author e-mail : oparviai 'at' iki.fi
|
||||||
|
@ -13,10 +19,10 @@
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Last changed : $Date: 2015-08-09 00:00:15 +0300 (Sun, 09 Aug 2015) $
|
// Last changed : $Date: 2017-04-07 22:01:22 +0300 (pe, 07 huhti 2017) $
|
||||||
// File revision : $Revision: 1.12 $
|
// File revision : $Revision: 1.12 $
|
||||||
//
|
//
|
||||||
// $Id: TDStretch.cpp 226 2015-08-08 21:00:15Z oparviai $
|
// $Id: TDStretch.cpp 249 2017-04-07 19:01:22Z oparviai $
|
||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
@ -219,6 +225,7 @@ void TDStretch::clearInput()
|
||||||
{
|
{
|
||||||
inputBuffer.clear();
|
inputBuffer.clear();
|
||||||
clearMidBuffer();
|
clearMidBuffer();
|
||||||
|
isBeginning = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -297,12 +304,13 @@ int TDStretch::seekBestOverlapPositionFull(const SAMPLETYPE *refPos)
|
||||||
int i;
|
int i;
|
||||||
double norm;
|
double norm;
|
||||||
|
|
||||||
bestCorr = FLT_MIN;
|
bestCorr = -FLT_MAX;
|
||||||
bestOffs = 0;
|
bestOffs = 0;
|
||||||
|
|
||||||
// Scans for the best correlation value by testing each possible position
|
// Scans for the best correlation value by testing each possible position
|
||||||
// over the permitted range.
|
// over the permitted range.
|
||||||
bestCorr = calcCrossCorr(refPos, pMidBuffer, norm);
|
bestCorr = calcCrossCorr(refPos, pMidBuffer, norm);
|
||||||
|
bestCorr = (bestCorr + 0.1) * 0.75;
|
||||||
|
|
||||||
#pragma omp parallel for
|
#pragma omp parallel for
|
||||||
for (i = 1; i < seekLength; i ++)
|
for (i = 1; i < seekLength; i ++)
|
||||||
|
@ -373,12 +381,10 @@ int TDStretch::seekBestOverlapPositionQuick(const SAMPLETYPE *refPos)
|
||||||
|
|
||||||
// note: 'float' types used in this function in case that the platform would need to use software-fp
|
// note: 'float' types used in this function in case that the platform would need to use software-fp
|
||||||
|
|
||||||
bestCorr = FLT_MIN;
|
bestCorr =
|
||||||
bestOffs = SCANWIND;
|
bestCorr2 = -FLT_MAX;
|
||||||
bestCorr2 = FLT_MIN;
|
bestOffs =
|
||||||
bestOffs2 = 0;
|
bestOffs2 = SCANWIND;
|
||||||
|
|
||||||
int best = 0;
|
|
||||||
|
|
||||||
// Scans for the best correlation value by testing each possible position
|
// Scans for the best correlation value by testing each possible position
|
||||||
// over the permitted range. Look for two best matches on the first pass to
|
// over the permitted range. Look for two best matches on the first pass to
|
||||||
|
@ -436,7 +442,6 @@ int TDStretch::seekBestOverlapPositionQuick(const SAMPLETYPE *refPos)
|
||||||
{
|
{
|
||||||
bestCorr = corr;
|
bestCorr = corr;
|
||||||
bestOffs = i;
|
bestOffs = i;
|
||||||
best = 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,7 +463,6 @@ int TDStretch::seekBestOverlapPositionQuick(const SAMPLETYPE *refPos)
|
||||||
{
|
{
|
||||||
bestCorr = corr;
|
bestCorr = corr;
|
||||||
bestOffs = i;
|
bestOffs = i;
|
||||||
best = 2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -520,13 +524,13 @@ void TDStretch::calcSeqParameters()
|
||||||
#define AUTOSEQ_TEMPO_TOP 2.0 // auto setting top tempo range (+100%)
|
#define AUTOSEQ_TEMPO_TOP 2.0 // auto setting top tempo range (+100%)
|
||||||
|
|
||||||
// sequence-ms setting values at above low & top tempo
|
// sequence-ms setting values at above low & top tempo
|
||||||
#define AUTOSEQ_AT_MIN 125.0
|
#define AUTOSEQ_AT_MIN 90.0
|
||||||
#define AUTOSEQ_AT_MAX 50.0
|
#define AUTOSEQ_AT_MAX 40.0
|
||||||
#define AUTOSEQ_K ((AUTOSEQ_AT_MAX - AUTOSEQ_AT_MIN) / (AUTOSEQ_TEMPO_TOP - AUTOSEQ_TEMPO_LOW))
|
#define AUTOSEQ_K ((AUTOSEQ_AT_MAX - AUTOSEQ_AT_MIN) / (AUTOSEQ_TEMPO_TOP - AUTOSEQ_TEMPO_LOW))
|
||||||
#define AUTOSEQ_C (AUTOSEQ_AT_MIN - (AUTOSEQ_K) * (AUTOSEQ_TEMPO_LOW))
|
#define AUTOSEQ_C (AUTOSEQ_AT_MIN - (AUTOSEQ_K) * (AUTOSEQ_TEMPO_LOW))
|
||||||
|
|
||||||
// seek-window-ms setting values at above low & top tempoq
|
// seek-window-ms setting values at above low & top tempoq
|
||||||
#define AUTOSEEK_AT_MIN 25.0
|
#define AUTOSEEK_AT_MIN 20.0
|
||||||
#define AUTOSEEK_AT_MAX 15.0
|
#define AUTOSEEK_AT_MAX 15.0
|
||||||
#define AUTOSEEK_K ((AUTOSEEK_AT_MAX - AUTOSEEK_AT_MIN) / (AUTOSEQ_TEMPO_TOP - AUTOSEQ_TEMPO_LOW))
|
#define AUTOSEEK_K ((AUTOSEEK_AT_MAX - AUTOSEEK_AT_MIN) / (AUTOSEQ_TEMPO_TOP - AUTOSEQ_TEMPO_LOW))
|
||||||
#define AUTOSEEK_C (AUTOSEEK_AT_MIN - (AUTOSEEK_K) * (AUTOSEQ_TEMPO_LOW))
|
#define AUTOSEEK_C (AUTOSEEK_AT_MIN - (AUTOSEEK_K) * (AUTOSEQ_TEMPO_LOW))
|
||||||
|
@ -637,7 +641,8 @@ void TDStretch::processNominalTempo()
|
||||||
// the result into 'outputBuffer'
|
// the result into 'outputBuffer'
|
||||||
void TDStretch::processSamples()
|
void TDStretch::processSamples()
|
||||||
{
|
{
|
||||||
int ovlSkip, offset;
|
int ovlSkip;
|
||||||
|
int offset = 0;
|
||||||
int temp;
|
int temp;
|
||||||
|
|
||||||
/* Removed this small optimization - can introduce a click to sound when tempo setting
|
/* Removed this small optimization - can introduce a click to sound when tempo setting
|
||||||
|
@ -654,35 +659,61 @@ void TDStretch::processSamples()
|
||||||
// to form a processing frame.
|
// to form a processing frame.
|
||||||
while ((int)inputBuffer.numSamples() >= sampleReq)
|
while ((int)inputBuffer.numSamples() >= sampleReq)
|
||||||
{
|
{
|
||||||
// If tempo differs from the normal ('SCALE'), scan for the best overlapping
|
if (isBeginning == false)
|
||||||
// position
|
{
|
||||||
offset = seekBestOverlapPosition(inputBuffer.ptrBegin());
|
// apart from the very beginning of the track,
|
||||||
|
// scan for the best overlapping position & do overlap-add
|
||||||
|
offset = seekBestOverlapPosition(inputBuffer.ptrBegin());
|
||||||
|
|
||||||
// Mix the samples in the 'inputBuffer' at position of 'offset' with the
|
// Mix the samples in the 'inputBuffer' at position of 'offset' with the
|
||||||
// samples in 'midBuffer' using sliding overlapping
|
// samples in 'midBuffer' using sliding overlapping
|
||||||
// ... first partially overlap with the end of the previous sequence
|
// ... first partially overlap with the end of the previous sequence
|
||||||
// (that's in 'midBuffer')
|
// (that's in 'midBuffer')
|
||||||
overlap(outputBuffer.ptrEnd((uint)overlapLength), inputBuffer.ptrBegin(), (uint)offset);
|
overlap(outputBuffer.ptrEnd((uint)overlapLength), inputBuffer.ptrBegin(), (uint)offset);
|
||||||
outputBuffer.putSamples((uint)overlapLength);
|
outputBuffer.putSamples((uint)overlapLength);
|
||||||
|
offset += overlapLength;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Adjust processing offset at beginning of track by not perform initial overlapping
|
||||||
|
// and compensating that in the 'input buffer skip' calculation
|
||||||
|
isBeginning = false;
|
||||||
|
int skip = (int)(tempo * overlapLength + 0.5);
|
||||||
|
|
||||||
|
#ifdef SOUNDTOUCH_ALLOW_NONEXACT_SIMD_OPTIMIZATION
|
||||||
|
#ifdef SOUNDTOUCH_ALLOW_SSE
|
||||||
|
// if SSE mode, round the skip amount to value corresponding to aligned memory address
|
||||||
|
if (channels == 1)
|
||||||
|
{
|
||||||
|
skip &= -4;
|
||||||
|
}
|
||||||
|
else if (channels == 2)
|
||||||
|
{
|
||||||
|
skip &= -2;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
skipFract -= skip;
|
||||||
|
assert(nominalSkip >= -skipFract);
|
||||||
|
}
|
||||||
|
|
||||||
// ... then copy sequence samples from 'inputBuffer' to output:
|
// ... then copy sequence samples from 'inputBuffer' to output:
|
||||||
|
|
||||||
// length of sequence
|
|
||||||
temp = (seekWindowLength - 2 * overlapLength);
|
|
||||||
|
|
||||||
// crosscheck that we don't have buffer overflow...
|
// crosscheck that we don't have buffer overflow...
|
||||||
if ((int)inputBuffer.numSamples() < (offset + temp + overlapLength * 2))
|
if ((int)inputBuffer.numSamples() < (offset + seekWindowLength - overlapLength))
|
||||||
{
|
{
|
||||||
continue; // just in case, shouldn't really happen
|
continue; // just in case, shouldn't really happen
|
||||||
}
|
}
|
||||||
|
|
||||||
outputBuffer.putSamples(inputBuffer.ptrBegin() + channels * (offset + overlapLength), (uint)temp);
|
// length of sequence
|
||||||
|
temp = (seekWindowLength - 2 * overlapLength);
|
||||||
|
outputBuffer.putSamples(inputBuffer.ptrBegin() + channels * offset, (uint)temp);
|
||||||
|
|
||||||
// Copies the end of the current sequence from 'inputBuffer' to
|
// Copies the end of the current sequence from 'inputBuffer' to
|
||||||
// 'midBuffer' for being mixed with the beginning of the next
|
// 'midBuffer' for being mixed with the beginning of the next
|
||||||
// processing sequence and so on
|
// processing sequence and so on
|
||||||
assert((offset + temp + overlapLength * 2) <= (int)inputBuffer.numSamples());
|
assert((offset + temp + overlapLength) <= (int)inputBuffer.numSamples());
|
||||||
memcpy(pMidBuffer, inputBuffer.ptrBegin() + channels * (offset + temp + overlapLength),
|
memcpy(pMidBuffer, inputBuffer.ptrBegin() + channels * (offset + temp),
|
||||||
channels * sizeof(SAMPLETYPE) * overlapLength);
|
channels * sizeof(SAMPLETYPE) * overlapLength);
|
||||||
|
|
||||||
// Remove the processed samples from the input buffer. Update
|
// Remove the processed samples from the input buffer. Update
|
||||||
|
@ -879,7 +910,12 @@ double TDStretch::calcCrossCorr(const short *mixingPos, const short *compare, do
|
||||||
|
|
||||||
if (lnorm > maxnorm)
|
if (lnorm > maxnorm)
|
||||||
{
|
{
|
||||||
maxnorm = lnorm;
|
// modify 'maxnorm' inside critical section to avoid multi-access conflict if in OpenMP mode
|
||||||
|
#pragma omp critical
|
||||||
|
if (lnorm > maxnorm)
|
||||||
|
{
|
||||||
|
maxnorm = lnorm;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Normalize result by dividing by sqrt(norm) - this step is easiest
|
// Normalize result by dividing by sqrt(norm) - this step is easiest
|
||||||
// done using floating point operation
|
// done using floating point operation
|
||||||
|
|
|
@ -13,10 +13,10 @@
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Last changed : $Date: 2015-08-09 00:00:15 +0300 (Sun, 09 Aug 2015) $
|
// Last changed : $Date: 2016-10-20 19:30:11 +0300 (to, 20 loka 2016) $
|
||||||
// File revision : $Revision: 4 $
|
// File revision : $Revision: 4 $
|
||||||
//
|
//
|
||||||
// $Id: TDStretch.h 226 2015-08-08 21:00:15Z oparviai $
|
// $Id: TDStretch.h 244 2016-10-20 16:30:11Z oparviai $
|
||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
@ -134,6 +134,7 @@ protected:
|
||||||
bool bQuickSeek;
|
bool bQuickSeek;
|
||||||
bool bAutoSeqSetting;
|
bool bAutoSeqSetting;
|
||||||
bool bAutoSeekSetting;
|
bool bAutoSeekSetting;
|
||||||
|
bool isBeginning;
|
||||||
|
|
||||||
SAMPLETYPE *pMidBuffer;
|
SAMPLETYPE *pMidBuffer;
|
||||||
SAMPLETYPE *pMidBufferUnaligned;
|
SAMPLETYPE *pMidBufferUnaligned;
|
||||||
|
@ -247,6 +248,13 @@ public:
|
||||||
{
|
{
|
||||||
return seekWindowLength - overlapLength;
|
return seekWindowLength - overlapLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// return approximate initial input-output latency
|
||||||
|
int getLatency() const
|
||||||
|
{
|
||||||
|
return sampleReq;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Last changed : $Date: 2008-02-10 18:26:55 +0200 (Sun, 10 Feb 2008) $
|
// Last changed : $Date: 2008-02-10 18:26:55 +0200 (su, 10 helmi 2008) $
|
||||||
// File revision : $Revision: 4 $
|
// File revision : $Revision: 4 $
|
||||||
//
|
//
|
||||||
// $Id: cpu_detect.h 11 2008-02-10 16:26:55Z oparviai $
|
// $Id: cpu_detect.h 11 2008-02-10 16:26:55Z oparviai $
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Last changed : $Date: 2014-01-07 20:24:28 +0200 (Tue, 07 Jan 2014) $
|
// Last changed : $Date: 2014-01-07 20:24:28 +0200 (ti, 07 tammi 2014) $
|
||||||
// File revision : $Revision: 4 $
|
// File revision : $Revision: 4 $
|
||||||
//
|
//
|
||||||
// $Id: cpu_detect_x86.cpp 183 2014-01-07 18:24:28Z oparviai $
|
// $Id: cpu_detect_x86.cpp 183 2014-01-07 18:24:28Z oparviai $
|
||||||
|
|
|
@ -20,10 +20,10 @@
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Last changed : $Date: 2015-08-09 00:00:15 +0300 (Sun, 09 Aug 2015) $
|
// Last changed : $Date: 2017-03-05 15:56:03 +0200 (su, 05 maalis 2017) $
|
||||||
// File revision : $Revision: 4 $
|
// File revision : $Revision: 4 $
|
||||||
//
|
//
|
||||||
// $Id: mmx_optimized.cpp 226 2015-08-08 21:00:15Z oparviai $
|
// $Id: mmx_optimized.cpp 247 2017-03-05 13:56:03Z oparviai $
|
||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
@ -125,7 +125,12 @@ double TDStretchMMX::calcCrossCorr(const short *pV1, const short *pV2, double &d
|
||||||
|
|
||||||
if (norm > (long)maxnorm)
|
if (norm > (long)maxnorm)
|
||||||
{
|
{
|
||||||
maxnorm = norm;
|
// modify 'maxnorm' inside critical section to avoid multi-access conflict if in OpenMP mode
|
||||||
|
#pragma omp critical
|
||||||
|
if (norm > (long)maxnorm)
|
||||||
|
{
|
||||||
|
maxnorm = norm;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normalize result by dividing by sqrt(norm) - this step is easiest
|
// Normalize result by dividing by sqrt(norm) - this step is easiest
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Last changed : $Date: 2015-08-09 00:00:15 +0300 (Sun, 09 Aug 2015) $
|
// Last changed : $Date: 2015-08-09 00:00:15 +0300 (su, 09 elo 2015) $
|
||||||
// File revision : $Revision: 4 $
|
// File revision : $Revision: 4 $
|
||||||
//
|
//
|
||||||
// $Id: sse_optimized.cpp 226 2015-08-08 21:00:15Z oparviai $
|
// $Id: sse_optimized.cpp 226 2015-08-08 21:00:15Z oparviai $
|
||||||
|
|
Loading…
Reference in New Issue