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)