Add a native version of the pitch detection algo as C# is to slow for exact real time detection(Speedup: 10)
This commit is contained in:
1 parent
f6499efd38
commit
8eb42b5a5f
7 files changed
+460
-28
No files matched your search
+5
-8
@@ -14,13 +14,13 @@ Output/Songs
|
||||
/*.ctl
|
||||
/Output/Registration.xml
|
||||
/Vocaluxe.suo
|
||||
/Vocaluxe/Vocaluxe.csproj.user
|
||||
*.csproj.user
|
||||
*.vcxproj.user
|
||||
/Output/Config.xml
|
||||
*.ipch
|
||||
*.log
|
||||
/Output/Playlists/*.xml
|
||||
/Output/x64/gstreamer/GstreamerHelper.dll
|
||||
/Output/x86/gstreamer/GstreamerHelper.dll
|
||||
GstreamerHelper.dll
|
||||
*.tlog
|
||||
*.suo
|
||||
*.obj
|
||||
@@ -39,11 +39,7 @@ Output/Songs
|
||||
*.Cache
|
||||
/GstreamerHelper/bin/*
|
||||
/VocaluxeLib/bin
|
||||
/ClientServerLib/ClientServerLib/ClientServerLib.csproj.user
|
||||
/ClientServerLib/ClientServerLib/bin/Debug/ClientServerLib.dll
|
||||
/ClientServerLib/ClientTest/bin/Debug/ClientServerLib.dll
|
||||
/ClientServerLib/ClientTest/bin/Release/ClientServerLib.dll
|
||||
/ClientServerLib/ClientServerLib/bin/ClientServerLib.dll
|
||||
ClientServerLib.dll
|
||||
ClientTest.exe
|
||||
*.vshost.*
|
||||
*.userprefs
|
||||
@@ -63,3 +59,4 @@ Output/Vocaluxe_x64.exe
|
||||
/Output/VocaluxeServerConfig.exe.config
|
||||
/PhoneGap/
|
||||
/Output/Profiles
|
||||
PitchTracker.dll
|
||||
@@ -0,0 +1,178 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{54A48AF7-515C-4EDD-B395-2BFFA096050A}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>PitchTracker</RootNamespace>
|
||||
<ProjectName>PitchTracker</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v110_xp</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v110_xp</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v110_xp</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v110_xp</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>bin\$(Configuration).$(Platform)\</OutDir>
|
||||
<IntDir>obj\$(Configuration).$(Platform)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>bin\$(Configuration).$(Platform)\</OutDir>
|
||||
<IntDir>obj\$(Configuration).$(Platform)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>bin\$(Configuration).$(Platform)\</OutDir>
|
||||
<IntDir>obj\$(Configuration).$(Platform)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>bin\$(Configuration).$(Platform)\</OutDir>
|
||||
<IntDir>obj\$(Configuration).$(Platform)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN64;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<FloatingPointModel>Fast</FloatingPointModel>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>xcopy "$(OutDir)*.dll" "$(SolutionDir)Output\x64\" /I /Y</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<FloatingPointModel>Fast</FloatingPointModel>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>xcopy "$(OutDir)*.dll" "$(SolutionDir)Output\x86\" /I /Y</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
<FloatingPointModel>Fast</FloatingPointModel>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>xcopy "$(OutDir)*.dll" "$(SolutionDir)Output\x64\" /I /Y</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<FloatingPointModel>Fast</FloatingPointModel>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>xcopy "$(OutDir)*.dll" "$(SolutionDir)Output\x86\" /I /Y</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pitchTracker.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pitchTracker.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Quelldateien">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Headerdateien">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Ressourcendateien">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pitchTracker.cpp">
|
||||
<Filter>Quelldateien</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pitchTracker.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,115 @@
|
||||
// This file is part of Vocaluxe.
|
||||
//
|
||||
// Vocaluxe is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Vocaluxe is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "pitchTracker.h"
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
double *SamplesPerPeriodPerTone = NULL;
|
||||
int MinHalfTone = 0, MaxHalfTone = 38;
|
||||
const double HalftoneBase = 1.05946309436; // 2^(1/12) -> HalftoneBase^12 = 2 (one octave)
|
||||
|
||||
void Init(double baseToneFrequency, int minHalfTone, int maxHalfTone){
|
||||
MinHalfTone = minHalfTone;
|
||||
MaxHalfTone = maxHalfTone;
|
||||
DeInit();
|
||||
if(maxHalfTone <= 0)
|
||||
return;
|
||||
SamplesPerPeriodPerTone = (double*) malloc(MaxHalfTone * sizeof(double));
|
||||
//Init Array to avoid costly calculations
|
||||
for (int toneIndex = 0; toneIndex <= MaxHalfTone; toneIndex++)
|
||||
{
|
||||
double freq = baseToneFrequency * pow(HalftoneBase, toneIndex);
|
||||
SamplesPerPeriodPerTone[toneIndex] = 44100.0 / freq; // samples in one period
|
||||
}
|
||||
}
|
||||
|
||||
void DeInit(){
|
||||
if(SamplesPerPeriodPerTone){
|
||||
free(SamplesPerPeriodPerTone);
|
||||
SamplesPerPeriodPerTone=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static double _AnalyzeToneFunc(double *samples, int sampleCt, int toneIndex){
|
||||
double samplesPerPeriodD = SamplesPerPeriodPerTone[toneIndex]; // samples in one period
|
||||
int samplesPerPeriod = (int)samplesPerPeriodD;
|
||||
double fHigh = samplesPerPeriodD - samplesPerPeriod;
|
||||
double fLow = 1.0 - fHigh;
|
||||
|
||||
double accumDist = 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 (lower means more distant)
|
||||
double dist = samples[sampleIndex] * (samples[correlatingSampleIndex] * fLow + samples[correlatingSampleIndex + 1] * fHigh);
|
||||
accumDist += dist;
|
||||
}
|
||||
|
||||
//Using _AnalysisBufLen here makes it return correct values among all analyzed frequencies
|
||||
double scaleValue = 32767.0 * 32767.0 * sampleCt; // Divide also by Int16.MaxValue^2
|
||||
return accumDist / scaleValue;
|
||||
}
|
||||
|
||||
int GetTone(double *samples, int sampleCt, float *weights){
|
||||
double maxVolume = 0;
|
||||
for(int i = 0; i < sampleCt; i++){
|
||||
double vol = abs(samples[i]);
|
||||
if(vol > maxVolume)
|
||||
maxVolume = vol;
|
||||
}
|
||||
double maxWeight = -1;
|
||||
double minWeight = 1;
|
||||
int maxTone = -1;
|
||||
for (int toneIndex = MinHalfTone; toneIndex <= MaxHalfTone; toneIndex++)
|
||||
{
|
||||
double curWeight = _AnalyzeToneFunc(samples, sampleCt, toneIndex) / maxVolume * 32767.0;
|
||||
|
||||
if (curWeight > maxWeight)
|
||||
{
|
||||
maxWeight = curWeight;
|
||||
maxTone = toneIndex;
|
||||
}
|
||||
|
||||
if (curWeight < minWeight)
|
||||
minWeight = curWeight;
|
||||
|
||||
weights[toneIndex] = (float) curWeight;
|
||||
}
|
||||
|
||||
if(maxWeight - minWeight > 0.01){
|
||||
return maxTone;
|
||||
}else return -1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef dywapitchtrack__H
|
||||
#define dywapitchtrack__H
|
||||
|
||||
#define DllExport extern "C" __declspec(dllexport)
|
||||
|
||||
DllExport void Init(double baseToneFrequency, int minHalfTone, int maxHalfTone);
|
||||
DllExport void DeInit();
|
||||
DllExport int GetTone(double *samples, int sampleCt, float *weights);
|
||||
|
||||
typedef void (__stdcall * LogCallback)(const char* text);
|
||||
static LogCallback Log;
|
||||
DllExport void SetLogCallback(LogCallback Callback);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -9,6 +9,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vocaluxe", "Vocaluxe\Vocalu
|
||||
{EC5167E4-CCFB-4CEE-987C-CF816F1062A3} = {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}
|
||||
{D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC} = {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}
|
||||
{5A4053F1-5AD5-441F-B254-D97A088127B6} = {5A4053F1-5AD5-441F-B254-D97A088127B6}
|
||||
{54A48AF7-515C-4EDD-B395-2BFFA096050A} = {54A48AF7-515C-4EDD-B395-2BFFA096050A}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VocaluxeLib", "VocaluxeLib\VocaluxeLib.csproj", "{D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}"
|
||||
@@ -25,6 +26,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServerLib", "ClientServerLi
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebserverInitalConfig", "WebserverInitalConfig\WebserverInitalConfig.csproj", "{55F89808-4E79-4FFE-BC13-48258913F5C9}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PitchTracker", "PitchTracker\PitchTracker.vcxproj", "{54A48AF7-515C-4EDD-B395-2BFFA096050A}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
DebugLinux|x64 = DebugLinux|x64
|
||||
@@ -191,6 +194,26 @@ Global
|
||||
{55F89808-4E79-4FFE-BC13-48258913F5C9}.ReleaseWin|x64.Build.0 = Release|Any CPU
|
||||
{55F89808-4E79-4FFE-BC13-48258913F5C9}.ReleaseWin|x86.ActiveCfg = Release|Any CPU
|
||||
{55F89808-4E79-4FFE-BC13-48258913F5C9}.ReleaseWin|x86.Build.0 = Release|Any CPU
|
||||
{54A48AF7-515C-4EDD-B395-2BFFA096050A}.DebugLinux|x64.ActiveCfg = Debug|x64
|
||||
{54A48AF7-515C-4EDD-B395-2BFFA096050A}.DebugLinux|x64.Build.0 = Debug|x64
|
||||
{54A48AF7-515C-4EDD-B395-2BFFA096050A}.DebugLinux|x86.ActiveCfg = Debug|Win32
|
||||
{54A48AF7-515C-4EDD-B395-2BFFA096050A}.DebugLinux|x86.Build.0 = Debug|Win32
|
||||
{54A48AF7-515C-4EDD-B395-2BFFA096050A}.DebugWin|x64.ActiveCfg = Debug|x64
|
||||
{54A48AF7-515C-4EDD-B395-2BFFA096050A}.DebugWin|x64.Build.0 = Debug|x64
|
||||
{54A48AF7-515C-4EDD-B395-2BFFA096050A}.DebugWin|x86.ActiveCfg = Debug|Win32
|
||||
{54A48AF7-515C-4EDD-B395-2BFFA096050A}.DebugWin|x86.Build.0 = Debug|Win32
|
||||
{54A48AF7-515C-4EDD-B395-2BFFA096050A}.InstallerWin|x64.ActiveCfg = Release|x64
|
||||
{54A48AF7-515C-4EDD-B395-2BFFA096050A}.InstallerWin|x64.Build.0 = Release|x64
|
||||
{54A48AF7-515C-4EDD-B395-2BFFA096050A}.InstallerWin|x86.ActiveCfg = Release|Win32
|
||||
{54A48AF7-515C-4EDD-B395-2BFFA096050A}.InstallerWin|x86.Build.0 = Release|Win32
|
||||
{54A48AF7-515C-4EDD-B395-2BFFA096050A}.ReleaseLinux|x64.ActiveCfg = Release|x64
|
||||
{54A48AF7-515C-4EDD-B395-2BFFA096050A}.ReleaseLinux|x64.Build.0 = Release|x64
|
||||
{54A48AF7-515C-4EDD-B395-2BFFA096050A}.ReleaseLinux|x86.ActiveCfg = Release|Win32
|
||||
{54A48AF7-515C-4EDD-B395-2BFFA096050A}.ReleaseLinux|x86.Build.0 = Release|Win32
|
||||
{54A48AF7-515C-4EDD-B395-2BFFA096050A}.ReleaseWin|x64.ActiveCfg = Release|x64
|
||||
{54A48AF7-515C-4EDD-B395-2BFFA096050A}.ReleaseWin|x64.Build.0 = Release|x64
|
||||
{54A48AF7-515C-4EDD-B395-2BFFA096050A}.ReleaseWin|x86.ActiveCfg = Release|Win32
|
||||
{54A48AF7-515C-4EDD-B395-2BFFA096050A}.ReleaseWin|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -1,9 +1,29 @@
|
||||
#define TEST_PITCH
|
||||
#region license
|
||||
// This file is part of Vocaluxe.
|
||||
//
|
||||
// Vocaluxe is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Vocaluxe is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
|
||||
#endregion
|
||||
|
||||
#define TEST_PITCH
|
||||
#define USE_NATIVE_DETECTION
|
||||
//If defined, it uses a library with native code that speeds up detection by a factor of 10
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
#if TEST_PITCH
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Forms;
|
||||
using VocaluxeLib;
|
||||
|
||||
@@ -11,16 +31,29 @@ using VocaluxeLib;
|
||||
|
||||
namespace Vocaluxe.Lib.Sound.Record
|
||||
{
|
||||
#if USE_NATIVE_DETECTION
|
||||
static class CPitchTracker
|
||||
{
|
||||
[DllImport("PitchTracker.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void Init(double baseToneFrequency, int minHalfTone, int maxHalfTone);
|
||||
|
||||
[DllImport("PitchTracker.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void DeInit();
|
||||
|
||||
[DllImport("PitchTracker.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern int GetTone(double[] samples, int sampleCt, float[] weights);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
|
||||
public delegate void LogCallback(string message);
|
||||
|
||||
[DllImport("PitchTracker.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void SetLogCallback(LogCallback c);
|
||||
}
|
||||
#endif
|
||||
|
||||
class CBuffer : IDisposable
|
||||
{
|
||||
public enum EAnalyzeFunction
|
||||
{
|
||||
AutoCorrelation, //Faster, more resistent to noise, good value for HalfToneMax=38 (higher->wrong results in test case, WHY?) with 38 no wrong values in test case
|
||||
Amdf //Average magnitude difference, slower, detects everything in range -> HalfToneMax=45
|
||||
}
|
||||
|
||||
private delegate double DAnalyzeTone(int tone);
|
||||
|
||||
private static int _InitCount;
|
||||
//Half tones: C C♯ D Eb E F F♯ G G♯ A Bb B
|
||||
private const double _BaseToneFreq = 65.4064; // lowest (half-)tone to analyze (C2 = 65.4064 Hz)
|
||||
private const double _HalftoneBase = 1.05946309436; // 2^(1/12) -> HalftoneBase^12 = 2 (one octave)
|
||||
@@ -34,9 +67,18 @@ namespace Vocaluxe.Lib.Sound.Record
|
||||
private readonly double[] _AnalysisBuffer = new double[_AnalysisBufLen];
|
||||
private readonly byte[] _AnalysisByteBuffer = new byte[_AnalysisByteBufLen]; //tmp buffer (stream->tmpBuffer->(Int16)AnalysisBuffer)
|
||||
|
||||
//Precalculated table holding sample# per period for each tone (actually we may not use the lower few entries, but keep it to avoid index modification
|
||||
private readonly float[] _TmpWeights = new float[NumHalfTones]; //tmp buffer for weights (gets copied to ToneWeight when checked)
|
||||
#if !USE_NATIVE_DETECTION
|
||||
//Precalculated table holding sample# per period for each tone (actually we may not use the lower few entries, but keep it to avoid index modification
|
||||
private static readonly double[] _SamplesPerPeriodPerTone = new double[_HalfToneMax + 1];
|
||||
private readonly float[] _TmpWeight = new float[NumHalfTones]; //tmp buffer for weights (gets copied to ToneWeight when checked)
|
||||
|
||||
public enum EAnalyzeFunction
|
||||
{
|
||||
AutoCorrelation, //Faster, more resistent to noise, good value for HalfToneMax=38 (higher->wrong results in test case, WHY?) with 38 no wrong values in test case
|
||||
Amdf //Average magnitude difference, slower, detects everything in range -> HalfToneMax=45
|
||||
}
|
||||
private delegate double DAnalyzeTone(int tone);
|
||||
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// ReSharper disable ConvertToConstant.Global
|
||||
// ReSharper disable FieldCanBeMadeReadOnly.Global
|
||||
@@ -48,7 +90,7 @@ namespace Vocaluxe.Lib.Sound.Record
|
||||
private DAnalyzeTone _AnalyzeToneFunc;
|
||||
private double _MinWeightDiff;
|
||||
// ReSharper restore FieldCanBeMadeReadOnly.Local
|
||||
|
||||
#endif
|
||||
private double _MaxVolume;
|
||||
private bool _NewSamples;
|
||||
|
||||
@@ -56,9 +98,11 @@ namespace Vocaluxe.Lib.Sound.Record
|
||||
|
||||
public CBuffer()
|
||||
{
|
||||
_Init();
|
||||
MinVolume = 0.02f;
|
||||
ToneWeigth = new float[NumHalfTones];
|
||||
Reset();
|
||||
#if !USE_NATIVE_DETECTION
|
||||
if (AnalyzeFunction == EAnalyzeFunction.Amdf)
|
||||
{
|
||||
_AnalyzeToneFunc = _GetAmdf;
|
||||
@@ -69,19 +113,32 @@ namespace Vocaluxe.Lib.Sound.Record
|
||||
_AnalyzeToneFunc = _GetAutoCorrelation;
|
||||
_MinWeightDiff = 0.0001;
|
||||
}
|
||||
#endif
|
||||
#if TEST_PITCH
|
||||
_TestPitchDetection();
|
||||
#endif
|
||||
}
|
||||
|
||||
static CBuffer()
|
||||
~CBuffer()
|
||||
{
|
||||
//Init Array to avoid costly calculations
|
||||
_Dispose();
|
||||
}
|
||||
|
||||
private static void _Init()
|
||||
{
|
||||
_InitCount++;
|
||||
if (_InitCount > 1)
|
||||
return; //Do init only once
|
||||
#if USE_NATIVE_DETECTION
|
||||
CPitchTracker.Init(_BaseToneFreq, _HalfToneMin, _HalfToneMax);
|
||||
#else
|
||||
//Init Array to avoid costly calculations
|
||||
for (int toneIndex = 0; toneIndex <= _HalfToneMax; toneIndex++)
|
||||
{
|
||||
double freq = _BaseToneFreq * Math.Pow(_HalftoneBase, toneIndex);
|
||||
_SamplesPerPeriodPerTone[toneIndex] = 44100.0 / freq; // samples in one period
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public int ToneAbs { get; private set; }
|
||||
@@ -98,7 +155,7 @@ namespace Vocaluxe.Lib.Sound.Record
|
||||
public float[] ToneWeigth { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Minimum volume for a tone to be valid
|
||||
/// Minimum volume for a tone to be valid
|
||||
/// </summary>
|
||||
public float MinVolume { get; set; }
|
||||
|
||||
@@ -183,7 +240,11 @@ namespace Vocaluxe.Lib.Sound.Record
|
||||
|
||||
private void _AnalyzeTones()
|
||||
{
|
||||
// prepare to analyze
|
||||
#if USE_NATIVE_DETECTION
|
||||
int maxTone = CPitchTracker.GetTone(_AnalysisBuffer, _AnalysisBufLen, _TmpWeights);
|
||||
if (maxTone >= 0)
|
||||
#else
|
||||
// prepare to analyze
|
||||
double maxWeight = -1.0;
|
||||
double minWeight = 1.0;
|
||||
int maxTone = -1;
|
||||
@@ -206,12 +267,13 @@ namespace Vocaluxe.Lib.Sound.Record
|
||||
if (curWeight < minWeight)
|
||||
minWeight = curWeight;
|
||||
|
||||
_TmpWeight[toneIndex - _HalfToneMin] = (float)curWeight;
|
||||
_TmpWeights[toneIndex - _HalfToneMin] = (float)curWeight;
|
||||
}
|
||||
|
||||
if (maxWeight - minWeight > _MinWeightDiff)
|
||||
#endif
|
||||
{
|
||||
Array.Copy(_TmpWeight, ToneWeigth, NumHalfTones);
|
||||
Array.Copy(_TmpWeights, ToneWeigth, NumHalfTones);
|
||||
|
||||
ToneAbs = maxTone;
|
||||
//Console.WriteLine(maxTone);
|
||||
@@ -222,6 +284,7 @@ namespace Vocaluxe.Lib.Sound.Record
|
||||
ToneValid = false;
|
||||
}
|
||||
|
||||
#if !USE_NATIVE_DETECTION
|
||||
private double _GetAutoCorrelation(int tone)
|
||||
{
|
||||
double samplesPerPeriodD = _SamplesPerPeriodPerTone[tone]; // samples in one period
|
||||
@@ -269,17 +332,29 @@ namespace Vocaluxe.Lib.Sound.Record
|
||||
accumDist += dist;
|
||||
}
|
||||
//Use analyzed sample count here. BufLen yields more errors
|
||||
return 1.0 - (double)accumDist / Int16.MaxValue / sampleIndex;
|
||||
return 1.0 - accumDist / Int16.MaxValue / sampleIndex;
|
||||
}
|
||||
#endif
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_Dispose();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private void _Dispose()
|
||||
{
|
||||
if (_Stream != null)
|
||||
{
|
||||
_Stream.Dispose();
|
||||
_Stream = null;
|
||||
}
|
||||
GC.SuppressFinalize(this);
|
||||
#if USE_NATIVE_DETECTION
|
||||
Debug.Assert(_InitCount > 0);
|
||||
_InitCount--;
|
||||
if (_InitCount == 0)
|
||||
CPitchTracker.DeInit();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if TEST_PITCH
|
||||
|
||||
Reference in new issue
Block a user