-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsimplepeakdetector.cpp
96 lines (79 loc) · 2.13 KB
/
simplepeakdetector.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#define _USE_MATH_DEFINES
#include <cmath>
#include <cassert>
#include "audioconfig.h"
#include "simplepeakdetector.h"
#include "Clip.h"
#define FREQ_LP_BEAT 150.0f // Low Pass filter frequency, in HZ
#define T_FILTER 1.0f / (2.0f * M_PI * FREQ_LP_BEAT) // Low Pass filter time constant
#define BEAT_RELEASE_TIME 0.2f // Release time of envelope detector, in second
SimplePeakDetector::SimplePeakDetector()
{
Reset();
}
void SimplePeakDetector::Reset()
{
m_Filter1Out = .0;
m_Filter2Out = .0;
m_EnvelopePeak = .0;
m_PeakTrigger = false;
m_PrevPeakPulse = false;
m_PeakFilter = 1.0 / (DEFAULT_SAMPLE_RATE * T_FILTER);
m_PeakRelease = exp(-1.0f / (DEFAULT_SAMPLE_RATE * BEAT_RELEASE_TIME));
}
void SimplePeakDetector::ProcessAudio(const float* inputSamples, unsigned int nbSamples, std::vector<Peak>& outPeaks)
{
assert(nbSamples == INPUT_WINDOW_SIZE);
Reset();
for (unsigned int sampleIndex = 0; sampleIndex < nbSamples; ++sampleIndex)
{
double envelopeIn;
// Filter data
m_Filter1Out = m_Filter1Out + (m_PeakFilter * (inputSamples[sampleIndex] - m_Filter1Out));
m_Filter2Out = m_Filter2Out + (m_PeakFilter * (m_Filter1Out - m_Filter2Out));
// Envelope follower
envelopeIn = fabs(m_Filter2Out);
if (envelopeIn > m_EnvelopePeak)
{
m_EnvelopePeak = envelopeIn; // Attack time = 0
}
else
{
m_EnvelopePeak *= m_PeakRelease;
m_EnvelopePeak += (1.0 - m_PeakRelease) * envelopeIn;
}
// Peak detector
if (!m_PeakTrigger)
{
if (m_EnvelopePeak > .5)
{
m_PeakTrigger = true;
}
}
else
{
if (m_EnvelopePeak < .3)
{
m_PeakTrigger = false;
}
}
if ((m_PeakTrigger) && (!m_PrevPeakPulse))
{
outPeaks.push_back(Peak(sampleIndex, sampleIndex));
}
m_PrevPeakPulse = m_PeakTrigger;
}
}
bool SimplePeakDetector::GetPeaks(const float* samples, unsigned int nbSamples, const AudioInfo& audioInfo, std::vector<Peak>& outPeaks)
{
if (!AudioInfo::CheckAudioInfo(audioInfo))
{
return false;
}
if (nbSamples != INPUT_WINDOW_SIZE)
{
return false;
}
ProcessAudio(samples, nbSamples, outPeaks);
return true;
}