diff --git a/README.html b/README.html
index 5b0e2a5..71ef801 100644
--- a/README.html
+++ b/README.html
@@ -18,7 +18,7 @@
-SoundTouch audio processing library v1.5.0
+SoundTouch audio processing library v1.5.1pre
SoundTouch library Copyright © Olli
Parviainen 2001-2009
@@ -536,6 +536,13 @@ estimates the BPM rate:
5. Change History
5.1. SoundTouch library Change History
+1.5.1pre:
+
+- Added automatic cutoff threshold adaptation to beat detection routine to
+ better adapt BPM calculation to different types of music
+
+
+
1.5.0:
- Added normalization to correlation calculation and improvement automatic seek/sequence parameter calculation to improve sound quality
@@ -657,7 +664,15 @@ files.
5.2. SoundStretch application Change
History
-1.4.0:
+v1.5.0:
+
+- Added "-speech" switch to activate algorithm parameters more
+ suitable for speech processing than the default parameters tuned for music
+ processing.
+
+
+
+v1.4.0:
- Moved BPM detection routines from SoundStretch application into SoundTouch
library
diff --git a/include/BPMDetect.h b/include/BPMDetect.h
index 423de02..ff1d3c4 100644
--- a/include/BPMDetect.h
+++ b/include/BPMDetect.h
@@ -78,10 +78,19 @@ protected:
float *xcorr;
/// Amplitude envelope sliding average approximation level accumulator
- float envelopeAccu;
+ double envelopeAccu;
/// RMS volume sliding average approximation level accumulator
- float RMSVolumeAccu;
+ double RMSVolumeAccu;
+
+ /// Level below which to cut off signals
+ double cutCoeff;
+
+ /// Accumulator for accounting what proportion of samples exceed cutCoeff level
+ double aboveCutAccu;
+
+ /// Accumulator for total samples to calculate proportion of samples that exceed cutCoeff level
+ double totalAccu;
/// Sample average counter.
int decimateCount;
diff --git a/include/SoundTouch.h b/include/SoundTouch.h
index ee33ca8..62bf27a 100644
--- a/include/SoundTouch.h
+++ b/include/SoundTouch.h
@@ -79,10 +79,10 @@ namespace soundtouch
{
/// Soundtouch library version string
-#define SOUNDTOUCH_VERSION "1.5.0"
+#define SOUNDTOUCH_VERSION "1.5.1pre"
/// SoundTouch library version id
-#define SOUNDTOUCH_VERSION_ID (10500)
+#define SOUNDTOUCH_VERSION_ID (10509)
//
// Available setting IDs for the 'setSetting' & 'get_setting' functions:
diff --git a/source/SoundTouch/BPMDetect.cpp b/source/SoundTouch/BPMDetect.cpp
index bc9e064..32c80ba 100644
--- a/source/SoundTouch/BPMDetect.cpp
+++ b/source/SoundTouch/BPMDetect.cpp
@@ -96,6 +96,10 @@ BPMDetect::BPMDetect(int numChannels, int aSampleRate)
RMSVolumeAccu = (0.092f * 0.092f) / avgnorm;
#endif
+ cutCoeff = 1.75;
+ aboveCutAccu = 0;
+ totalAccu = 0;
+
// choose decimation factor so that result is approx. 500 Hz
decimateBy = sampleRate / 500;
assert(decimateBy > 0);
@@ -215,16 +219,15 @@ void BPMDetect::updateXCorr(int process_samples)
}
-
// Calculates envelope of the sample data
void BPMDetect::calcEnvelope(SAMPLETYPE *samples, int numsamples)
{
- const float decay = 0.7f; // decay constant for smoothing the envelope
- const float norm = (1 - decay);
+ const static double decay = 0.7f; // decay constant for smoothing the envelope
+ const static double norm = (1 - decay);
int i;
LONG_SAMPLETYPE out;
- float val;
+ double val;
for (i = 0; i < numsamples; i ++)
{
@@ -233,10 +236,32 @@ void BPMDetect::calcEnvelope(SAMPLETYPE *samples, int numsamples)
val = (float)fabs((float)samples[i]);
RMSVolumeAccu += val * val;
- // cut amplitudes that are below 2 times average RMS volume
+ // cut amplitudes that are below cutoff ~2 times RMS volume
// (we're interested in peak values, not the silent moments)
- val -= 2 * (float)sqrt(RMSVolumeAccu * avgnorm);
- val = (val > 0) ? val : 0;
+ val -= cutCoeff * sqrt(RMSVolumeAccu * avgnorm);
+ if (val > 0)
+ {
+ aboveCutAccu += 1.0; // sample above threshold
+ }
+ else
+ {
+ val = 0;
+ }
+
+ totalAccu += 1.0;
+
+ // maintain sliding statistic what proportion of 'val' samples is
+ // above cutoff threshold
+ aboveCutAccu *= 0.99931; // 2 sec time constant
+ totalAccu *= 0.99931;
+
+ if (totalAccu > 500)
+ {
+ // after initial settling, auto-adjust cutoff level so that ~8% of
+ // values are above the threshold
+ double d = (aboveCutAccu / totalAccu) - 0.08;
+ cutCoeff += 0.001 * d;
+ }
// smooth amplitude envelope
envelopeAccu *= decay;
@@ -249,6 +274,12 @@ void BPMDetect::calcEnvelope(SAMPLETYPE *samples, int numsamples)
#endif // INTEGER_SAMPLES
samples[i] = (SAMPLETYPE)out;
}
+
+ // check that cutoff doesn't get too small - it can be just silent sequence!
+ if (cutCoeff < 1.5)
+ {
+ cutCoeff = 1.5;
+ }
}