mirror of
https://github.com/RPCS3/soundtouch.git
synced 2024-11-27 13:20:40 +00:00
Adjustments in beat detection
This commit is contained in:
parent
b4e22218e6
commit
0462e450a6
@ -117,23 +117,19 @@ BPMDetect::BPMDetect(int numChannels, int aSampleRate)
|
||||
|
||||
envelopeAccu = 0;
|
||||
|
||||
// Initialize RMS volume accumulator to RMS level of 3000 (out of 32768) that's
|
||||
// a typical RMS signal level value for song data. This value is then adapted
|
||||
// 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 = (3000 * 3000) / avgnorm;
|
||||
RMSVolumeAccu = (1500 * 1500) / avgnorm;
|
||||
#else
|
||||
// float samples, scaled to range [-1..+1[
|
||||
RMSVolumeAccu = (0.092f * 0.092f) / avgnorm;
|
||||
RMSVolumeAccu = (0.045f * 0.045f) / avgnorm;
|
||||
#endif
|
||||
|
||||
cutCoeff = 1.75;
|
||||
aboveCutAccu = 0;
|
||||
totalAccu = 0;
|
||||
|
||||
// choose decimation factor so that result is approx. 500 Hz
|
||||
decimateBy = sampleRate / 500;
|
||||
// choose decimation factor so that result is approx. 1000 Hz
|
||||
decimateBy = sampleRate / 1000;
|
||||
assert(decimateBy > 0);
|
||||
assert(INPUT_BLOCK_SAMPLES < decimateBy * DECIMATED_BLOCK_SAMPLES);
|
||||
|
||||
@ -270,31 +266,11 @@ void BPMDetect::calcEnvelope(SAMPLETYPE *samples, int numsamples)
|
||||
|
||||
// cut amplitudes that are below cutoff ~2 times RMS volume
|
||||
// (we're interested in peak values, not the silent moments)
|
||||
val -= cutCoeff * sqrt(RMSVolumeAccu * avgnorm);
|
||||
if (val > 0)
|
||||
{
|
||||
aboveCutAccu += 1.0; // sample above threshold
|
||||
}
|
||||
else
|
||||
if (val < 0.5 * sqrt(RMSVolumeAccu * avgnorm))
|
||||
{
|
||||
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;
|
||||
envelopeAccu += val;
|
||||
@ -306,12 +282,6 @@ void BPMDetect::calcEnvelope(SAMPLETYPE *samples, int numsamples)
|
||||
#endif // SOUNDTOUCH_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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -355,6 +325,26 @@ void BPMDetect::inputSamples(const SAMPLETYPE *samples, int numSamples)
|
||||
|
||||
|
||||
|
||||
void BPMDetect::removeBias()
|
||||
{
|
||||
int i;
|
||||
float minval = 1e12f; // arbitrary large number
|
||||
|
||||
for (i = windowStart; i < windowLen; i ++)
|
||||
{
|
||||
if (xcorr[i] < minval)
|
||||
{
|
||||
minval = xcorr[i];
|
||||
}
|
||||
}
|
||||
|
||||
for (i = windowStart; i < windowLen; i ++)
|
||||
{
|
||||
xcorr[i] -= minval;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float BPMDetect::getBpm()
|
||||
{
|
||||
double peakPos;
|
||||
@ -366,6 +356,9 @@ float BPMDetect::getBpm()
|
||||
// save bpm debug analysis data if debug data enabled
|
||||
_SaveDebugData(xcorr, windowStart, windowLen, coeff);
|
||||
|
||||
// remove bias from xcorr data
|
||||
removeBias();
|
||||
|
||||
// find peak position
|
||||
peakPos = peakFinder.detectPeak(xcorr, windowStart, windowLen);
|
||||
|
||||
|
@ -103,7 +103,7 @@ int PeakFinder::findGround(const float *data, int peakpos, int direction) const
|
||||
|
||||
pos = peakpos;
|
||||
|
||||
while ((pos > minPos) && (pos < maxPos))
|
||||
while ((pos > minPos+1) && (pos < maxPos-1))
|
||||
{
|
||||
int prevpos;
|
||||
|
||||
@ -132,7 +132,7 @@ int PeakFinder::findGround(const float *data, int peakpos, int direction) const
|
||||
{
|
||||
// going uphill, increase climbing counter
|
||||
climb_count ++;
|
||||
if (climb_count >= 10) break; // we've been climbing too long => it's next uphill => quit
|
||||
if (climb_count > 5) break; // we've been climbing too long => it's next uphill => quit
|
||||
}
|
||||
}
|
||||
return lowpos;
|
||||
@ -192,12 +192,9 @@ double PeakFinder::getPeakCenter(const float *data, int peakpos) const
|
||||
gp1 = findGround(data, peakpos, -1);
|
||||
gp2 = findGround(data, peakpos, 1);
|
||||
|
||||
groundLevel = max(data[gp1], data[gp2]);
|
||||
groundLevel = 0.5 * (data[gp1] + data[gp2]);
|
||||
peakLevel = data[peakpos];
|
||||
|
||||
if (groundLevel < 1e-9) return 0; // ground level too small => detection failed
|
||||
if ((peakLevel / groundLevel) < 1.3) return 0; // peak less than 30% of the ground level => no good peak detected
|
||||
|
||||
// calculate 70%-level of the peak
|
||||
cutLevel = 0.70f * peakLevel + 0.30f * groundLevel;
|
||||
// find mid-level crossings
|
||||
@ -269,7 +266,7 @@ double PeakFinder::detectPeak(const float *data, int aminPos, int amaxPos)
|
||||
// now compare to highest detected peak
|
||||
i1 = (int)(highPeak + 0.5);
|
||||
i2 = (int)(peaktmp + 0.5);
|
||||
if (data[i2] >= 0.5*data[i1])
|
||||
if (data[i2] >= 0.4*data[i1])
|
||||
{
|
||||
// The harmonic is at least half as high primary peak,
|
||||
// thus use the harmonic peak instead
|
||||
|
Loading…
Reference in New Issue
Block a user