diff --git a/PitchTracker/PitchTracker.vcxproj b/PitchTracker/PitchTracker.vcxproj
index a2053137..47be7dd7 100644
--- a/PitchTracker/PitchTracker.vcxproj
+++ b/PitchTracker/PitchTracker.vcxproj
@@ -95,6 +95,7 @@
WIN64;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
true
Fast
+ false
Windows
@@ -112,6 +113,7 @@
WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
true
Fast
+ false
Windows
@@ -169,7 +171,7 @@
-
+
@@ -177,7 +179,7 @@
-
+
diff --git a/PitchTracker/PitchTracker.vcxproj.filters b/PitchTracker/PitchTracker.vcxproj.filters
index 821a397b..efd0974f 100644
--- a/PitchTracker/PitchTracker.vcxproj.filters
+++ b/PitchTracker/PitchTracker.vcxproj.filters
@@ -33,7 +33,7 @@
Quelldateien\performous
-
+
Quelldateien
@@ -53,7 +53,7 @@
Headerdateien\performous\libda
-
+
Headerdateien
diff --git a/PitchTracker/PitchWrapper.cpp b/PitchTracker/PitchWrapper.cpp
index 31271e82..4fc47b4c 100644
--- a/PitchTracker/PitchWrapper.cpp
+++ b/PitchTracker/PitchWrapper.cpp
@@ -1,58 +1,23 @@
#include "PitchWrapper.h"
-#include "pdaAKF.h"
#include "Helper.h"
-AnalyzerExt::AnalyzerExt(double baseToneFrequency, int minHalfTone, int maxHalfTone, unsigned step): Analyzer(44100., "", step){
- PitchTrackerAKF::Init(baseToneFrequency, minHalfTone, maxHalfTone);
+
+Analyzer* Analyzer_Create(unsigned step){
+ return new Analyzer(44100, "", step);
}
-AnalyzerExt::~AnalyzerExt(){
- PitchTrackerAKF::DeInit();
-}
-
-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(AnaylsisBuf, AnaylsisBuf + m_SampleCt))
- return -1;
- return PitchTrackerAKF::GetTone(AnaylsisBuf, m_SampleCt, maxVolume, weights);
-}
-
-void PtFast_Init(double baseToneFrequency, int minHalfTone, int maxHalfTone){
- PitchTrackerAKF::Init(baseToneFrequency, minHalfTone, maxHalfTone);
-}
-
-void PtFast_DeInit(){
- PitchTrackerAKF::DeInit();
-}
-
-int PtFast_GetTone(short* samples, int sampleCt, double* maxVolume, float* weights){
- if(sampleCt <= 0)
- return -1;
- double* dataDouble = short2DoubleArray(samples, sampleCt, false);
- int result = PitchTrackerAKF::GetTone(dataDouble, sampleCt, maxVolume, weights, true);
- freeDoubleArray(dataDouble);
- return result;
-}
-
-AnalyzerExt* Analyzer_Create(double baseToneFrequency, int minHalfTone, int maxHalfTone, unsigned step){
- return new AnalyzerExt(baseToneFrequency, minHalfTone, maxHalfTone, step);
-}
-
-void Analyzer_Free(AnalyzerExt* analyzer){
+void Analyzer_Free(Analyzer* analyzer){
if(analyzer)
delete analyzer;
}
-void Analyzer_InputFloat(AnalyzerExt* analyzer, float* data, int sampleCt){
+void Analyzer_InputFloat(Analyzer* analyzer, float* data, int sampleCt){
if(sampleCt == 0 || !analyzer)
return;
analyzer->input(data, data + sampleCt);
}
-void Analyzer_InputShort(AnalyzerExt* analyzer, short* data, int sampleCt){
+void Analyzer_InputShort(Analyzer* analyzer, short* data, int sampleCt){
if(sampleCt == 0 || !analyzer)
return;
float* dataFloat = short2FloatArray(data, sampleCt);
@@ -60,45 +25,64 @@ void Analyzer_InputShort(AnalyzerExt* analyzer, short* data, int sampleCt){
freeFloatArray(dataFloat);
}
-void Analyzer_InputByte(AnalyzerExt* analyzer, char* data, int sampleCt){
- if(sampleCt == 0 || !analyzer)
+void Analyzer_InputByte(Analyzer* analyzer, char* data, int sampleCt){
+ if(sampleCt <= 0 || !analyzer)
return;
float* dataFloat = short2FloatArray(static_cast(static_cast(data)), sampleCt);
analyzer->input(dataFloat, dataFloat + sampleCt);
freeFloatArray(dataFloat);
}
-void Analyzer_Process(AnalyzerExt* analyzer){
+void Analyzer_Process(Analyzer* analyzer){
if(!analyzer)
return;
analyzer->process();
}
-double Analyzer_GetPeak(AnalyzerExt* analyzer){
+double Analyzer_GetPeak(Analyzer* analyzer){
if(!analyzer)
return -999;
return analyzer->getPeak();
}
-double Analyzer_FindNote(AnalyzerExt* analyzer, double minFreq, double maxFreq){
+double Analyzer_FindNote(Analyzer* analyzer, double minFreq, double maxFreq){
if(!analyzer)
return -1;
const Tone* tone = analyzer->findTone(minFreq, maxFreq);
return (tone == NULL) ? -1 : FreqToNote(tone->freq);
}
-int Analyzer_GetNoteFast(AnalyzerExt* analyzer, double* maxVolume, float* weights){
- if(!analyzer)
- return -1;
- return analyzer->GetNoteFast(maxVolume, weights);
-}
-
-bool Analyzer_OutputFloat(AnalyzerExt* analyzer, float* data, int sampleCt, float rate){
+bool Analyzer_OutputFloat(Analyzer* analyzer, float* data, int sampleCt, float rate){
if(!analyzer)
return false;
return analyzer->output(data, data + sampleCt, rate);
}
+DllExport PtAKF* PtAKF_Create(){
+ return new PtAKF();
+}
+
+DllExport void PtAKF_Free(PtAKF* analyzer){
+ if(analyzer)
+ delete analyzer;
+}
+
+DllExport int PtAKF_GetNumHalfTones(){
+ return PtAKF::GetNumHalfTones();
+}
+
+DllExport void PtAKF_InputByte(PtAKF* analyzer, char* data, int sampleCt){
+ if(sampleCt <= 0 || !analyzer)
+ return;
+ short* dataShort = static_cast(static_cast(data));
+ analyzer->input(dataShort, dataShort + sampleCt);
+}
+
+DllExport int PtAKF_GetNote(PtAKF* analyzer, double* maxVolume, float* weights){
+ if(!analyzer)
+ return -1;
+ return analyzer->GetNote(maxVolume, weights);
+}
/*
namespace Native{
diff --git a/PitchTracker/PitchWrapper.h b/PitchTracker/PitchWrapper.h
index f22771ba..d3039bc9 100644
--- a/PitchTracker/PitchWrapper.h
+++ b/PitchTracker/PitchWrapper.h
@@ -1,37 +1,25 @@
#pragma once
#include "performous/pitch.hh"
+#include "ptAKF.h"
#define DllExport extern "C" __declspec(dllexport)
-class AnalyzerExt: public Analyzer{
-public:
- AnalyzerExt(double baseToneFrequency, int minHalfTone, int maxHalfTone, unsigned step = 200);
- ~AnalyzerExt();
- template void input(InIt begin, InIt end){
- m_fastAnalysisBuf.insert(begin, end);
- Analyzer::input(begin, end);
- }
- int GetNoteFast(double* maxVolume, float* weights);
-private:
- constexpr static size_t m_SampleCt = 4096;
- RingBuffer m_fastAnalysisBuf; // Buffer used for fast analysis instead of FFT
-};
+DllExport Analyzer* Analyzer_Create(unsigned step);
+DllExport void Analyzer_Free(Analyzer* analyzer);
+DllExport void Analyzer_InputFloat(Analyzer* analyzer, float* data, int sampleCt);
+DllExport void Analyzer_InputShort(Analyzer* analyzer, short* data, int sampleCt);
+DllExport void Analyzer_InputByte(Analyzer* analyzer, char* data, int sampleCt);
+DllExport void Analyzer_Process(Analyzer* analyzer);
+DllExport double Analyzer_GetPeak(Analyzer* analyzer);
+DllExport double Analyzer_FindNote(Analyzer* analyzer, double minFreq, double maxFreq);
+DllExport bool Analyzer_OutputFloat(Analyzer* analyzer, float* data, int sampleCt, float rate);
-DllExport void PtFast_Init(double baseToneFrequency, int minHalfTone, int maxHalfTone);
-DllExport void PtFast_DeInit();
-DllExport int PtFast_GetTone(short* samples, int sampleCt, float* weights);
-
-DllExport AnalyzerExt* Analyzer_Create(double baseToneFrequency, int minHalfTone, int maxHalfTone, unsigned step);
-DllExport void Analyzer_Free(AnalyzerExt* analyzer);
-DllExport void Analyzer_InputFloat(AnalyzerExt* analyzer, float* data, int sampleCt);
-DllExport void Analyzer_InputShort(AnalyzerExt* analyzer, short* data, int sampleCt);
-DllExport void Analyzer_InputByte(AnalyzerExt* analyzer, char* data, int sampleCt);
-DllExport void Analyzer_Process(AnalyzerExt* analyzer);
-DllExport double Analyzer_GetPeak(AnalyzerExt* analyzer);
-DllExport int Analyzer_GetNoteFast(AnalyzerExt* analyzer, double* maxVolume, float* weights);
-DllExport double Analyzer_FindNote(AnalyzerExt* analyzer, double minFreq, double maxFreq);
-DllExport bool Analyzer_OutputFloat(AnalyzerExt* analyzer, float* data, int sampleCt, float rate);
+DllExport PtAKF* PtAKF_Create();
+DllExport void PtAKF_Free(PtAKF* analyzer);
+DllExport int PtAKF_GetNumHalfTones();
+DllExport void PtAKF_InputByte(PtAKF* analyzer, char* data, int sampleCt);
+DllExport int PtAKF_GetNote(PtAKF* analyzer, double* maxVolume, float* weights);
/*
public ref class CTone {
@@ -74,7 +62,7 @@ public:
String^ GetId();
private:
- AnalyzerExt* m_analyzer;
+ Analyzer* m_analyzer;
String^ m_id;
};
diff --git a/PitchTracker/pdaAKF.h b/PitchTracker/pdaAKF.h
deleted file mode 100644
index 6341e973..00000000
--- a/PitchTracker/pdaAKF.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#pragma once
-
-// A pitch detection that is based on the AKF and AMDF (initially from original Vocaluxe/USDx)
-namespace PitchTrackerAKF{
- void Init(double baseToneFrequency, int minHalfTone, int maxHalfTone);
- void DeInit();
- template int GetTone(T *samples, int sampleCt, double* maxVolume, float *weights, bool scale = false);
-
- typedef void (__stdcall * LogCallback)(const char* text);
- static LogCallback Log;
- void SetLogCallback(LogCallback Callback);
-}
diff --git a/PitchTracker/pdaAKF.cpp b/PitchTracker/ptAKF.cpp
similarity index 57%
rename from PitchTracker/pdaAKF.cpp
rename to PitchTracker/ptAKF.cpp
index 460a74b9..fd272a6f 100644
--- a/PitchTracker/pdaAKF.cpp
+++ b/PitchTracker/ptAKF.cpp
@@ -13,28 +13,112 @@
// You should have received a copy of the GNU General Public License
// along with Vocaluxe. If not, see .
-#include "pdaAKF.h"
+#include "ptAKF.h"
#include
-#include
-#include
-#include
+
+static constexpr double BaseToneFrequency = 65.4064; // lowest (half-)tone to analyze (C2 = 65.4064 Hz)
+static constexpr double HalftoneBase = 1.05946309436; // 2^(1/12) -> HalftoneBase^12 = 2 (one octave)
+int PtAKF::_InitCount = 0;
+float* PtAKF::_SamplesPerPeriodPerTone = NULL;
+
+PtAKF::PtAKF(){
+ _InitCount++;
+ if(_InitCount == 1){
+ _SamplesPerPeriodPerTone = new float[_MaxHalfTone + 1];
+ //Init Array to avoid costly calculations
+ for (int toneIndex = 0; toneIndex <= _MaxHalfTone; toneIndex++)
+ {
+ double freq = BaseToneFrequency * pow(HalftoneBase, toneIndex);
+ _SamplesPerPeriodPerTone[toneIndex] = static_cast(44100.0 / freq); // samples in one period
+ }
+ }
+}
+
+PtAKF::~PtAKF(){
+ _InitCount--;
+ if(!_InitCount){
+ delete[] _SamplesPerPeriodPerTone;
+ _SamplesPerPeriodPerTone = NULL;
+ }
+}
+
+int PtAKF::GetNote(double* maxVolume, float* weights){
+ float AnaylsisBuf[_SampleCt];
+ size_t size = _AnalysisBuf.size();
+ if(size > _SampleCt)
+ _AnalysisBuf.pop(size - _SampleCt);
+ if(!_AnalysisBuf.read(AnaylsisBuf, AnaylsisBuf + _SampleCt))
+ return -1;
+ return _GetNote(AnaylsisBuf, maxVolume, weights);
+}
+
+int PtAKF::_GetNote(float* samples, double* maxVolume, float* weights){
+ float maxVolumeL = 0;
+ for(int i = 0; i < _SampleCt; i++){
+ float vol = abs(samples[i]);
+ if(vol > maxVolumeL)
+ maxVolumeL = vol;
+ }
+ maxVolumeL /= 32767.;
+ *maxVolume = maxVolumeL;
+
+ float maxWeight = -1;
+ float minWeight = 1;
+ int maxTone = -1;
+ for (int toneIndex = _MinHalfTone; toneIndex <= _MaxHalfTone; toneIndex++)
+ {
+ float curWeight = _AnalyzeToneFunc(samples, toneIndex);
+
+ if (curWeight > maxWeight)
+ {
+ maxWeight = curWeight;
+ maxTone = toneIndex;
+ }
+
+ if (curWeight < minWeight)
+ minWeight = curWeight;
+
+ weights[toneIndex - _MinHalfTone] = curWeight;
+ }
+
+ if(maxWeight - minWeight > 0.01){
+ return maxTone;
+ }else return -1;
+}
+
+float PtAKF::_AnalyzeToneFunc(float* samples, int toneIndex){
+ // Use method by Kobayashi and Shimamura (1995): Combine AKF and AMDF to a new f(z)=AKF(z)/(AMDF(z)+k) with k=1
+
+ float samplesPerPeriodD = _SamplesPerPeriodPerTone[toneIndex]; // samples in one period
+ int samplesPerPeriod = static_cast(samplesPerPeriodD);
+ float fHigh = samplesPerPeriodD - samplesPerPeriod;
+ float fLow = 1.0f - fHigh;
+
+ float accumDistAKF = 0; // accumulated distances
+ float 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
+ float xn = samples[sampleIndex];
+ float xnt = samples[correlatingSampleIndex] * fLow + samples[correlatingSampleIndex + 1] * fHigh;
+ accumDistAKF += xn * xnt;
+ accumDistAMDF += abs(xn - xnt);
+ }
+
+ accumDistAKF /= _SampleCt;
+ accumDistAMDF /= sampleIndex;
+
+ 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
+}
+/*
+
+
namespace PitchTrackerAKF{
-
- static void doLog(const char* msg,...){
- va_list argptr = NULL;
- va_start(argptr, msg);
-
- char buffer[200];
- vsprintf_s(buffer,msg, argptr);
- if(Log) Log(buffer);
- va_end(argptr);
- }
-
- void SetLogCallback(LogCallback Callback){
- Log=Callback;
- }
-
static double *SamplesPerPeriodPerTone = NULL;
static double BaseToneFrequency = -1;
static int MinHalfTone = -1, MaxHalfTone = -1;
@@ -138,4 +222,5 @@ namespace PitchTrackerAKF{
template int GetTone(float *samples, int sampleCt, double* maxVolume, float *weights, bool scale);
template int GetTone(double *samples, int sampleCt, double* maxVolume, float *weights, bool scale);
-}
\ No newline at end of file
+}
+*/
\ No newline at end of file
diff --git a/PitchTracker/ptAKF.h b/PitchTracker/ptAKF.h
new file mode 100644
index 00000000..240e7aa7
--- /dev/null
+++ b/PitchTracker/ptAKF.h
@@ -0,0 +1,27 @@
+#pragma once
+#include "performous/pitch.hh"
+
+// A pitch detection that is based on the AKF and AMDF (initially from original Vocaluxe/USDx)
+class PtAKF{
+public:
+ PtAKF();
+ ~PtAKF();
+
+ void input(short* begin, short* end){
+ _AnalysisBuf.insert(begin, end);
+ }
+
+ int GetNote(double* maxVolume, float* weights);
+ static int GetNumHalfTones(){ return _MaxHalfTone - _MinHalfTone + 1;}
+private:
+ static int _InitCount;
+ static float* _SamplesPerPeriodPerTone;
+ static constexpr int _MinHalfTone = 0; //C2
+ static constexpr int _MaxHalfTone = 47; //B5
+
+ constexpr static size_t _SampleCt = 4096;
+ RingBuffer<_SampleCt * 2> _AnalysisBuf;
+
+ static int _GetNote(float* samples, double* maxVolume, float* weights);
+ static float _AnalyzeToneFunc(float* samples, int toneIndex);
+};
\ No newline at end of file
diff --git a/Vocaluxe/Lib/Sound/Record/CAnalyzer.cs b/Vocaluxe/Lib/Sound/Record/CAnalyzer.cs
index 426572d0..39d79f00 100644
--- a/Vocaluxe/Lib/Sound/Record/CAnalyzer.cs
+++ b/Vocaluxe/Lib/Sound/Record/CAnalyzer.cs
@@ -3,11 +3,15 @@ using System.Runtime.InteropServices;
namespace Vocaluxe.Lib.Sound.Record
{
+ ///
+ /// Analyzer from Performous
+ /// Should be very reliable but needs some proof (artificial tests show some errors)
+ ///
class CAnalyzer : IDisposable
{
#region Imports
[DllImport("PitchTracker.dll", CallingConvention = CallingConvention.Cdecl)]
- private static extern IntPtr Analyzer_Create(double baseToneFrequency, int minHalfTone, int maxHalfTone, uint step = 200);
+ private static extern IntPtr Analyzer_Create(uint step = 200);
[DllImport("PitchTracker.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern void Analyzer_Free(IntPtr analyzer);
@@ -27,9 +31,6 @@ namespace Vocaluxe.Lib.Sound.Record
[DllImport("PitchTracker.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern double Analyzer_GetPeak(IntPtr analyzer);
- [DllImport("PitchTracker.dll", CallingConvention = CallingConvention.Cdecl)]
- private static extern int Analyzer_GetNoteFast(IntPtr analyzer, [Out] out double maxVolume, [Out] float[] weights);
-
[DllImport("PitchTracker.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern double Analyzer_FindNote(IntPtr analyzer, double minFreq, double maxFreq);
@@ -39,9 +40,9 @@ namespace Vocaluxe.Lib.Sound.Record
private IntPtr _Instance;
- public CAnalyzer(double baseToneFrequency, int minHalfTone, int maxHalfTone, uint step = 200)
+ public CAnalyzer(uint step = 200)
{
- _Instance = Analyzer_Create(baseToneFrequency, minHalfTone, maxHalfTone, step);
+ _Instance = Analyzer_Create(step);
}
~CAnalyzer()
@@ -79,11 +80,6 @@ namespace Vocaluxe.Lib.Sound.Record
return Analyzer_FindNote(_Instance, minFreq, maxFreq);
}
- public int GetNoteFast(out double maxVolume, float[] weights)
- {
- return Analyzer_GetNoteFast(_Instance, out maxVolume, weights);
- }
-
public bool Output(float[] data, float rate)
{
return Analyzer_OutputFloat(_Instance, data, data.Length, rate);
@@ -104,22 +100,63 @@ namespace Vocaluxe.Lib.Sound.Record
}
}
- static class CFastAnalyzer
+ ///
+ /// Pitchtracker (Pt) that uses autocorrelation (AKF) and AMDF
+ /// Quite fast and perfect in artificial tests, but may fail in real world scenarios (e.g. missing fundamental)
+ ///
+ class CPtAKF : IDisposable
{
#region Imports
- [DllImport("PitchTracker.dll", EntryPoint = "PtFast_Init", CallingConvention = CallingConvention.Cdecl)]
- public static extern void Init(double baseToneFrequency, int minHalfTone, int maxHalfTone);
+ [DllImport("PitchTracker.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern IntPtr PtAKF_Create();
- [DllImport("PitchTracker.dll", EntryPoint = "PtFast_DeInit", CallingConvention = CallingConvention.Cdecl)]
- public static extern void DeInit();
+ [DllImport("PitchTracker.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern void PtAKF_Free(IntPtr analyzer);
- [DllImport("PitchTracker.dll", EntryPoint = "PtFast_GetTone", CallingConvention = CallingConvention.Cdecl)]
- private static extern int PtFast_GetTone([In] short[] samples, int sampleCt, [Out] out double maxVolume, [Out] float[] weights);
+ [DllImport("PitchTracker.dll", EntryPoint = "PtAKF_GetNumHalfTones", CallingConvention = CallingConvention.Cdecl)]
+ public static extern int GetNumHalfTones();
+
+ [DllImport("PitchTracker.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern void PtAKF_InputByte(IntPtr analyzer, [In] byte[] data, int sampleCt);
+
+ [DllImport("PitchTracker.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern int PtAKF_GetNote(IntPtr analyzer, [Out] out double maxVolume, [Out] float[] weights);
#endregion
- public static int GetTone(short[] samples, out double maxVolume, float[] weights)
+ private IntPtr _Instance;
+
+ public CPtAKF()
{
- return PtFast_GetTone(samples, samples.Length, out maxVolume, weights);
+ _Instance = PtAKF_Create();
+ }
+
+ ~CPtAKF()
+ {
+ _Dispose(false);
+ }
+
+ public void Input(byte[] data)
+ {
+ PtAKF_InputByte(_Instance, data, data.Length / 2);
+ }
+
+ public int GetNote(out double maxVolume, float[] weights)
+ {
+ return PtAKF_GetNote(_Instance, out maxVolume, weights);
+ }
+
+ private void _Dispose(bool disposing)
+ {
+ if (_Instance == IntPtr.Zero)
+ throw new ObjectDisposedException(GetType().Name);
+ PtAKF_Free(_Instance);
+ _Instance = IntPtr.Zero;
+ }
+
+ public void Dispose()
+ {
+ _Dispose(true);
+ GC.SuppressFinalize(this);
}
}
}
\ No newline at end of file
diff --git a/Vocaluxe/Lib/Sound/Record/CBuffer.cs b/Vocaluxe/Lib/Sound/Record/CBuffer.cs
index 6b4db2f8..f2114109 100644
--- a/Vocaluxe/Lib/Sound/Record/CBuffer.cs
+++ b/Vocaluxe/Lib/Sound/Record/CBuffer.cs
@@ -29,22 +29,19 @@ namespace Vocaluxe.Lib.Sound.Record
{
class CBuffer : IDisposable
{
+#if TEST_PITCH
//Half tones: C C♯ D D# E F F♯ G G♯ A A# B
private const double _BaseToneFreq = 65.4064; // lowest (half-)tone to analyze (C2 = 65.4064 Hz)
-#if TEST_PITCH
private const double _HalftoneBase = 1.05946309436; // 2^(1/12) -> HalftoneBase^12 = 2 (one octave)
#endif
- private const int _HalfToneMin = 0; // C2
- private const int _HalfToneMax = 38; //45; // inclusive, 38=D5; 45=A5
- public const int NumHalfTones = _HalfToneMax - _HalfToneMin + 1; //Number of halftones to analyze
- private CAnalyzer _Analyzer = new CAnalyzer(_BaseToneFreq, _HalfToneMin, _HalfToneMax);
+ private CPtAKF _Analyzer = new CPtAKF();
private double _MaxVolume;
public CBuffer()
{
MinVolume = 0.02f;
- ToneWeigths = new float[NumHalfTones];
+ ToneWeigths = new float[GetNumHalfTones()];
Reset();
#if TEST_PITCH
_TestPitchDetection();
@@ -56,6 +53,11 @@ namespace Vocaluxe.Lib.Sound.Record
_Dispose();
}
+ public static int GetNumHalfTones()
+ {
+ return CPtAKF.GetNumHalfTones();
+ }
+
public int ToneAbs { get; private set; }
public int Tone { get; set; }
@@ -98,7 +100,7 @@ namespace Vocaluxe.Lib.Sound.Record
{
//_Analyzer.Process();
//_MaxVolume = _Analyzer.GetPeak() / 43 + 1;
- int tone = _Analyzer.GetNoteFast(out _MaxVolume, ToneWeigths); //(int)Math.Round(_Analyzer.FindNote()); //
+ int tone = _Analyzer.GetNote(out _MaxVolume, ToneWeigths); //(int)Math.Round(_Analyzer.FindNote()); //
if (tone >= 0 && _MaxVolume >= MinVolume)
{
ToneAbs = tone;
@@ -142,7 +144,7 @@ namespace Vocaluxe.Lib.Sound.Record
if (_PitchTestRun)
return;
_PitchTestRun = true;
- int toneFrom = Math.Max(0, _HalfToneMin);
+ int toneFrom = 0;
const int toneTo = 47; //B5
Console.WriteLine("Testing notes " + _ToneToNote(toneFrom) + " - " + _ToneToNote(toneTo));
byte[] data;
diff --git a/Vocaluxe/Lib/Sound/Record/CRecordBase.cs b/Vocaluxe/Lib/Sound/Record/CRecordBase.cs
index 074a7711..f68fc268 100644
--- a/Vocaluxe/Lib/Sound/Record/CRecordBase.cs
+++ b/Vocaluxe/Lib/Sound/Record/CRecordBase.cs
@@ -132,7 +132,7 @@ namespace Vocaluxe.Lib.Sound.Record
public int NumHalfTones()
{
- return CBuffer.NumHalfTones;
+ return CBuffer.GetNumHalfTones();
}
public float[] ToneWeigth(int player)