Improve robustness by combining AKF and AMDF

This commit is contained in:
Flamefire committed 2014-03-29 17:47:52 +01:00
1 parent 980644108e
commit 6ad9f6a1ef
3 files changed
+23 -13

No files matched your search

+3 -2
View File
@@ -11,12 +11,13 @@ AnalyzerExt::~AnalyzerExt(){
}
int AnalyzerExt::GetNoteFast(double* maxVolume, float* weights){
float AnaylsisBuf[m_SampleCt];
size_t size = m_fastAnalysisBuf.size();
if(size > m_SampleCt)
m_fastAnalysisBuf.pop(size - m_SampleCt);
if(!m_fastAnalysisBuf.read(m_AnalysisBuf, m_AnalysisBuf + m_SampleCt))
if(!m_fastAnalysisBuf.read(AnaylsisBuf, AnaylsisBuf + m_SampleCt))
return -1;
return PitchTracker::GetTone(m_AnalysisBuf, m_SampleCt, maxVolume, weights);
return PitchTracker::GetTone(AnaylsisBuf, m_SampleCt, maxVolume, weights);
}
void PtFast_Init(double baseToneFrequency, int minHalfTone, int maxHalfTone){
-1
View File
@@ -16,7 +16,6 @@ public:
private:
constexpr static size_t m_SampleCt = 4096;
RingBuffer<m_SampleCt * 2> m_fastAnalysisBuf; // Buffer used for fast analysis instead of FFT
float m_AnalysisBuf[4096];
};
DllExport void PtFast_Init(double baseToneFrequency, int minHalfTone, int maxHalfTone);
+20 -10
View File
@@ -66,26 +66,35 @@ namespace PitchTracker{
}
template<typename T>
static T _AnalyzeToneFunc(T *samples, int sampleCt, int toneIndex){
static T _AnalyzeToneFunc(T *samples, int sampleCt, int toneIndex, bool scale){
// Use method by Kobayashi and Shimamura (1995): Combine AKF and AMDF to a new f(z)=AKF(z)/(AMDF(z)+k) with k=1
double samplesPerPeriodD = SamplesPerPeriodPerTone[toneIndex]; // samples in one period
int samplesPerPeriod = static_cast<int>(samplesPerPeriodD);
T fHigh = static_cast<T>(samplesPerPeriodD - samplesPerPeriod);
T fLow = static_cast<T>(1.0 - fHigh);
T accumDist = 0; // accumulated distances
T accumDistAKF = 0; // accumulated distances
T accumDistAMDF = 0; // accumulated distances
// compare correlating samples
int sampleIndex = 0; // index of sample to analyze
// Start value= index of sample one period ahead
for (int correlatingSampleIndex = sampleIndex + samplesPerPeriod; correlatingSampleIndex + 1 < sampleCt; correlatingSampleIndex++, sampleIndex++)
{
// calc distance to corresponding sample in next period (lower means more distant)
T dist = samples[sampleIndex] * (samples[correlatingSampleIndex] * fLow + samples[correlatingSampleIndex + 1] * fHigh);
accumDist += dist;
// calc distance to corresponding sample in next period
T xn = samples[sampleIndex];
T xnt = samples[correlatingSampleIndex] * fLow + samples[correlatingSampleIndex + 1] * fHigh;
accumDistAKF += xn * xnt;
accumDistAMDF += abs(xn - xnt);
}
//Using sampleCt here makes it return correct values among all analyzed frequencies
return accumDist / sampleCt;
accumDistAKF /= sampleCt;
accumDistAMDF /= sampleIndex;
if(scale)
return accumDistAKF / (accumDistAMDF * 32767.f + 32767.f); // Need to scale AKF by MAX^2 and AMDF by MAX, so do some maths to divide only once
else
return accumDistAKF / (accumDistAMDF + 1.f);
}
template<typename T>
@@ -98,15 +107,16 @@ namespace PitchTracker{
if(vol > maxVolumeL)
maxVolumeL = vol;
}
if(scale)
maxVolumeL /= 32767.;
*maxVolume = maxVolumeL;
T maxWeight = -1;
T minWeight = 1;
int maxTone = -1;
for (int toneIndex = MinHalfTone; toneIndex <= MaxHalfTone; toneIndex++)
{
T curWeight = _AnalyzeToneFunc<T>(samples, sampleCt, toneIndex) / maxVolumeL;
if(scale)
curWeight /= 32768.0; //maximum abs value of a short, would actually need to scale by MaxValue^2 but we already scaled by maxVolume
T curWeight = _AnalyzeToneFunc<T>(samples, sampleCt, toneIndex, scale);
if (curWeight > maxWeight)
{