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
|
||||
#include "pitch.hh"
|
||||
#include "PitchWrapper.h"
|
||||
|
||||
#pragma managed(push, off)
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <cmath>
|
||||
|
||||
@@ -43,19 +40,23 @@ void freeDoubleArray(double* 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 PitchTracking{
|
||||
CTone^ ConvertToneToManaged(Tone tone){
|
||||
CTone^ ConvertToneToManaged(Tone* tone){
|
||||
CTone^ result = gcnew CTone();
|
||||
result->Freq = tone.freq;
|
||||
result->DB = tone.db;
|
||||
result->Stabledb = tone.stabledb;
|
||||
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->Freq = tone->freq;
|
||||
result->DB = tone->db;
|
||||
result->Stabledb = tone->stabledb;
|
||||
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->Note = static_cast<int>(std::round(result->NoteExact));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
@@ -170,20 +170,7 @@
|
||||
<ClCompile Include="compatibility.cpp" />
|
||||
<ClCompile Include="pitch.cc" />
|
||||
<ClCompile Include="pitchTracker.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>
|
||||
<ClCompile Include="PitchWrapper.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="compatibility.h" />
|
||||
|
||||
@@ -1,10 +1,82 @@
|
||||
#include "PitchWrapper.h"
|
||||
#pragma managed(push, off)
|
||||
#include "pitchTracker.h"
|
||||
#pragma managed(pop)
|
||||
|
||||
#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 PitchTracking{
|
||||
|
||||
@@ -31,7 +103,7 @@ namespace Native{
|
||||
if(data->Length == 0)
|
||||
return;
|
||||
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);
|
||||
freeFloatArray(dataFloat);
|
||||
}
|
||||
@@ -64,7 +136,7 @@ namespace Native{
|
||||
|
||||
CTone^ CAnalyzer::FindTone(double minFreq, double 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){
|
||||
@@ -98,4 +170,5 @@ namespace Native{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
+63
-54
@@ -1,63 +1,72 @@
|
||||
#pragma once
|
||||
|
||||
#pragma managed(push, off)
|
||||
#include "pitch.hh"
|
||||
#pragma managed(pop)
|
||||
|
||||
using namespace System;
|
||||
using namespace System::Collections::Generic;
|
||||
#define DllExport extern "C" __declspec(dllexport)
|
||||
|
||||
namespace Native{
|
||||
namespace PitchTracking{
|
||||
public ref class CTone {
|
||||
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; }
|
||||
};
|
||||
DllExport void PtFast_Init(double baseToneFrequency, int minHalfTone, int maxHalfTone);
|
||||
DllExport void PtFast_DeInit();
|
||||
DllExport int PtFast_GetTone(short* samples, int sampleCt, float* weights);
|
||||
|
||||
public ref class CAnalyzer {
|
||||
public:
|
||||
CAnalyzer(double rate, String^ id) {
|
||||
m_analyzer = new Analyzer(rate,"");
|
||||
m_id = id;
|
||||
}
|
||||
CAnalyzer(double rate, String^ id, unsigned step) {
|
||||
m_analyzer = new Analyzer(rate,"",step);
|
||||
m_id = id;
|
||||
}
|
||||
~CAnalyzer() { this->!CAnalyzer(); }
|
||||
!CAnalyzer() { delete m_analyzer; }
|
||||
DllExport Analyzer* Analyzer_Create(double rate, 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);
|
||||
|
||||
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();
|
||||
/*
|
||||
public ref class CTone {
|
||||
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; }
|
||||
};
|
||||
|
||||
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);
|
||||
};
|
||||
public ref class CAnalyzer {
|
||||
public:
|
||||
CAnalyzer(double rate, String^ id) {
|
||||
m_analyzer = new Analyzer(rate,"");
|
||||
m_id = id;
|
||||
}
|
||||
}
|
||||
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;
|
||||
const unsigned size = m_passthrough.size();
|
||||
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 */);
|
||||
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) {
|
||||
double s = 0.0;
|
||||
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_resampleFactor = 0.99 * m_resampleFactor + 0.01 * (size > 700 ? 1.02 : 0.98);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ public:
|
||||
return best;
|
||||
}
|
||||
/** 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 */
|
||||
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.IO;
|
||||
using System.Diagnostics;
|
||||
#if USE_NATIVE_DETECTION
|
||||
using Native.PitchTracking;
|
||||
|
||||
#endif
|
||||
#if TEST_PITCH
|
||||
using System.Windows.Forms;
|
||||
using VocaluxeLib;
|
||||
@@ -74,7 +71,7 @@ namespace Vocaluxe.Lib.Sound.Record
|
||||
private double _MinWeightDiff;
|
||||
// ReSharper restore FieldCanBeMadeReadOnly.Local
|
||||
#else
|
||||
private readonly CAnalyzer _Analyzer = new CAnalyzer(44100.0, "");
|
||||
private readonly CAnalyzer _Analyzer = new CAnalyzer();
|
||||
#endif
|
||||
private double _MaxVolume;
|
||||
private bool _NewSamples;
|
||||
@@ -115,7 +112,7 @@ namespace Vocaluxe.Lib.Sound.Record
|
||||
if (_InitCount > 1)
|
||||
return; //Do init only once
|
||||
#if USE_NATIVE_DETECTION
|
||||
CPitchTracker.Init(_BaseToneFreq, _HalfToneMin, _HalfToneMax);
|
||||
CFastAnalyzer.Init(_BaseToneFreq, _HalfToneMin, _HalfToneMax);
|
||||
#else
|
||||
//Init Array to avoid costly calculations
|
||||
for (int toneIndex = 0; toneIndex <= _HalfToneMax; toneIndex++)
|
||||
@@ -239,7 +236,7 @@ namespace Vocaluxe.Lib.Sound.Record
|
||||
private void _AnalyzeTones()
|
||||
{
|
||||
#if USE_NATIVE_DETECTION
|
||||
int maxTone = CPitchTracker.GetTone(_AnalysisBuffer, _TmpWeights);
|
||||
int maxTone = CFastAnalyzer.GetTone(_AnalysisBuffer, _TmpWeights);
|
||||
if (maxTone >= 0)
|
||||
#else
|
||||
// prepare to analyze
|
||||
@@ -350,7 +347,7 @@ namespace Vocaluxe.Lib.Sound.Record
|
||||
Debug.Assert(_InitCount > 0);
|
||||
_InitCount--;
|
||||
if (_InitCount == 0)
|
||||
CPitchTracker.DeInit();
|
||||
CFastAnalyzer.DeInit();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -199,10 +199,6 @@
|
||||
<Reference Include="OpenTK.GLControl">
|
||||
<HintPath>..\Output\OpenTK.GLControl.dll</HintPath>
|
||||
</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">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\Output\PortAudioSharp.dll</HintPath>
|
||||
@@ -227,6 +223,7 @@
|
||||
<Compile Include="Lib\Sound\Playback\OpenAL\COpenAlStream.cs" />
|
||||
<Compile Include="Lib\Sound\Playback\PortAudio\CPortAudioStream.cs" />
|
||||
<Compile Include="Lib\Sound\CPortAudioHandle.cs" />
|
||||
<Compile Include="Lib\Sound\Record\CAnalyzer.cs" />
|
||||
<Compile Include="Lib\Sound\Record\CBuffer.cs" />
|
||||
<Compile Include="Base\CConfig.cs" />
|
||||
<Compile Include="Base\CCover.cs" />
|
||||
|
||||
Reference in new issue
Block a user