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>
|
</head>
|
||||||
<body class="normal">
|
<body class="normal">
|
||||||
<hr>
|
<hr>
|
||||||
<h1>SoundTouch audio processing library v1.5.0
|
<h1>SoundTouch audio processing library v1.5.1pre
|
||||||
</h1>
|
</h1>
|
||||||
<p class="normal">SoundTouch library Copyright © Olli
|
<p class="normal">SoundTouch library Copyright © Olli
|
||||||
Parviainen 2001-2009 </p>
|
Parviainen 2001-2009 </p>
|
||||||
@ -536,6 +536,13 @@ estimates the BPM rate:</p>
|
|||||||
<h2>5. Change History</h2>
|
<h2>5. Change History</h2>
|
||||||
<h3>5.1. SoundTouch library Change History </h3>
|
<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>
|
<p><strong>1.5.0:</strong></p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Added normalization to correlation calculation and improvement automatic seek/sequence parameter calculation to improve sound quality</li>
|
<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
|
<h3>5.2. SoundStretch application Change
|
||||||
History </h3>
|
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>
|
<ul>
|
||||||
<li>Moved BPM detection routines from SoundStretch application into SoundTouch
|
<li>Moved BPM detection routines from SoundStretch application into SoundTouch
|
||||||
library</li>
|
library</li>
|
||||||
|
|||||||
@ -78,10 +78,19 @@ protected:
|
|||||||
float *xcorr;
|
float *xcorr;
|
||||||
|
|
||||||
/// Amplitude envelope sliding average approximation level accumulator
|
/// Amplitude envelope sliding average approximation level accumulator
|
||||||
float envelopeAccu;
|
double envelopeAccu;
|
||||||
|
|
||||||
/// RMS volume sliding average approximation level accumulator
|
/// 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.
|
/// Sample average counter.
|
||||||
int decimateCount;
|
int decimateCount;
|
||||||
|
|||||||
@ -79,10 +79,10 @@ namespace soundtouch
|
|||||||
{
|
{
|
||||||
|
|
||||||
/// Soundtouch library version string
|
/// Soundtouch library version string
|
||||||
#define SOUNDTOUCH_VERSION "1.5.0"
|
#define SOUNDTOUCH_VERSION "1.5.1pre"
|
||||||
|
|
||||||
/// SoundTouch library version id
|
/// SoundTouch library version id
|
||||||
#define SOUNDTOUCH_VERSION_ID (10500)
|
#define SOUNDTOUCH_VERSION_ID (10509)
|
||||||
|
|
||||||
//
|
//
|
||||||
// Available setting IDs for the 'setSetting' & 'get_setting' functions:
|
// 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;
|
RMSVolumeAccu = (0.092f * 0.092f) / avgnorm;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
cutCoeff = 1.75;
|
||||||
|
aboveCutAccu = 0;
|
||||||
|
totalAccu = 0;
|
||||||
|
|
||||||
// choose decimation factor so that result is approx. 500 Hz
|
// choose decimation factor so that result is approx. 500 Hz
|
||||||
decimateBy = sampleRate / 500;
|
decimateBy = sampleRate / 500;
|
||||||
assert(decimateBy > 0);
|
assert(decimateBy > 0);
|
||||||
@ -215,16 +219,15 @@ void BPMDetect::updateXCorr(int process_samples)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Calculates envelope of the sample data
|
// Calculates envelope of the sample data
|
||||||
void BPMDetect::calcEnvelope(SAMPLETYPE *samples, int numsamples)
|
void BPMDetect::calcEnvelope(SAMPLETYPE *samples, int numsamples)
|
||||||
{
|
{
|
||||||
const float decay = 0.7f; // decay constant for smoothing the envelope
|
const static double decay = 0.7f; // decay constant for smoothing the envelope
|
||||||
const float norm = (1 - decay);
|
const static double norm = (1 - decay);
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
LONG_SAMPLETYPE out;
|
LONG_SAMPLETYPE out;
|
||||||
float val;
|
double val;
|
||||||
|
|
||||||
for (i = 0; i < numsamples; i ++)
|
for (i = 0; i < numsamples; i ++)
|
||||||
{
|
{
|
||||||
@ -233,10 +236,32 @@ void BPMDetect::calcEnvelope(SAMPLETYPE *samples, int numsamples)
|
|||||||
val = (float)fabs((float)samples[i]);
|
val = (float)fabs((float)samples[i]);
|
||||||
RMSVolumeAccu += val * val;
|
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)
|
// (we're interested in peak values, not the silent moments)
|
||||||
val -= 2 * (float)sqrt(RMSVolumeAccu * avgnorm);
|
val -= cutCoeff * sqrt(RMSVolumeAccu * avgnorm);
|
||||||
val = (val > 0) ? val : 0;
|
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
|
// smooth amplitude envelope
|
||||||
envelopeAccu *= decay;
|
envelopeAccu *= decay;
|
||||||
@ -249,6 +274,12 @@ void BPMDetect::calcEnvelope(SAMPLETYPE *samples, int numsamples)
|
|||||||
#endif // INTEGER_SAMPLES
|
#endif // INTEGER_SAMPLES
|
||||||
samples[i] = (SAMPLETYPE)out;
|
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