summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormatthewsotoudeh <matthewsot@outlook.com>2016-09-05 18:08:25 -0700
committermatthewsotoudeh <matthewsot@outlook.com>2016-09-05 18:08:25 -0700
commitca227e22c764cf7a0b7e7998d1113b4230cc78e3 (patch)
tree0f217a9317c86c9ace430f791955de2c6afca20d
parent6b8d632411145d135bd9491b7234e316e53d3185 (diff)
added basic solution
-rw-r--r--MFCCDotNet/MFCCDotNet.sln22
-rw-r--r--MFCCDotNet/MFCCDotNet/AssemblyInfo.fs35
-rw-r--r--MFCCDotNet/MFCCDotNet/MFCC.fs104
-rw-r--r--MFCCDotNet/MFCCDotNet/MFCCDotNet.fsproj61
-rw-r--r--MFCCDotNet/MFCCDotNet/Script.fsx6
-rw-r--r--MFCCDotNet/MFCCDotNet/packages.config6
6 files changed, 234 insertions, 0 deletions
diff --git a/MFCCDotNet/MFCCDotNet.sln b/MFCCDotNet/MFCCDotNet.sln
new file mode 100644
index 0000000..454706b
--- /dev/null
+++ b/MFCCDotNet/MFCCDotNet.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25420.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "MFCCDotNet", "MFCCDotNet\MFCCDotNet.fsproj", "{05825573-931A-4A57-B553-7E3AFF19B479}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {05825573-931A-4A57-B553-7E3AFF19B479}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {05825573-931A-4A57-B553-7E3AFF19B479}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {05825573-931A-4A57-B553-7E3AFF19B479}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {05825573-931A-4A57-B553-7E3AFF19B479}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/MFCCDotNet/MFCCDotNet/AssemblyInfo.fs b/MFCCDotNet/MFCCDotNet/AssemblyInfo.fs
new file mode 100644
index 0000000..b312b4f
--- /dev/null
+++ b/MFCCDotNet/MFCCDotNet/AssemblyInfo.fs
@@ -0,0 +1,35 @@
+namespace MFCCDotNet.AssemblyInfo
+
+open System.Resources
+open System.Reflection
+open System.Runtime.CompilerServices
+open System.Runtime.InteropServices
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[<assembly: AssemblyTitle("MFCCDotNet")>]
+[<assembly: AssemblyDescription("")>]
+[<assembly: AssemblyConfiguration("")>]
+[<assembly: AssemblyCompany("")>]
+[<assembly: AssemblyProduct("MFCCDotNet")>]
+[<assembly: AssemblyCopyright("Copyright © 2016")>]
+[<assembly: AssemblyTrademark("")>]
+[<assembly: AssemblyCulture("")>]
+[<assembly: NeutralResourcesLanguage("en")>]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [<assembly: AssemblyVersion("1.0.*")>]
+[<assembly: AssemblyVersion("1.0.0.0")>]
+[<assembly: AssemblyFileVersion("1.0.0.0")>]
+
+do
+ () \ No newline at end of file
diff --git a/MFCCDotNet/MFCCDotNet/MFCC.fs b/MFCCDotNet/MFCCDotNet/MFCC.fs
new file mode 100644
index 0000000..59159a7
--- /dev/null
+++ b/MFCCDotNet/MFCCDotNet/MFCC.fs
@@ -0,0 +1,104 @@
+namespace MFCCDotNet
+
+open System.Numerics
+open MathNet.Numerics.LinearAlgebra
+open MathNet.Numerics.IntegralTransforms
+open MathNet.Numerics
+
+module public MFCC =
+ type triangle_filter = { start_bin: int; peak_bin: int; end_bin: int; }
+
+ let mel (frequency) =
+ 1125.0 * log10 (1.0 + (frequency / 700.0));
+
+ let hertz (mel) =
+ 700.0 * exp ((mel / 1125.0) - 1.0)
+
+ let mutable _filterbank : seq<triangle_filter> = null
+
+ //See http://practicalcryptography.com/miscellaneous/machine-learning/guide-mel-frequency-cepstral-coefficients-mfccs/#computing-the-mel-filterbank
+ let compute_filterbank (num_filters, fft_size, sample_rate) =
+ if not (isNull _filterbank) then
+ _filterbank
+ else
+ let lower_freq = 300.0;
+ let upper_freq = 8000.0;
+ let lower_mel = mel(lower_freq);
+ let upper_mel = mel(upper_freq);
+ let mel_spacing = (upper_mel - lower_mel) / float (num_filters + 1);
+ let points_hertz = seq { for i in 0 .. (num_filters + 1) do yield hertz(lower_mel + (float i * mel_spacing)) };
+ let fft_bin_points = points_hertz |> Seq.map(fun hertz_point -> int (floor ((float fft_size + 1.0) * float (hertz_point / sample_rate))));
+
+ _filterbank <- seq {
+ for i in 1 .. num_filters do
+ yield {
+ start_bin = fft_bin_points |> Seq.item(i - 1);
+ peak_bin = fft_bin_points |> Seq.item(i);
+ end_bin = fft_bin_points |> Seq.item(i + 1);
+ };
+ };
+ _filterbank
+
+ let apply_filter (fft_output, filter : triangle_filter) =
+ let total = Array.length fft_output - 1;
+ seq {
+ for i in 0 .. total do
+ if (i = filter.peak_bin) then
+ yield fft_output.[i];
+ elif (i > filter.start_bin && i < filter.peak_bin) then
+ let filter_weight = float (i - filter.start_bin) / float (filter.peak_bin - filter.start_bin);
+ yield fft_output.[i] * filter_weight;
+ elif (i > filter.peak_bin && i < filter.end_bin) then
+ let filter_weight = float (filter.end_bin - i) / float (filter.end_bin - filter.peak_bin);
+ yield fft_output.[i] * filter_weight;
+ else yield 0.0;
+ }
+
+ //A more efficient Seq.sum(apply_filter())
+ let apply_and_sum_filter (fft_output : float[], filter : triangle_filter) =
+ let mutable total = 0.0;
+ for i = filter.start_bin to filter.end_bin do
+ if (i = filter.peak_bin) then
+ total <- total + fft_output.[i];
+ elif (i > filter.start_bin && i < filter.peak_bin) then
+ let filter_weight = float (i - filter.start_bin) / float (filter.peak_bin - filter.start_bin);
+ total <- total + fft_output.[i] * filter_weight;
+ elif (i > filter.peak_bin && i < filter.end_bin) then
+ let filter_weight = float (filter.end_bin - i) / float (filter.end_bin - filter.peak_bin);
+ total <- total + fft_output.[i] * filter_weight;
+ total;
+
+ //https://en.wikipedia.org/wiki/Discrete_cosine_transform
+ let dct (input:float[]) =
+ let N = Array.length input;
+ let output = Array.zeroCreate<float>(N);
+ for k in 0 .. N - 1 do
+ for n in 0 .. N - 1 do
+ let xn = input.[n];
+ Array.set output k (output.[k] + (xn * cos((float System.Math.PI / float N) * (float n + 0.5) * (float k))));
+
+ Array.set output 0 (output.[0] * (1.0 / sqrt 2.0))
+ let scale = sqrt (2.0 / float N)
+ output |> Array.map(fun el -> el * scale)
+
+ let compute (samples : float[], num_filters, num_features) =
+ let hamming = Window.Hamming(Array.length samples);
+ let windowed_samples = samples |> Array.mapi(fun index sample -> sample * hamming.[index]);
+
+ let mutable complex_output = windowed_samples |> Array.map(fun sample -> Complex(sample, 0.0));
+ Fourier.Forward(complex_output);
+ let abs_output = complex_output |> Array.map(fun sample -> sqrt ((sample.Real * sample.Real) + (sample.Imaginary * sample.Imaginary)));
+ //for extra optimization
+ //let abs_output = complex_output |> Array.map(fun sample -> abs sample.Real + abs sample.Imaginary);
+
+ let filters = compute_filterbank(num_filters, Array.length abs_output, 48000.0);
+ let accumulator = Array.zeroCreate<float>(Array.length abs_output);
+
+ let mel_output = filters |>
+ Seq.take(num_features) |>
+ Seq.map(fun filter -> log10(apply_and_sum_filter(abs_output, filter))) |>
+ Seq.toArray;
+ //|> Seq.fold (fun acc el -> acc |> Array.mapi(fun index acc_el -> acc_el + (el |> Seq.nth(index)))) accumulator;
+
+ let dct_output = dct(mel_output);
+ dct_output; \ No newline at end of file
diff --git a/MFCCDotNet/MFCCDotNet/MFCCDotNet.fsproj b/MFCCDotNet/MFCCDotNet/MFCCDotNet.fsproj
new file mode 100644
index 0000000..55b4f00
--- /dev/null
+++ b/MFCCDotNet/MFCCDotNet/MFCCDotNet.fsproj
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>05825573-931a-4a57-b553-7e3aff19b479</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <RootNamespace>MFCCDotNet</RootNamespace>
+ <AssemblyName>MFCCDotNet</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <TargetFrameworkProfile>Profile7</TargetFrameworkProfile>
+ <TargetProfile>netcore</TargetProfile>
+ <TargetFSharpCoreVersion>3.7.4.0</TargetFSharpCoreVersion>
+ <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
+ <Name>MFCCDotNet</Name>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <Tailcalls>false</Tailcalls>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <WarningLevel>3</WarningLevel>
+ <DocumentationFile>bin\Debug\MFCCDotNet.XML</DocumentationFile>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <Tailcalls>true</Tailcalls>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <WarningLevel>3</WarningLevel>
+ <DocumentationFile>bin\Release\MFCCDotNet.XML</DocumentationFile>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="FSharp.Core">
+ <Name>FSharp.Core</Name>
+ <AssemblyName>FSharp.Core.dll</AssemblyName>
+ <HintPath>$(MSBuildExtensionsPath32)\..\Reference Assemblies\Microsoft\FSharp\.NETCore\$(TargetFSharpCoreVersion)\FSharp.Core.dll</HintPath>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="AssemblyInfo.fs" />
+ <Compile Include="PortableLibrary1.fs" />
+ <None Include="Script.fsx" />
+ </ItemGroup>
+ <PropertyGroup>
+ <MinimumVisualStudioVersion Condition="'$(MinimumVisualStudioVersion)' == ''">12</MinimumVisualStudioVersion>
+ </PropertyGroup>
+ <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.Portable.FSharp.Targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/MFCCDotNet/MFCCDotNet/Script.fsx b/MFCCDotNet/MFCCDotNet/Script.fsx
new file mode 100644
index 0000000..0519c09
--- /dev/null
+++ b/MFCCDotNet/MFCCDotNet/Script.fsx
@@ -0,0 +1,6 @@
+// Learn more about F# at http://fsharp.org. See the 'F# Tutorial' project
+// for more guidance on F# programming.
+
+#load "PortableLibrary1.fs"
+open MFCCDotNet
+
diff --git a/MFCCDotNet/MFCCDotNet/packages.config b/MFCCDotNet/MFCCDotNet/packages.config
new file mode 100644
index 0000000..f109b94
--- /dev/null
+++ b/MFCCDotNet/MFCCDotNet/packages.config
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="FSharp.Core" version="4.0.0.1" targetFramework="portable45-net45+win8" />
+ <package id="MathNet.Numerics" version="3.13.0" targetFramework="portable45-net45+win8" />
+ <package id="MathNet.Numerics.FSharp" version="3.13.0" targetFramework="portable45-net45+win8" />
+</packages> \ No newline at end of file
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback