Remove C++/Cli version and replace with P/Invoke wrapper to support all platforms
This commit is contained in:
1 parent
e54892391f
commit
ae9f8bb30a
9 files changed
+283
-100
No files matched your search
+12
-11
@@ -1,9 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "pitch.hh"
|
#include "pitch.hh"
|
||||||
#include "PitchWrapper.h"
|
#include "PitchWrapper.h"
|
||||||
|
|
||||||
#pragma managed(push, off)
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
@@ -43,19 +40,23 @@ void freeDoubleArray(double* floats){
|
|||||||
free(floats);
|
free(floats);
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma managed(pop)
|
double ToneToNote(const Tone* tone){
|
||||||
|
return 12.0 * std::log(tone->freq / 127.09) / std::log(2.0) + 27.5 - 16; // 16 = C2
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
namespace Native{
|
namespace Native{
|
||||||
namespace PitchTracking{
|
namespace PitchTracking{
|
||||||
CTone^ ConvertToneToManaged(Tone tone){
|
CTone^ ConvertToneToManaged(Tone* tone){
|
||||||
CTone^ result = gcnew CTone();
|
CTone^ result = gcnew CTone();
|
||||||
result->Freq = tone.freq;
|
result->Freq = tone->freq;
|
||||||
result->DB = tone.db;
|
result->DB = tone->db;
|
||||||
result->Stabledb = tone.stabledb;
|
result->Stabledb = tone->stabledb;
|
||||||
result->Age = static_cast<int>(tone.age);
|
result->Age = static_cast<int>(tone->age);
|
||||||
result->NoteExact = 12.0 * std::log(tone.freq / 127.09) / std::log(2.0) + 27.5 - 16; // 16 = C2
|
result->NoteExact = 12.0 * std::log(tone->freq / 127.09) / std::log(2.0) + 27.5 - 16; // 16 = C2
|
||||||
result->Note = static_cast<int>(std::round(result->NoteExact));
|
result->Note = static_cast<int>(std::round(result->NoteExact));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
@@ -170,20 +170,7 @@
|
|||||||
<ClCompile Include="compatibility.cpp" />
|
<ClCompile Include="compatibility.cpp" />
|
||||||
<ClCompile Include="pitch.cc" />
|
<ClCompile Include="pitch.cc" />
|
||||||
<ClCompile Include="pitchTracker.cpp" />
|
<ClCompile Include="pitchTracker.cpp" />
|
||||||
<ClCompile Include="PitchWrapper.cpp">
|
<ClCompile Include="PitchWrapper.cpp" />
|
||||||
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</CompileAsManaged>
|
|
||||||
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</CompileAsManaged>
|
|
||||||
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</CompileAsManaged>
|
|
||||||
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</CompileAsManaged>
|
|
||||||
<MinimalRebuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</MinimalRebuild>
|
|
||||||
<MinimalRebuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</MinimalRebuild>
|
|
||||||
<ExceptionHandling Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</ExceptionHandling>
|
|
||||||
<ExceptionHandling Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExceptionHandling>
|
|
||||||
<ExceptionHandling Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExceptionHandling>
|
|
||||||
<ExceptionHandling Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExceptionHandling>
|
|
||||||
<BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Default</BasicRuntimeChecks>
|
|
||||||
<BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Default</BasicRuntimeChecks>
|
|
||||||
</ClCompile>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="compatibility.h" />
|
<ClInclude Include="compatibility.h" />
|
||||||
|
|||||||
@@ -1,10 +1,82 @@
|
|||||||
#include "PitchWrapper.h"
|
#include "PitchWrapper.h"
|
||||||
#pragma managed(push, off)
|
|
||||||
#include "pitchTracker.h"
|
#include "pitchTracker.h"
|
||||||
#pragma managed(pop)
|
|
||||||
|
|
||||||
#include "Helper.h"
|
#include "Helper.h"
|
||||||
|
|
||||||
|
void PtFast_Init(double baseToneFrequency, int minHalfTone, int maxHalfTone){
|
||||||
|
PitchTracker::Init(baseToneFrequency, minHalfTone, maxHalfTone);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PtFast_DeInit(){
|
||||||
|
PitchTracker::DeInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
int PtFast_GetTone(short* samples, int sampleCt, float* weights){
|
||||||
|
if(sampleCt <= 0)
|
||||||
|
return -1;
|
||||||
|
double* dataDouble = short2DoubleArray(samples, sampleCt, false);
|
||||||
|
int result = PitchTracker::GetTone(dataDouble, sampleCt, weights, true);
|
||||||
|
freeDoubleArray(dataDouble);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Analyzer* Analyzer_Create(double rate, unsigned step){
|
||||||
|
return new Analyzer(rate, "", step);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Analyzer_Free(Analyzer* analyzer){
|
||||||
|
if(analyzer)
|
||||||
|
delete analyzer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Analyzer_InputFloat(Analyzer* analyzer, float* data, int sampleCt){
|
||||||
|
if(sampleCt == 0 || !analyzer)
|
||||||
|
return;
|
||||||
|
analyzer->input(data, data + sampleCt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Analyzer_InputShort(Analyzer* analyzer, short* data, int sampleCt){
|
||||||
|
if(sampleCt == 0 || !analyzer)
|
||||||
|
return;
|
||||||
|
float* dataFloat = short2FloatArray(data, sampleCt);
|
||||||
|
analyzer->input(dataFloat, dataFloat + sampleCt);
|
||||||
|
freeFloatArray(dataFloat);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Analyzer_InputByte(Analyzer* analyzer, char* data, int sampleCt){
|
||||||
|
if(sampleCt == 0 || !analyzer)
|
||||||
|
return;
|
||||||
|
float* dataFloat = short2FloatArray(static_cast<short*>(static_cast<void*>(data)), sampleCt);
|
||||||
|
analyzer->input(dataFloat, dataFloat + sampleCt);
|
||||||
|
freeFloatArray(dataFloat);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Analyzer_Process(Analyzer* analyzer){
|
||||||
|
if(!analyzer)
|
||||||
|
return;
|
||||||
|
analyzer->process();
|
||||||
|
}
|
||||||
|
|
||||||
|
double Analyzer_GetPeak(Analyzer* analyzer){
|
||||||
|
if(!analyzer)
|
||||||
|
return -999;
|
||||||
|
return analyzer->getPeak();
|
||||||
|
}
|
||||||
|
|
||||||
|
double Analyzer_FindNote(Analyzer* analyzer, double minFreq, double maxFreq){
|
||||||
|
if(!analyzer)
|
||||||
|
return -1;
|
||||||
|
const Tone* tone = analyzer->findTone(minFreq, maxFreq);
|
||||||
|
return (tone == NULL) ? -1 : ToneToNote(tone);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Analyzer_OutputFloat(Analyzer* analyzer, float* data, int sampleCt, float rate){
|
||||||
|
if(!analyzer)
|
||||||
|
return false;
|
||||||
|
return analyzer->output(data, data + sampleCt, rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
namespace Native{
|
namespace Native{
|
||||||
namespace PitchTracking{
|
namespace PitchTracking{
|
||||||
|
|
||||||
@@ -31,7 +103,7 @@ namespace Native{
|
|||||||
if(data->Length == 0)
|
if(data->Length == 0)
|
||||||
return;
|
return;
|
||||||
pin_ptr<Byte> dataPtr = &data[0];
|
pin_ptr<Byte> dataPtr = &data[0];
|
||||||
float* dataFloat = short2FloatArray(static_cast<short*>(static_cast<void*>(dataPtr)), data->Length);
|
float* dataFloat = short2FloatArray(static_cast<short*>(static_cast<void*>(dataPtr)), data->Length / 2);
|
||||||
m_analyzer->input(dataFloat, dataFloat + data->Length);
|
m_analyzer->input(dataFloat, dataFloat + data->Length);
|
||||||
freeFloatArray(dataFloat);
|
freeFloatArray(dataFloat);
|
||||||
}
|
}
|
||||||
@@ -64,7 +136,7 @@ namespace Native{
|
|||||||
|
|
||||||
CTone^ CAnalyzer::FindTone(double minFreq, double maxFreq){
|
CTone^ CAnalyzer::FindTone(double minFreq, double maxFreq){
|
||||||
const Tone* tone = m_analyzer->findTone(minFreq, maxFreq);
|
const Tone* tone = m_analyzer->findTone(minFreq, maxFreq);
|
||||||
return (tone == NULL) ? nullptr : ConvertToneToManaged(*tone);
|
return (tone == NULL) ? nullptr : ConvertToneToManaged(tone);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAnalyzer::Output(array<float>^ data, float rate){
|
void CAnalyzer::Output(array<float>^ data, float rate){
|
||||||
@@ -98,4 +170,5 @@ namespace Native{
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
+63
-54
@@ -1,63 +1,72 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#pragma managed(push, off)
|
|
||||||
#include "pitch.hh"
|
#include "pitch.hh"
|
||||||
#pragma managed(pop)
|
|
||||||
|
|
||||||
using namespace System;
|
#define DllExport extern "C" __declspec(dllexport)
|
||||||
using namespace System::Collections::Generic;
|
|
||||||
|
|
||||||
namespace Native{
|
DllExport void PtFast_Init(double baseToneFrequency, int minHalfTone, int maxHalfTone);
|
||||||
namespace PitchTracking{
|
DllExport void PtFast_DeInit();
|
||||||
public ref class CTone {
|
DllExport int PtFast_GetTone(short* samples, int sampleCt, float* weights);
|
||||||
public:
|
|
||||||
static const int MAXHARM = 48; ///< The maximum number of harmonics tracked
|
|
||||||
static const int MINAGE = 2; ///< The minimum age required for a tone to be output
|
|
||||||
double Freq; ///< Frequency (Hz)
|
|
||||||
double DB; ///< Level (dB)
|
|
||||||
double Stabledb; ///< Stable level, useful for graphics rendering
|
|
||||||
int Age; ///< How many times the tone has been detected in row
|
|
||||||
double NoteExact;
|
|
||||||
int Note;
|
|
||||||
/// Less-than compare by levels (instead of frequencies like operator< does)
|
|
||||||
static bool dbCompare(CTone l, CTone r) { return l.DB < r.DB; }
|
|
||||||
};
|
|
||||||
|
|
||||||
public ref class CAnalyzer {
|
DllExport Analyzer* Analyzer_Create(double rate, unsigned step);
|
||||||
public:
|
DllExport void Analyzer_Free(Analyzer* analyzer);
|
||||||
CAnalyzer(double rate, String^ id) {
|
DllExport void Analyzer_InputFloat(Analyzer* analyzer, float* data, int sampleCt);
|
||||||
m_analyzer = new Analyzer(rate,"");
|
DllExport void Analyzer_InputShort(Analyzer* analyzer, short* data, int sampleCt);
|
||||||
m_id = id;
|
DllExport void Analyzer_InputByte(Analyzer* analyzer, char* data, int sampleCt);
|
||||||
}
|
DllExport void Analyzer_Process(Analyzer* analyzer);
|
||||||
CAnalyzer(double rate, String^ id, unsigned step) {
|
DllExport double Analyzer_GetPeak(Analyzer* analyzer);
|
||||||
m_analyzer = new Analyzer(rate,"",step);
|
DllExport double Analyzer_FindNote(Analyzer* analyzer, double minFreq, double maxFreq);
|
||||||
m_id = id;
|
DllExport bool Analyzer_OutputFloat(Analyzer* analyzer, float* data, int sampleCt, float rate);
|
||||||
}
|
|
||||||
~CAnalyzer() { this->!CAnalyzer(); }
|
|
||||||
!CAnalyzer() { delete m_analyzer; }
|
|
||||||
|
|
||||||
void Input(array<float>^ data);
|
/*
|
||||||
void Input(array<short>^ data);
|
public ref class CTone {
|
||||||
void Input(array<Byte>^ data);
|
public:
|
||||||
void Process();
|
static const int MAXHARM = 48; ///< The maximum number of harmonics tracked
|
||||||
double GetPeak();
|
static const int MINAGE = 2; ///< The minimum age required for a tone to be output
|
||||||
array<CTone^>^ GetTones();
|
double Freq; ///< Frequency (Hz)
|
||||||
CTone^ FindTone();
|
double DB; ///< Level (dB)
|
||||||
CTone^ FindTone(double minFreq);
|
double Stabledb; ///< Stable level, useful for graphics rendering
|
||||||
CTone^ FindTone(double minFreq, double maxFreq);
|
int Age; ///< How many times the tone has been detected in row
|
||||||
void Output(array<float>^ data, float rate);
|
double NoteExact;
|
||||||
String^ GetId();
|
int Note;
|
||||||
|
/// Less-than compare by levels (instead of frequencies like operator< does)
|
||||||
|
static bool dbCompare(CTone l, CTone r) { return l.DB < r.DB; }
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
public ref class CAnalyzer {
|
||||||
Analyzer* m_analyzer;
|
public:
|
||||||
String^ m_id;
|
CAnalyzer(double rate, String^ id) {
|
||||||
};
|
m_analyzer = new Analyzer(rate,"");
|
||||||
|
m_id = id;
|
||||||
public ref class CPitchTracker abstract sealed{
|
|
||||||
public:
|
|
||||||
static void Init(double baseToneFrequency, int minHalfTone, int maxHalfTone);
|
|
||||||
static void DeInit();
|
|
||||||
static int GetTone(array<short>^ samples, array<float>^ weights);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
CAnalyzer(double rate, String^ id, unsigned step) {
|
||||||
|
m_analyzer = new Analyzer(rate,"",step);
|
||||||
|
m_id = id;
|
||||||
|
}
|
||||||
|
~CAnalyzer() { this->!CAnalyzer(); }
|
||||||
|
!CAnalyzer() { delete m_analyzer; }
|
||||||
|
|
||||||
|
void Input(array<float>^ data);
|
||||||
|
void Input(array<short>^ data);
|
||||||
|
void Input(array<Byte>^ data);
|
||||||
|
void Process();
|
||||||
|
double GetPeak();
|
||||||
|
array<CTone^>^ GetTones();
|
||||||
|
CTone^ FindTone();
|
||||||
|
CTone^ FindTone(double minFreq);
|
||||||
|
CTone^ FindTone(double minFreq, double maxFreq);
|
||||||
|
void Output(array<float>^ data, float rate);
|
||||||
|
String^ GetId();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Analyzer* m_analyzer;
|
||||||
|
String^ m_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
public ref class CPitchTracker abstract sealed{
|
||||||
|
public:
|
||||||
|
static void Init(double baseToneFrequency, int minHalfTone, int maxHalfTone);
|
||||||
|
static void DeInit();
|
||||||
|
static int GetTone(array<short>^ samples, array<float>^ weights);
|
||||||
|
};
|
||||||
|
*/
|
||||||
@@ -48,14 +48,15 @@ Analyzer::Analyzer(double rate, std::string id, std::size_t step):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Analyzer::output(float* begin, float* end, double rate) {
|
bool Analyzer::output(float* begin, float* end, double rate) {
|
||||||
constexpr unsigned a = 2;
|
constexpr unsigned a = 2;
|
||||||
const unsigned size = m_passthrough.size();
|
const unsigned size = m_passthrough.size();
|
||||||
const unsigned out = static_cast<unsigned>((end - begin) / 2 /* stereo */);
|
const unsigned out = static_cast<unsigned>((end - begin) / 2 /* stereo */);
|
||||||
if (out == 0) return;
|
if (out == 0) return false;
|
||||||
const unsigned in = static_cast<unsigned>(m_resampleFactor * (m_rate / rate) * out + 2 * a /* lanczos kernel */ + 5 /* safety margin for rounding errors */);
|
const unsigned in = static_cast<unsigned>(m_resampleFactor * (m_rate / rate) * out + 2 * a /* lanczos kernel */ + 5 /* safety margin for rounding errors */);
|
||||||
float pcm[m_passthrough.capacity];
|
float pcm[m_passthrough.capacity];
|
||||||
m_passthrough.read(pcm, pcm + in + 4);
|
if(!m_passthrough.read(pcm, pcm + in + 4))
|
||||||
|
return false;
|
||||||
for (unsigned i = 0; i < out; ++i) {
|
for (unsigned i = 0; i < out; ++i) {
|
||||||
double s = 0.0;
|
double s = 0.0;
|
||||||
unsigned k = static_cast<unsigned>(m_resamplePos);
|
unsigned k = static_cast<unsigned>(m_resamplePos);
|
||||||
@@ -77,6 +78,7 @@ void Analyzer::output(float* begin, float* end, double rate) {
|
|||||||
m_passthrough.pop(num);
|
m_passthrough.pop(num);
|
||||||
m_resampleFactor = 0.99 * m_resampleFactor + 0.01 * (size > 700 ? 1.02 : 0.98);
|
m_resampleFactor = 0.99 * m_resampleFactor + 0.01 * (size > 700 ? 1.02 : 0.98);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ public:
|
|||||||
return best;
|
return best;
|
||||||
}
|
}
|
||||||
/** Give data away for mic pass-through */
|
/** Give data away for mic pass-through */
|
||||||
void output(float* begin, float* end, double rate);
|
bool output(float* begin, float* end, double rate);
|
||||||
/** Returns the id (color name) of the mic */
|
/** Returns the id (color name) of the mic */
|
||||||
std::string const& getId() const { return m_id; }
|
std::string const& getId() const { return m_id; }
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,117 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace Vocaluxe.Lib.Sound.Record
|
||||||
|
{
|
||||||
|
class CAnalyzer : IDisposable
|
||||||
|
{
|
||||||
|
#region Imports
|
||||||
|
[DllImport("PitchTracker.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
private static extern IntPtr Analyzer_Create(double rate, uint step);
|
||||||
|
|
||||||
|
[DllImport("PitchTracker.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
private static extern void Analyzer_Free(IntPtr analyzer);
|
||||||
|
|
||||||
|
[DllImport("PitchTracker.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
private static extern void Analyzer_InputFloat(IntPtr analyzer, float[] data, int sampleCt);
|
||||||
|
|
||||||
|
[DllImport("PitchTracker.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
private static extern void Analyzer_InputShort(IntPtr analyzer, short[] data, int sampleCt);
|
||||||
|
|
||||||
|
[DllImport("PitchTracker.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
private static extern void Analyzer_InputByte(IntPtr analyzer, byte[] data, int sampleCt);
|
||||||
|
|
||||||
|
[DllImport("PitchTracker.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
private static extern void Analyzer_Process(IntPtr analyzer);
|
||||||
|
|
||||||
|
[DllImport("PitchTracker.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
private static extern double Analyzer_GetPeak(IntPtr analyzer);
|
||||||
|
|
||||||
|
[DllImport("PitchTracker.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
private static extern double Analyzer_FindNote(IntPtr analyzer, double minFreq, double maxFreq);
|
||||||
|
|
||||||
|
[DllImport("PitchTracker.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
private static extern bool Analyzer_OutputFloat(IntPtr analyzer, [Out] float[] data, int sampleCt, float rate);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private IntPtr _Instance;
|
||||||
|
|
||||||
|
public CAnalyzer(double rate = 44100.0, uint step = 200)
|
||||||
|
{
|
||||||
|
_Instance = Analyzer_Create(rate, step);
|
||||||
|
}
|
||||||
|
|
||||||
|
~CAnalyzer()
|
||||||
|
{
|
||||||
|
_Dispose(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Input(float[] data)
|
||||||
|
{
|
||||||
|
Analyzer_InputFloat(_Instance, data, data.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Input(short[] data)
|
||||||
|
{
|
||||||
|
Analyzer_InputShort(_Instance, data, data.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Input(byte[] data)
|
||||||
|
{
|
||||||
|
Analyzer_InputByte(_Instance, data, data.Length / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Process()
|
||||||
|
{
|
||||||
|
Analyzer_Process(_Instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double GetPeak()
|
||||||
|
{
|
||||||
|
return Analyzer_GetPeak(_Instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double FindNote(double minFreq = 35.0, double maxFreq = 1000.0)
|
||||||
|
{
|
||||||
|
return Analyzer_FindNote(_Instance, minFreq, maxFreq);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Output(float[] data, float rate)
|
||||||
|
{
|
||||||
|
return Analyzer_OutputFloat(_Instance, data, data.Length, rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void _Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (_Instance == IntPtr.Zero)
|
||||||
|
throw new ObjectDisposedException(GetType().Name);
|
||||||
|
Analyzer_Free(_Instance);
|
||||||
|
_Instance = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class CFastAnalyzer
|
||||||
|
{
|
||||||
|
#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", EntryPoint = "PtFast_DeInit", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
public static extern void DeInit();
|
||||||
|
|
||||||
|
[DllImport("PitchTracker.dll", EntryPoint = "PtFast_GetTone", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
private static extern int PtFast_GetTone(short[] samples, int sampleCt, float[] weights);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public static int GetTone(short[] samples, float[] weights)
|
||||||
|
{
|
||||||
|
return PtFast_GetTone(samples, samples.Length, weights);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,10 +22,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
#if USE_NATIVE_DETECTION
|
|
||||||
using Native.PitchTracking;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
#if TEST_PITCH
|
#if TEST_PITCH
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using VocaluxeLib;
|
using VocaluxeLib;
|
||||||
@@ -74,7 +71,7 @@ namespace Vocaluxe.Lib.Sound.Record
|
|||||||
private double _MinWeightDiff;
|
private double _MinWeightDiff;
|
||||||
// ReSharper restore FieldCanBeMadeReadOnly.Local
|
// ReSharper restore FieldCanBeMadeReadOnly.Local
|
||||||
#else
|
#else
|
||||||
private readonly CAnalyzer _Analyzer = new CAnalyzer(44100.0, "");
|
private readonly CAnalyzer _Analyzer = new CAnalyzer();
|
||||||
#endif
|
#endif
|
||||||
private double _MaxVolume;
|
private double _MaxVolume;
|
||||||
private bool _NewSamples;
|
private bool _NewSamples;
|
||||||
@@ -115,7 +112,7 @@ namespace Vocaluxe.Lib.Sound.Record
|
|||||||
if (_InitCount > 1)
|
if (_InitCount > 1)
|
||||||
return; //Do init only once
|
return; //Do init only once
|
||||||
#if USE_NATIVE_DETECTION
|
#if USE_NATIVE_DETECTION
|
||||||
CPitchTracker.Init(_BaseToneFreq, _HalfToneMin, _HalfToneMax);
|
CFastAnalyzer.Init(_BaseToneFreq, _HalfToneMin, _HalfToneMax);
|
||||||
#else
|
#else
|
||||||
//Init Array to avoid costly calculations
|
//Init Array to avoid costly calculations
|
||||||
for (int toneIndex = 0; toneIndex <= _HalfToneMax; toneIndex++)
|
for (int toneIndex = 0; toneIndex <= _HalfToneMax; toneIndex++)
|
||||||
@@ -239,7 +236,7 @@ namespace Vocaluxe.Lib.Sound.Record
|
|||||||
private void _AnalyzeTones()
|
private void _AnalyzeTones()
|
||||||
{
|
{
|
||||||
#if USE_NATIVE_DETECTION
|
#if USE_NATIVE_DETECTION
|
||||||
int maxTone = CPitchTracker.GetTone(_AnalysisBuffer, _TmpWeights);
|
int maxTone = CFastAnalyzer.GetTone(_AnalysisBuffer, _TmpWeights);
|
||||||
if (maxTone >= 0)
|
if (maxTone >= 0)
|
||||||
#else
|
#else
|
||||||
// prepare to analyze
|
// prepare to analyze
|
||||||
@@ -350,7 +347,7 @@ namespace Vocaluxe.Lib.Sound.Record
|
|||||||
Debug.Assert(_InitCount > 0);
|
Debug.Assert(_InitCount > 0);
|
||||||
_InitCount--;
|
_InitCount--;
|
||||||
if (_InitCount == 0)
|
if (_InitCount == 0)
|
||||||
CPitchTracker.DeInit();
|
CFastAnalyzer.DeInit();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -199,10 +199,6 @@
|
|||||||
<Reference Include="OpenTK.GLControl">
|
<Reference Include="OpenTK.GLControl">
|
||||||
<HintPath>..\Output\OpenTK.GLControl.dll</HintPath>
|
<HintPath>..\Output\OpenTK.GLControl.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="PitchTracker">
|
|
||||||
<HintPath>..\Output\x64\PitchTracker.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="PortAudioSharp, Version=0.19.3.27472, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="PortAudioSharp, Version=0.19.3.27472, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\Output\PortAudioSharp.dll</HintPath>
|
<HintPath>..\Output\PortAudioSharp.dll</HintPath>
|
||||||
@@ -227,6 +223,7 @@
|
|||||||
<Compile Include="Lib\Sound\Playback\OpenAL\COpenAlStream.cs" />
|
<Compile Include="Lib\Sound\Playback\OpenAL\COpenAlStream.cs" />
|
||||||
<Compile Include="Lib\Sound\Playback\PortAudio\CPortAudioStream.cs" />
|
<Compile Include="Lib\Sound\Playback\PortAudio\CPortAudioStream.cs" />
|
||||||
<Compile Include="Lib\Sound\CPortAudioHandle.cs" />
|
<Compile Include="Lib\Sound\CPortAudioHandle.cs" />
|
||||||
|
<Compile Include="Lib\Sound\Record\CAnalyzer.cs" />
|
||||||
<Compile Include="Lib\Sound\Record\CBuffer.cs" />
|
<Compile Include="Lib\Sound\Record\CBuffer.cs" />
|
||||||
<Compile Include="Base\CConfig.cs" />
|
<Compile Include="Base\CConfig.cs" />
|
||||||
<Compile Include="Base\CCover.cs" />
|
<Compile Include="Base\CCover.cs" />
|
||||||
|
|||||||
Reference in new issue
Block a user