From 980644108e3359a7b49ff628a7460d714af030b5 Mon Sep 17 00:00:00 2001 From: Flamefire Date: Fri, 28 Mar 2014 22:13:52 +0100 Subject: [PATCH] Add FastAnalyzer to the class (split it later) Fix some bugs Use FastAnalyzer as Analyzer seems not to be reliable by now (need further tests) --- PitchTracker/PitchWrapper.cpp | 15 ++++++++------- PitchTracker/PitchWrapper.h | 4 ++-- PitchTracker/pitch.cc | 2 +- PitchTracker/pitch.hh | 2 +- PitchTracker/pitchTracker.cpp | 15 ++++++++------- PitchTracker/pitchTracker.h | 2 +- Vocaluxe/Lib/Sound/Record/CAnalyzer.cs | 12 ++++++------ Vocaluxe/Lib/Sound/Record/CBuffer.cs | 19 ++++++++++++------- 8 files changed, 39 insertions(+), 32 deletions(-) diff --git a/PitchTracker/PitchWrapper.cpp b/PitchTracker/PitchWrapper.cpp index 45a29b18..992b6c10 100644 --- a/PitchTracker/PitchWrapper.cpp +++ b/PitchTracker/PitchWrapper.cpp @@ -10,12 +10,13 @@ AnalyzerExt::~AnalyzerExt(){ PitchTracker::DeInit(); } -int AnalyzerExt::GetNoteFast(float* weights){ +int AnalyzerExt::GetNoteFast(double* maxVolume, float* weights){ size_t size = m_fastAnalysisBuf.size(); if(size > m_SampleCt) m_fastAnalysisBuf.pop(size - m_SampleCt); - m_fastAnalysisBuf.read(m_AnalysisBuf, m_AnalysisBuf + m_SampleCt); - return PitchTracker::GetTone(m_AnalysisBuf, m_SampleCt, weights); + if(!m_fastAnalysisBuf.read(m_AnalysisBuf, m_AnalysisBuf + m_SampleCt)) + return -1; + return PitchTracker::GetTone(m_AnalysisBuf, m_SampleCt, maxVolume, weights); } void PtFast_Init(double baseToneFrequency, int minHalfTone, int maxHalfTone){ @@ -26,11 +27,11 @@ void PtFast_DeInit(){ PitchTracker::DeInit(); } -int PtFast_GetTone(short* samples, int sampleCt, float* weights){ +int PtFast_GetTone(short* samples, int sampleCt, double* maxVolume, float* weights){ if(sampleCt <= 0) return -1; double* dataDouble = short2DoubleArray(samples, sampleCt, false); - int result = PitchTracker::GetTone(dataDouble, sampleCt, weights, true); + int result = PitchTracker::GetTone(dataDouble, sampleCt, maxVolume, weights, true); freeDoubleArray(dataDouble); return result; } @@ -85,10 +86,10 @@ double Analyzer_FindNote(AnalyzerExt* analyzer, double minFreq, double maxFreq){ return (tone == NULL) ? -1 : ToneToNote(tone); } -int Analyzer_GetNoteFast(AnalyzerExt* analyzer, float* weights){ +int Analyzer_GetNoteFast(AnalyzerExt* analyzer, double* maxVolume, float* weights){ if(!analyzer) return -1; - return analyzer->GetNoteFast(weights); + return analyzer->GetNoteFast(maxVolume, weights); } bool Analyzer_OutputFloat(AnalyzerExt* analyzer, float* data, int sampleCt, float rate){ diff --git a/PitchTracker/PitchWrapper.h b/PitchTracker/PitchWrapper.h index 09298158..37fc9444 100644 --- a/PitchTracker/PitchWrapper.h +++ b/PitchTracker/PitchWrapper.h @@ -12,7 +12,7 @@ public: m_fastAnalysisBuf.insert(begin, end); Analyzer::input(begin, end); } - int GetNoteFast(float* weights); + 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 @@ -30,7 +30,7 @@ DllExport void Analyzer_InputShort(AnalyzerExt* analyzer, short* data, int sampl 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, float* weights); +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); diff --git a/PitchTracker/pitch.cc b/PitchTracker/pitch.cc index 85af7d5f..760dc9dc 100644 --- a/PitchTracker/pitch.cc +++ b/PitchTracker/pitch.cc @@ -137,7 +137,7 @@ void Analyzer::calcTones() { double phase = std::arg(m_fft[k]); // process phase difference double delta = phase - m_fftLastPhase[k]; - m_fftLastPhase[k] = phase; + m_fftLastPhase[k] = static_cast(phase); delta -= k * phaseStep; // subtract expected phase difference delta = remainder(delta, 2.0 * M_PI); // map delta phase into +/- M_PI interval delta /= phaseStep; // calculate diff from bin center frequency diff --git a/PitchTracker/pitch.hh b/PitchTracker/pitch.hh index f153ecd8..ff3d982e 100644 --- a/PitchTracker/pitch.hh +++ b/PitchTracker/pitch.hh @@ -52,7 +52,7 @@ public: /// Read data from current position if there is enough data to fill the range (otherwise return false). Does not move read pointer. template bool read(OutIt begin, OutIt end) { size_t r = m_read; - if (size() <= static_cast(end - begin)) return false; // Not enough audio available + if (size() < static_cast(end - begin)) return false; // Not enough audio available while (begin != end) *begin++ = m_buf[r++ % SIZE]; // Copy audio to output iterator return true; } diff --git a/PitchTracker/pitchTracker.cpp b/PitchTracker/pitchTracker.cpp index bd075c7e..8850fb1b 100644 --- a/PitchTracker/pitchTracker.cpp +++ b/PitchTracker/pitchTracker.cpp @@ -89,21 +89,22 @@ namespace PitchTracker{ } template - int GetTone(T *samples, int sampleCt, float *weights, bool scale){ + int GetTone(T *samples, int sampleCt, double* maxVolume, float *weights, bool scale){ if(!SamplesPerPeriodPerTone) return -1; - T maxVolume = 0; + T maxVolumeL = 0; for(int i = 0; i < sampleCt; i++){ T vol = abs(samples[i]); - if(vol > maxVolume) - maxVolume = vol; + if(vol > maxVolumeL) + maxVolumeL = vol; } + *maxVolume = maxVolumeL; T maxWeight = -1; T minWeight = 1; int maxTone = -1; for (int toneIndex = MinHalfTone; toneIndex <= MaxHalfTone; toneIndex++) { - T curWeight = _AnalyzeToneFunc(samples, sampleCt, toneIndex) / maxVolume; + T curWeight = _AnalyzeToneFunc(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 @@ -124,7 +125,7 @@ namespace PitchTracker{ }else return -1; } - template int GetTone(float *samples, int sampleCt, float *weights, bool scale); - template int GetTone(double *samples, int sampleCt, float *weights, bool scale); + 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 diff --git a/PitchTracker/pitchTracker.h b/PitchTracker/pitchTracker.h index a03d5926..3d3c2de0 100644 --- a/PitchTracker/pitchTracker.h +++ b/PitchTracker/pitchTracker.h @@ -3,7 +3,7 @@ namespace PitchTracker{ void Init(double baseToneFrequency, int minHalfTone, int maxHalfTone); void DeInit(); - template int GetTone(T *samples, int sampleCt, float *weights, bool scale = false); + template int GetTone(T *samples, int sampleCt, double* maxVolume, float *weights, bool scale = false); typedef void (__stdcall * LogCallback)(const char* text); static LogCallback Log; diff --git a/Vocaluxe/Lib/Sound/Record/CAnalyzer.cs b/Vocaluxe/Lib/Sound/Record/CAnalyzer.cs index 676f37b3..426572d0 100644 --- a/Vocaluxe/Lib/Sound/Record/CAnalyzer.cs +++ b/Vocaluxe/Lib/Sound/Record/CAnalyzer.cs @@ -28,7 +28,7 @@ namespace Vocaluxe.Lib.Sound.Record private static extern double Analyzer_GetPeak(IntPtr analyzer); [DllImport("PitchTracker.dll", CallingConvention = CallingConvention.Cdecl)] - private static extern double Analyzer_GetNoteFast(IntPtr analyzer, [Out] float[] weights); + 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); @@ -79,9 +79,9 @@ namespace Vocaluxe.Lib.Sound.Record return Analyzer_FindNote(_Instance, minFreq, maxFreq); } - public double GetNoteFast(float[] weights) + public int GetNoteFast(out double maxVolume, float[] weights) { - return Analyzer_GetNoteFast(_Instance, weights); + return Analyzer_GetNoteFast(_Instance, out maxVolume, weights); } public bool Output(float[] data, float rate) @@ -114,12 +114,12 @@ namespace Vocaluxe.Lib.Sound.Record public static extern void DeInit(); [DllImport("PitchTracker.dll", EntryPoint = "PtFast_GetTone", CallingConvention = CallingConvention.Cdecl)] - private static extern int PtFast_GetTone([In] short[] samples, int sampleCt, [Out] float[] weights); + private static extern int PtFast_GetTone([In] short[] samples, int sampleCt, [Out] out double maxVolume, [Out] float[] weights); #endregion - public static int GetTone(short[] samples, float[] weights) + public static int GetTone(short[] samples, out double maxVolume, float[] weights) { - return PtFast_GetTone(samples, samples.Length, weights); + return PtFast_GetTone(samples, samples.Length, out maxVolume, weights); } } } \ No newline at end of file diff --git a/Vocaluxe/Lib/Sound/Record/CBuffer.cs b/Vocaluxe/Lib/Sound/Record/CBuffer.cs index edcbb9b3..6b4db2f8 100644 --- a/Vocaluxe/Lib/Sound/Record/CBuffer.cs +++ b/Vocaluxe/Lib/Sound/Record/CBuffer.cs @@ -96,10 +96,10 @@ namespace Vocaluxe.Lib.Sound.Record public void AnalyzeBuffer() { - _Analyzer.Process(); - _MaxVolume = _Analyzer.GetPeak() / 43 + 1; - int tone = (int)Math.Round(_Analyzer.FindNote()); - if (tone >= 0) + //_Analyzer.Process(); + //_MaxVolume = _Analyzer.GetPeak() / 43 + 1; + int tone = _Analyzer.GetNoteFast(out _MaxVolume, ToneWeigths); //(int)Math.Round(_Analyzer.FindNote()); // + if (tone >= 0 && _MaxVolume >= MinVolume) { ToneAbs = tone; Tone = ToneAbs % 12; @@ -146,6 +146,7 @@ namespace Vocaluxe.Lib.Sound.Record const int toneTo = 47; //B5 Console.WriteLine("Testing notes " + _ToneToNote(toneFrom) + " - " + _ToneToNote(toneTo)); byte[] data; + byte[] data2 = new byte[2048]; int ok = 0; double angle = 0; for (int distort = 0; distort < 10; distort++) @@ -155,8 +156,12 @@ namespace Vocaluxe.Lib.Sound.Record _GetSineWave(_BaseToneFreq * Math.Pow(_HalftoneBase, tone), 44100, ref angle, out data); _Distort(data, tone, distort); - ProcessNewBuffer(data); - AnalyzeBuffer(); + for (int i = 0; i < 4; i++) + { + Buffer.BlockCopy(data, i * 2048, data2, 0, 2048); + ProcessNewBuffer(data2); + AnalyzeBuffer(); + } if (!ToneValid) CBase.Log.LogDebug("Note " + _ToneToNote(tone) + " not detected (Distortion: " + distort + ")"); else if (Tone != tone % 12) @@ -168,7 +173,7 @@ namespace Vocaluxe.Lib.Sound.Record _GetSineWave(_BaseToneFreq * Math.Pow(_HalftoneBase, 5), 44100, ref angle, out data); Stopwatch sw = new Stopwatch(); sw.Start(); - const int repeats = 1000; + const int repeats = 100; for (int i = 0; i < repeats; i++) { ProcessNewBuffer(data);