diff options
author | matthewsotoudeh <matthewsot@outlook.com> | 2016-09-05 18:08:25 -0700 |
---|---|---|
committer | matthewsotoudeh <matthewsot@outlook.com> | 2016-09-05 18:08:25 -0700 |
commit | ca227e22c764cf7a0b7e7998d1113b4230cc78e3 (patch) | |
tree | 0f217a9317c86c9ace430f791955de2c6afca20d | |
parent | 6b8d632411145d135bd9491b7234e316e53d3185 (diff) |
added basic solution
-rw-r--r-- | MFCCDotNet/MFCCDotNet.sln | 22 | ||||
-rw-r--r-- | MFCCDotNet/MFCCDotNet/AssemblyInfo.fs | 35 | ||||
-rw-r--r-- | MFCCDotNet/MFCCDotNet/MFCC.fs | 104 | ||||
-rw-r--r-- | MFCCDotNet/MFCCDotNet/MFCCDotNet.fsproj | 61 | ||||
-rw-r--r-- | MFCCDotNet/MFCCDotNet/Script.fsx | 6 | ||||
-rw-r--r-- | MFCCDotNet/MFCCDotNet/packages.config | 6 |
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 |