mirror of
https://github.com/azahar-emu/soundtouch
synced 2025-11-07 15:40:04 +01:00
Added automatic cutoff threshold adaptation to beat detection routine to better adapt BPM calculation to different types of music
This commit is contained in:
parent
3dbc7209bd
commit
ff06c88fd5
19
README.html
19
README.html
@ -18,7 +18,7 @@
|
||||
</head>
|
||||
<body class="normal">
|
||||
<hr>
|
||||
<h1>SoundTouch audio processing library v1.5.0
|
||||
<h1>SoundTouch audio processing library v1.5.1pre
|
||||
</h1>
|
||||
<p class="normal">SoundTouch library Copyright © Olli
|
||||
Parviainen 2001-2009 </p>
|
||||
@ -536,6 +536,13 @@ estimates the BPM rate:</p>
|
||||
<h2>5. Change History</h2>
|
||||
<h3>5.1. SoundTouch library Change History </h3>
|
||||
|
||||
<p><b>1.5.1pre:</b></p>
|
||||
<ul>
|
||||
<li>Added automatic cutoff threshold adaptation to beat detection routine to
|
||||
better adapt BPM calculation to different types of music</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<p><strong>1.5.0:</strong></p>
|
||||
<ul>
|
||||
<li>Added normalization to correlation calculation and improvement automatic seek/sequence parameter calculation to improve sound quality</li>
|
||||
@ -657,7 +664,15 @@ files. </li>
|
||||
<h3>5.2. SoundStretch application Change
|
||||
History </h3>
|
||||
|
||||
<p><strong>1.4.0:</strong></p>
|
||||
<p><b>v1.5.0:</b></p>
|
||||
<ul>
|
||||
<li>Added "-speech" switch to activate algorithm parameters more
|
||||
suitable for speech processing than the default parameters tuned for music
|
||||
processing.</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<p><strong>v1.4.0:</strong></p>
|
||||
<ul>
|
||||
<li>Moved BPM detection routines from SoundStretch application into SoundTouch
|
||||
library</li>
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user