From fe670f0e36a5ee4d150ae0a009a228b466ed4877 Mon Sep 17 00:00:00 2001 From: "Matthew C. Kelley" Date: Sat, 19 Nov 2022 15:15:39 -0800 Subject: [PATCH 1/2] Remove MFCC submodule and depend on package --- Project.toml | 5 +- README.md | 9 +- src/MFCC/LICENSE | 21 --- src/MFCC/MFCC.jl | 24 --- src/MFCC/feacalc.jl | 176 ---------------------- src/MFCC/io.jl | 93 ------------ src/MFCC/mfccs.jl | 184 ----------------------- src/MFCC/nomodule.jl | 14 -- src/MFCC/rasta.jl | 330 ------------------------------------------ src/Phonetics.jl | 2 - src/acdist.jl | 2 +- test/MFCC/LICENSE | 19 --- test/MFCC/bl2.mfcc | Bin 19072 -> 0 bytes test/MFCC/bl2.wav | Bin 67244 -> 0 bytes test/MFCC/runtests.jl | 27 ---- test/runtests.jl | 7 +- 16 files changed, 6 insertions(+), 907 deletions(-) delete mode 100644 src/MFCC/LICENSE delete mode 100644 src/MFCC/MFCC.jl delete mode 100644 src/MFCC/feacalc.jl delete mode 100644 src/MFCC/io.jl delete mode 100644 src/MFCC/mfccs.jl delete mode 100644 src/MFCC/nomodule.jl delete mode 100644 src/MFCC/rasta.jl delete mode 100644 test/MFCC/LICENSE delete mode 100644 test/MFCC/bl2.mfcc delete mode 100644 test/MFCC/bl2.wav delete mode 100644 test/MFCC/runtests.jl diff --git a/Project.toml b/Project.toml index ab13703..d783dc5 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "Phonetics" uuid = "e3a49ea3-7edf-49e1-b84f-839ab305a372" authors = ["Matthew C. Kelley -Currently under development. Some function interfaces may break from time to time while in early releases. - -Please note that the MFCC module is effectively a simple static link to the source code from [MFCC.jl v0.3.2](https://github.com/JuliaDSP/MFCC.jl), which is permitted under the BSD-2 license it was conveyed under. It has only been trivially modified to work with newer versions of `HDF5.jl` and to work as a statically linked library. The licenses for that code by itself are provided within the `src/MFCC` and `test/MFCC` folders. If you use the MFCC module itself from `Phonetics.jl` in your own work, please make sure to give credit as appropriate to David A. van Leeuwen, according to the license in the MFCC module folder. - -The license for the `Phonetics.jl` project as a whole is given in the `LICENSE.txt` file in the root folder. Please note that statically including the `MFCC.jl` code is currently intended as a stopgap while version compatiblity is resolved in `MFCC.jl` so that dynamic linking of it via the package manager can be retinroduced. - `Phonetics.jl` can be installed with ```julia diff --git a/src/MFCC/LICENSE b/src/MFCC/LICENSE deleted file mode 100644 index a689cb6..0000000 --- a/src/MFCC/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -Copyright (c) 2013--2014 David A. van Leeuwen, (c) 2005--2012, Dan Ellis -All rights reserved. - -Updated (trivially) 2022 by Matthew C. Kelley to work with newer versions of Julia and associated packages - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the -following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this list of conditions and -the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and -the following disclaimer in the documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - diff --git a/src/MFCC/MFCC.jl b/src/MFCC/MFCC.jl deleted file mode 100644 index d324df7..0000000 --- a/src/MFCC/MFCC.jl +++ /dev/null @@ -1,24 +0,0 @@ -## MFCC.jl -## (c) 2013-2015 David A. van Leeuwen, (c) 2005--2012 Dan Ellis - -## Recoded from / inspired by melfcc from Dan Ellis's rastamat package. - -module MFCC - -export powspec, audspec, postaud, lifter -export mfcc, deltas, warp, sdc, znorm, znorm!, stmvn -export feasave, feaload, feasize -export feacalc - -using DSP -using HDF5 -using WAV -using SpecialFunctions ## erfinv -using Statistics - -include("rasta.jl") -include("mfccs.jl") -include("feacalc.jl") -include("io.jl") - -end diff --git a/src/MFCC/feacalc.jl b/src/MFCC/feacalc.jl deleted file mode 100644 index d2f82a3..0000000 --- a/src/MFCC/feacalc.jl +++ /dev/null @@ -1,176 +0,0 @@ -## Feacalc.jl Full implementation of feature calculation for speech files. -## (c) 2013-2016 David A. van Leeuwen - -## Feacalc. Feature calculation as used for speaker and language recognition. - -nrow(x) = size(x,1) -ncol(x) = size(x,2) - -## compute features according to standard settingsm directly from a wav file. -## this does channel at the time. -function feacalc(wavfile::AbstractString; method=:wav, kwargs...) - if method == :wav - (x, sr) = wavread(wavfile) - elseif method == :sox - (x, sr) = soxread(wavfile) - elseif method == :sphere - (x, sr) = sphread(wavfile) - end - sr = Float64(sr) # more reasonable sr - feacalc(x; sr=sr, source=wavfile, kwargs...) -end - -## assume we have an array already -function feacalc(x::Array; augtype=:ddelta, normtype=:warp, sadtype=:energy, dynrange::Real=30., nwarp::Int=399, chan=:mono, sr::AbstractFloat=8000.0, source=":array", defaults=:nbspeaker, mfccargs...) - if ndims(x) > 1 - nsamples, nchan = size(x) - if chan == :mono - x = vec(mean(x, dims=2)) # averave multiple channels for now - elseif in(chan, [:a, :b]) - channum = findin([:a, :b], [chan]) - x = vec(x[:,channum]) - elseif isa(chan, Integer) - if !(chan in 1:nchan) - error("Bad channel specification: ", chan) - end - x = vec(x[:,chan]) - chan=[:a, :b][chan] - else - error("Unknown channel specification: ", chan) - end - else - nsamples, nchan = length(x), 1 - end - ## save some metadata - meta = Dict("nsamples" => nsamples, "sr" => sr, "source" => source, "nchan" => nchan, - "chan" => chan) - preemph = 0.97 - preemph ^= 16000. / sr - - ## basic features - (m, pspec, params) = mfcc(x, sr, defaults; preemph=preemph, mfccargs...) - meta["totnframes"] = nrow(m) - - ## augment features - if augtype==:delta || augtype==:ddelta - d = deltas(m) - if augtype==:ddelta - dd = deltas(d) - m = hcat(m, d, dd) - else - m = hcat(m, d) - end - elseif augtype==:sdc - m = sdc(m) - end - meta["augtype"] = augtype - - if nrow(m)>0 - if sadtype==:energy - ## integrate power - deltaf = size(pspec,2) / (sr/2) - minfreqi = round(Int, 300deltaf) - maxfreqi = round(Int, 4000deltaf) - power = 10log10(sum(pspec[:,minfreqi:maxfreqi], 2)) - - maxpow = maximum(power) - speech = findall(power .> maxpow - dynrange) - params["dynrange"] = dynrange - elseif sadtype==:none - speech = collect(1:nrow(m)) - end - else - speech=Int[] - end - meta["sadtype"] = sadtype - ## perform SAD - m = m[speech,:] - meta["speech"] = map(UInt32, speech) - meta["nframes"] , meta["nfea"] = size(m) - - ## normalization - if nrow(m)>0 - if normtype==:warp - m = warp(m, nwarp) - params["warp"] = nwarp # the default - elseif normtype==:mvn - if nrow(m)>1 - znorm!(m,1) - else - fill!(m, 0) - end - end - meta["normtype"] = normtype - end - return(map(Float32, m), meta, params) -end - -## When called with a specific application in mind, call with two arguments -function feacalc(wavfile::AbstractString, application::Symbol; kwargs...) - if (application in [:speaker, :nbspeaker]) - feacalc(wavfile; defaults=:nbspeaker, kwargs...) - elseif application==:wbspeaker - feacalc(wavfile; defaults=:wbspeaker, kwargs...) - elseif (application==:language) - feacalc(wavfile; defaults=:rasta, nwarp=299, augtype=:sdc, kwargs...) - elseif (application==:diarization) - feacalc(wavfile; defaults=:rasta, sadtype=:none, normtype=:mvn, augtype=:none, kwargs...) - else - error("Unknown application ", application) - end -end - -function sad(pspec::Matrix{Float64}, sr::Float64, method=:energy; dynrange::Float64=30.) - deltaf = size(pspec,2) / (sr/2) - minfreqi = round(Int, 300deltaf) - maxfreqi = round(Int, 4000deltaf) - power = 10log10(sum(pspec[:,minfreqi:maxfreqi], 2)) - maxpow = maximum(power) - speech = findall(power .> maxpow - dynrange) -end - -## listen to SAD -function sad(wavfile::AbstractString, speechout::AbstractString, silout::AbstractString; dynrange::Float64=30.) - (x, sr, nbits) = wavread(wavfile) - sr = float64(sr) # more reasonable sr - x = vec(mean(x, dims=2)) # averave multiple channels for now - (m, pspec, meta) = mfcc(x, sr; preemph=0) - sp = sad(pspec, sr, dynrange=dynrange) - sl = round(Int, meta["steptime"] * sr) - xi = falses(size(x)) - for i in sp - xi[(i-1)*sl+(1:sl)] = true - end - y = x[findall(xi)] - wavwrite(y, speechout, Fs=sr, nbits=nbits, compression=WAVE_FORMAT_PCM) - y = x[findall(.!xi)] - wavwrite(y, silout, Fs=sr, nbits=nbits, compression=WAVE_FORMAT_PCM) -end - -## this should probably be called soxread... -function soxread(file) - nch = parse(Int, readall(`soxi -c $file`)) - sr = parse(i=Int, readall(`soxi -r $file`)) - sox = `sox $file -t raw -e signed -r $sr -b 16 -` - fd, proc = open(sox, "r") - x = Int16[] - while !eof(fd) - push!(x, read(fd, Int16)) - end - ns = length(x) ÷ nch - reshape(x, nch, ns)' / (1<<15), sr -end - -## similarly using sphere tools -function sphread(file) - nch = parse(Int, readstring(`h_read -n -F channel_count $file`)) - sr = parse(Int, readstring(`h_read -n -F sample_rate $file`)) - open(pipeline(`w_decode -o pcm $file -`, `h_strip - - `), "r") do fd - x = Int16[] - while !eof(fd) - push!(x, read(fd, Int16)) - end - ns = length(x) ÷ nch - return reshape(x, nch, ns)' / (1<<15), sr - end -end diff --git a/src/MFCC/io.jl b/src/MFCC/io.jl deleted file mode 100644 index 535b826..0000000 --- a/src/MFCC/io.jl +++ /dev/null @@ -1,93 +0,0 @@ -## io.jl -## (c) 2014 David A. van Leeuwen -## -## i/o functions for speech feature data. -## For compatibility reasons, we do not use JLD but encode everything in HDF5 types -## Is that a valid argument? I don't know -## -## Updated (trivally) 2022 Matthew C. Kelley - -import FileIO -import HDF5 -#import JLD - -## encode non-HDF5 types in the key by adding type indicator---a poorman's solution -HDF5.write(fd::HDF5.File, s::AbstractString, b::Bool) = write(fd, string(s,":Bool"), Int8(b)) -HDF5.write(fd::HDF5.File, s::AbstractString, sym::Symbol) = write(fd, string(s,":Symbol"), string(sym)) -HDF5.write(fd::HDF5.File, s::AbstractString, ss::SubString) = write(fd, s, ascii(ss)) - -## always save data in Float32 -## the functiona arguments are the same as the output of feacalc -## x: the MFCC data -## meta: a dict with parameters anout the data, nsamples, nframes, totnframes (before sad), ... -## params: a dict with parameters about the feature extraction itself. -function feasave(file::AbstractString, x::Matrix{T}; meta::Dict=Dict(), params::Dict=Dict()) where {T<:AbstractFloat} - dir = dirname(file) - if length(dir)>0 && !isdir(dir) - mkpath(dir) - end - fd = h5open(file, "w") - fd["features/data"] = map(Float32, x) - for (k,v) in meta - fd[string("features/meta/", k)] = v - end - for (k,v) in params - fd[string("features/params/", k)] = v - end - close(fd) -end - -## JLD version of the same -## FileIO.save(file::AbstractString, x::Matrix) - -## the reverse encoding of Julia types. -function retype(d::Dict) - r = Dict() - for (k,v) in d - if (m=match(r"^(.*):Bool$", k)) != nothing - r[m.captures[1]] = v>0 - elseif (m=match(r"(.*):Symbol", k)) != nothing - r[m.captures[1]] = symbol(v) - else - r[k] = v - end - end - r -end - -## Try to handle missing elements in the hdf5 file more gacefully -function h5check(obj, name, content) - content ∈ keys(obj) || error('"', name, '"', " does not contain ", '"', content, '"') - obj[content] -end - -## Currently we always read the data in float64 -function feaload(file::AbstractString; meta=false, params=false) - h5open(file, "r") do fd - f = h5check(fd, file, "features") - fea = map(Float64, read(h5check(f, "features", "data"))) - if length(fea)==0 # "no data" - m = read(h5check(f, "features", "meta")) - fea = zeros(0,m["nfea"]) - end - if ! (meta || params) - return fea - end - res = Any[fea] - if meta - push!(res, retype(read(h5check(f, "features", "meta")))) - end - if params - push!(res, retype(read(h5check(f, "features", "params")))) - end - tuple(res...) - end -end - -## helper function to quickly determine the size of a feature file -function feasize(file::AbstractString) - h5open(file, "r") do fd - f = h5check(fd, file, "features") - size(h5check(f, "features", "data")) - end -end diff --git a/src/MFCC/mfccs.jl b/src/MFCC/mfccs.jl deleted file mode 100644 index 1714642..0000000 --- a/src/MFCC/mfccs.jl +++ /dev/null @@ -1,184 +0,0 @@ -## mfccs.jl -## (c) 2013--2014 David A. van Leeuwen - -## Recoded from / inspired by melfcc from Dan Ellis's rastamat package. - -using SpecialFunctions -using Distributed -using DSP - -## This function accepts a vector of sample values, below we will generalize to arrays, -## i.e., multichannel data -## Recoded from rastamat's "melfcc.m" (c) Dan Ellis. -## Defaults here are HTK parameters, this is contrary to melfcc -function mfcc(x::Vector{T}, sr::Real=16000.0; wintime=0.025, steptime=0.01, numcep=13, - lifterexp=-22, sumpower=false, preemph=0.97, dither=false, minfreq=0.0, maxfreq=sr/2, - nbands=20, bwidth=1.0, dcttype=3, fbtype=:htkmel, - usecmp=false, modelorder=0) where {T<:AbstractFloat} - if (preemph != 0) - x = filt(PolynomialRatio([1., -preemph], [1.]), x) - end - pspec = powspec(x, sr, wintime=wintime, steptime=steptime, dither=dither) - aspec = audspec(pspec, sr, nfilts=nbands, fbtype=fbtype, minfreq=minfreq, maxfreq=maxfreq, sumpower=sumpower, bwidth=bwidth) - if usecmp - # PLP-like weighting/compression - aspec = postaud(aspec, maxfreq, fbtype) - end - if modelorder > 0 - if dcttype != 1 - error("Sorry, modelorder>0 and dcttype ≠ 1 is not implemented") - end - # LPC analysis - lpcas = dolpc(aspec, modelorder) - # cepstra - cepstra = lpc2cep(lpcas, numcep) - else - cepstra = spec2cep(aspec, numcep, dcttype) - end - cepstra = Array(lifter(cepstra, lifterexp)') - meta = Dict("sr" => sr, "wintime" => wintime, "steptime" => steptime, "numcep" => numcep, - "lifterexp" => lifterexp, "sumpower" => sumpower, "preemph" => preemph, - "dither" => dither, "minfreq" => minfreq, "maxfreq" => maxfreq, "nbands" => nbands, - "bwidth" => bwidth, "dcttype" => dcttype, "fbtype" => fbtype, - "usecmp" => usecmp, "modelorder" => modelorder) - return (cepstra, pspec', meta) -end - -mfcc(x::Array{T}, sr::Real=16000.0; args...) where {T<:AbstractFloat} = @distributed (tuple) for i=1:size(x)[2] mfcc(x[:,i], sr; args...) end - - -## default feature configurations, :rasta, :htk, :spkid_toolkit, :wbspeaker -## With optional extra agrs... you can specify more options -function mfcc(x::Vector{T}, sr::AbstractFloat, defaults::Symbol; args...) where {T<:AbstractFloat} - if defaults == :rasta - mfcc(x, sr; lifterexp=0.6, sumpower=true, nbands=40, dcttype=2, fbtype=:mel, args...) - elseif defaults ∈ [:spkid_toolkit, :nbspeaker] - mfcc(x, sr; lifterexp=0.6, sumpower=true, nbands=30, dcttype=2, fbtype=:mel, minfreq=130., maxfreq=3900., numcep=20, args...) - elseif defaults == :wbspeaker - mfcc(x, sr; lifterexp=0.6, sumpower=true, nbands=63, dcttype=2, fbtype=:mel, minfreq=62.5, maxfreq=7937.5, numcep=20, args...) - elseif defaults == :htk - mfcc(x, sr; args...) - else - error("Unknown set of defaults ", defaults) - end -end - -## our features run down with time, this is essential for the use of DSP.filt() -function deltas(x::Matrix{T}, w::Int=9) where {T<:AbstractFloat} - (nr, nc) = size(x) - if nr == 0 || w <= 1 - return x - end - hlen = floor(Int, w/2) - w = 2hlen + 1 # make w odd - win = collect(convert(T, hlen):-1:-hlen) - x1 = reshape(x[1, :], 1, size(x, 2)) ## julia v0.4 v0.5 changeover - xend = reshape(x[end,:], 1, size(x, 2)) - xx = vcat(repeat(x1, hlen, 1), x, repeat(xend, hlen, 1)) ## take care of boundaries - norm = 3 / (hlen * w * (hlen + 1)) - return norm * filt(PolynomialRatio(win, [1.]), xx)[2hlen .+ (1:nr), :] -end - - -import Base.Sort.sortperm -sortperm(a::Array, dim::Int) = mapslices(sortperm, a, dims=dim) - -erfinvtabs = Dict{Int,Vector{Float64}}() -function erfinvtab(wl::Int) - global erfinvtabs - if wl ∉ keys(erfinvtabs) - erfinvtabs[wl] = √2 * erfinv.(2collect(1:wl) / (wl + 1) .- 1) - end - return erfinvtabs[wl] -end - -function warpstats(x::Matrix{T}, w::Int=399) where {T<:Real} - nx, nfea = size(x) - wl = min(w, nx) - hw = (wl+1) / 2 - rank = similar(x, Int) - if nx < w - index = sortperm(x, 1) - for j in 1:nfea - rank[index[:,j], j] = collect(1:nx) - end - else - for j in 1:nfea # operations in outer loop over columns, better for memory cache - for i in 1:nx - s = max(1, i - round(Int, hw) + 1) - e = s + w - 1 - if e > nx - d = e - nx - e -= d - s -= d - end - r = 1 - for k in s:e - r += x[i, j] > x[k, j] - end - rank[i, j] = r - end - end - end - return rank, erfinvtab(wl) -end - -function warp(x::Matrix{T}, w::Int=399) where {T<:Real} - rank, erfinvtab = warpstats(x, w) - return erfinvtab[rank] -end -warp(x::Vector{T}, w::Int=399) where {T<:Real} = warp(x'', w) - -function WarpedArray(x::Matrix, w::Int) - rank, erfinvtab = warpstats(x, w) - WarpedArray(rank, erfinvtab) -end - -## mean and variance normalization -znorm(x::Array, dim::Int=1) = znorm!(copy(x), dim) -znorm!(x::Array, dim::Int=1) = broadcast!(/, x, broadcast!(-, x, x, mean(x, dims=dim)), std(x, dims=dim)) - -## short-term mean and variance normalization -function stmvn(x::Vector, w::Int=399) - y = similar(x) - hw = w ÷ 2 ## effectively makes `w` odd... - nx = length(x) - nx ≤ 1 && return x - ## initialize sum x and sum x^2 - sx = (hw + 1) * x[1] - sxx = (hw + 1) * x[1] * x[1] - for i in 2:min(nx, hw + 1) - sx += x[i] - sxx += x[i] * x[i] - end - if hw + 1 > nx - sx += (hw + 1 - nx) * x[nx] - sxx += (hw + 1 - nx) * x[nx] * x[nx] - end - for i in 1:nx - μ = sx / w - σ = sqrt((sxx - μ * sx) / (w - 1)) - y[i] = (x[i] - μ) / σ - mi = max(i - hw, 1) - ma = min(i + hw + 1, nx) - sx += x[ma] - x[mi] - sxx += x[ma] * x[ma] - x[mi] * x[mi] - end - return y -end - -stmvn(m::Matrix, w::Int=399, dim::Int=1) = mapslices(x->stmvn(x, w), m, dims=dim) - -## Shifted Delta Coefficients by copying -function sdc(x::Matrix{T}, n::Int=7, d::Int=1, p::Int=3, k::Int=7) where {T<:AbstractFloat} - nx, nfea = size(x) - n ≤ nfea || error("Not enough features for n") - hnfill = (k-1) * p / 2 - nfill1, nfill2 = floor(Int, hnfill), ceil(Int, hnfill) - xx = vcat(zeros(eltype(x), nfill1, n), deltas(x[:,1:n], 2d+1), zeros(eltype(x), nfill2, n)) - y = zeros(eltype(x), nx, n*k) - for (dt, offset) in zip(0:p:p*k-1, 0:n:n*k-1) - y[:, offset+(1:n)] = xx[dt+(1:nx), :] - end - return y -end diff --git a/src/MFCC/nomodule.jl b/src/MFCC/nomodule.jl deleted file mode 100644 index 76e7669..0000000 --- a/src/MFCC/nomodule.jl +++ /dev/null @@ -1,14 +0,0 @@ -## for development - -using DSP -using HDF5 - -if !isdefined(:WarpedArray) - include("types.jl") -end - -include("rasta.jl") -include("mfccs.jl") -include("warpedarray.jl") -include("feacalc.jl") -include("io.jl") diff --git a/src/MFCC/rasta.jl b/src/MFCC/rasta.jl deleted file mode 100644 index f77494c..0000000 --- a/src/MFCC/rasta.jl +++ /dev/null @@ -1,330 +0,0 @@ -## (c) 2013--2014 David A. van Leeuwen, (c) 2005--2012, Dan Ellis - -## Freely adapted from Dan Ellis's rastamat package. -## We've kept routine names the same, but the interface has changed a bit. - -## we haven't implemented rasta filtering, yet, in fact. These routines are a minimum for -## encoding HTK-style mfccs - -# powspec tested against octave with simple vectors - -using DSP -using FFTW -using LinearAlgebra - -function powspec(x::Vector{T}, sr::Real=8000.0; wintime=0.025, steptime=0.01, dither=true) where {T<:AbstractFloat} - nwin = round(Integer, wintime * sr) - nstep = round(Integer, steptime * sr) - - nfft = 2 .^ Integer((ceil(log2(nwin)))) - window = hamming(nwin) # overrule default in specgram which is hanning in Octave - noverlap = nwin - nstep - - y = spectrogram(x .* (1<<15), nwin, noverlap, nfft=nfft, fs=sr, window=window, onesided=true).power - ## for compability with previous specgram method, remove the last frequency and scale - y = y[1:end-1, :] ## * sumabs2(window) * sr / 2 - y .+= dither * nwin / (sum(abs2, window) * sr / 2) ## OK with julia 0.5, 0.6 interpretation as broadcast! - - return y -end - -# audspec tested against octave with simple vectors for all fbtypes -function audspec(x::Matrix{T}, sr::Real=16000.0; nfilts=ceil(Int, hz2bark(sr/2)), fbtype=:bark, - minfreq=0., maxfreq=sr/2, sumpower=true, bwidth=1.0) where {T<:AbstractFloat} - nfreqs, nframes = size(x) - nfft = 2(nfreqs-1) - if fbtype == :bark - wts = fft2barkmx(nfft, nfilts, sr=sr, width=bwidth, minfreq=minfreq, maxfreq=maxfreq) - elseif fbtype == :mel - wts = fft2melmx(nfft, nfilts, sr=sr, width=bwidth, minfreq=minfreq, maxfreq=maxfreq) - elseif fbtype == :htkmel - wts = fft2melmx(nfft, nfilts, sr=sr, width=bwidth, minfreq=minfreq, maxfreq=maxfreq, - htkmel=true, constamp=true) - elseif fbtype == :fcmel - wts = fft2melmx(nfft, nfilts, sr=sr, width=bwidth, minfreq=minfreq, maxfreq=maxfreq, - htkmel=true, constamp=false) - else - error("Unknown filterbank type ", fbtype) - end - wts = wts[:, 1:nfreqs] - if sumpower - return wts * x - else - return (wts * sqrt.(x)).^2 - end -end - -function fft2barkmx(nfft::Int, nfilts::Int; sr=8000.0, width=1.0, minfreq=0., maxfreq=sr/2) - hnfft = nfft >> 1 - minbark = hz2bark(minfreq) - nyqbark = hz2bark(maxfreq) - minbark - wts=zeros(nfilts, nfft) - stepbark = nyqbark/(nfilts-1) - binbarks = hz2bark.((0:hnfft) * sr / nfft) - for i in 1:nfilts - midbark = minbark + (i-1) * stepbark - lof = (binbarks .- midbark) / width .- 0.5 - hif = (binbarks .- midbark) / width .+ 0.5 - logwts = min.(0, hif, -2.5lof) - wts[i, 1:1+hnfft] = 10.0.^logwts - end - return wts -end - -## Hynek's formula -hz2bark(f) = 6asinh(f / 600) -bark2hz(bark) = 600 * sinh(bark / 6) - -function fft2melmx(nfft::Int, nfilts::Int; sr=8000.0, width=1.0, minfreq=0.0, maxfreq=sr/2, htkmel=false, constamp=false) - wts = zeros(nfilts, nfft) - # Center freqs of each DFT bin - fftfreqs = collect(0:nfft-1) / nfft * sr; - # 'Center freqs' of mel bands - uniformly spaced between limits - minmel = hz2mel(minfreq, htkmel); - maxmel = hz2mel(maxfreq, htkmel); - binfreqs = mel2hz(minmel .+ collect(0:(nfilts+1)) / (nfilts + 1) * (maxmel - minmel), htkmel); -## binbin = iround(binfrqs/sr*(nfft-1)); - - for i in 1:nfilts - fs = binfreqs[i .+ (0:2)] - # scale by width - fs = fs[2] .+ (fs .- fs[2])width - # lower and upper slopes for all bins - loslope = (fftfreqs .- fs[1]) / (fs[2] - fs[1]) - hislope = (fs[3] .- fftfreqs) / (fs[3] - fs[2]) - # then intersect them with each other and zero - wts[i,:] = max.(0, min.(loslope, hislope)) - end - - if !constamp - ## unclear what this does... - ## Slaney-style mel is scaled to be approx constant E per channel - wts = broadcast(*, 2 ./ ((binfreqs[3:nfilts+2]) - binfreqs[1:nfilts]), wts) - end - # Make sure 2nd half of DFT is zero - wts[:, (nfft>>1)+1:nfft] .= 0. - return wts -end - -function hz2mel(f::Vector{T}, htk=false) where {T<:AbstractFloat} - if htk - return 2595 .* log10.(1 .+ f / 700) - else - f0 = 0.0 - fsp = 200/3 - brkfrq = 1000.0 - brkpt = (brkfrq - f0) / fsp - logstep = exp(log(6.4) / 27) - linpts = f .< brkfrq - z = zeros(size(f)) # prevent InexactError() by making these Float64 - z[findall(linpts)] = f[findall(linpts)]/brkfrq ./ log(logstep) - z[findall(.!linpts)] = brkpt .+ log.(f[findall(.!linpts)] / brkfrq) ./ log(logstep) - end - return z -end -hz2mel(f::AbstractFloat, htk=false) = hz2mel([f], htk)[1] - -function mel2hz(z::Vector{T}, htk=false) where {T<:AbstractFloat} - if htk - f = 700 .* (10 .^ (z ./ 2595) .- 1) - else - f0 = 0.0 - fsp = 200/3 - brkfrq = 1000.0 - brkpt = (brkfrq - f0) / fsp - logstep = exp(log(6.4) / 27) - linpts = z .< brkpt - f = similar(z) - f[linpts] = f0 .+ fsp * z[linpts] - f[.!linpts] = brkfrq .* exp.(log.(logstep) * (z[.!linpts] .- brkpt)) - end - return f -end - -function postaud(x::Matrix{T}, fmax::Real, fbtype=:bark, broaden=false) where {T<:AbstractFloat} - (nbands,nframes) = size(x) - nfpts = nbands + 2broaden - if fbtype == :bark - bandcfhz = bark2hz.(range(0, hz2bark(fmax), length=nfpts)) - elseif fbtype == :mel - bandcfhz = mel2hz(range(0, hz2mel(fmax), length=nfpts)) - elseif fbtype == :htkmel || fbtype == :fcmel - bandcfhz = mel2hz(range(0, hz2mel(fmax,1), length=nfpts),1); - else - error("Unknown filterbank type") - end - # Remove extremal bands (the ones that will be duplicated) - bandcfhz = bandcfhz[1+broaden:nfpts-broaden]; - # Hynek's magic equal-loudness-curve formula - fsq = bandcfhz.^2 - ftmp = fsq + 1.6e5 - eql = ((fsq ./ ftmp).^2) .* ((fsq + 1.44e6) ./ (fsq + 9.61e6)) - # weight the critical bands - z = broadcast(*, eql, x) - # cube root compress - z .^= 0.33 - # replicate first and last band (because they are unreliable as calculated) - if broaden - z = z[[1, 1:nbands, nbands], :]; - else - z = z[[2, 2:(nbands-1), nbands-1], :] - end - return z -end - -function dolpc(x::Array{T}, modelorder::Int=8) where {T<:AbstractFloat} - nbands, nframes = size(x) - r = real(ifft(vcat(x, x[collect(nbands-1:-1:2), :]), 1)[1:nbands, :]) - # Find LPC coeffs by durbin - y, e = levinson(r, modelorder) - # Normalize each poly by gain - y ./= e -end - -function lpc2cep(a::Array{T}, ncep::Int=0) where {T<:AbstractFloat} - nlpc, nc = size(a) - order = nlpc - 1 - if ncep == 0 - ncep = nlpc - end - c = zeros(ncep, nc) - # Code copied from HSigP.c: LPC2Cepstrum - # First cep is log(Error) from Durbin - c[1,:] = -log.(a[1, :]) - # Renormalize lpc A coeffs - a ./= a[1, :] - for n in 2:ncep - sum = zero(T) - for m in 2:n - sum += (n - m) * a[m, :] .* c[n - m + 1, :] - end - c[n, :] = -a[n, :] - sum / (n - 1) - end - return c -end - -function spec2cep(spec::Array{T}, ncep::Int=13, dcttype::Int=2) where {T<:AbstractFloat} - # no discrete cosine transform option - dcttype == -1 && return log(spec) - - (nr, nc) = size(spec) - dctm = zeros(typeof(spec[1]), ncep, nr) - if 1 < dcttype < 4 # type 2,3 - for i in 1:ncep - dctm[i, :] = cos.((i - 1) * collect(1:2:2nr-1)π / (2nr)) * √(2/nr) - end - if dcttype == 2 - dctm[1, :] /= √2 - end - elseif dcttype == 4 # type 4 - for i in 1:ncep - dctm[i, :] = 2cos.((i-1) * collect(1:nr)π/(nr+1)) - dctm[i, 1] += 1 - dctm[i, nr] += (-1)^(i-1) - end - dctm /= 2(nr + 1) - else # type 1 - for i in 1:ncep - dctm[i, :] = cos.((i-1) * collect(0:nr-1)π / (nr - 1)) / (nr - 1) - end - dctm[:, [1, nr]] /= 2 - end - return dctm * log.(spec) -end - -function lifter(x::Array{T}, lift::Real=0.6, invs=false) where {T<:AbstractFloat} - (ncep, nf) = size(x) - if lift == 0 - return x - end - if lift > 0 - if lift > 10 - error("Too high lift number") - end - liftw = [1; collect(1:ncep-1).^lift] - else - # Hack to support HTK liftering - if !isa(lift, Integer) - error("Negative lift must be interger") - end - lift = -lift # strictly speaking unnecessary... - liftw = vcat(1, (1 .+ lift/2 * sin.(collect(1:ncep-1)π / lift))) - end - if invs - liftw = 1 ./ liftw - end - y = broadcast(*, x, liftw) - return y -end - -## Freely after octave's implementation, by Paul Kienzle -## Permission granted to usee this in a MIT license on 20 dec 2013 by the author Paul Kienzle: -## "You are welcome to move my octave code from GPL to MIT like core Julia." -## untested -## only returns a, v -function levinson(acf::Vector{T}, p::Int) where {T<:Real} - if length(acf) < 1 - error("empty autocorrelation function") - end - if p < 0 - error("negative model order") - end - if p < 100 - ## direct solution [O(p^3), but no loops so slightly faster for small p] - ## Kay & Marple Eqn (2.39) - R = toeplitz(acf[1:p], conj(acf[1:p])) - a = R \ -acf[2:p+1] - pushfirst!(a, 1) - v = real(a.*conj(acf[1:p+1])) - else - ## durbin-levinson [O(p^2), so significantly faster for large p] - ## Kay & Marple Eqns (2.42-2.46) - ref = zeros(p) - g = -acf[2] / acf[1] - a = [g] - v = real((1 - abs2(g)) * acf[1]) - ref[1] = g - for t=2:p - g = -(acf[t+1] + a ⋅ acf[t:-1:2]) / v - a = [a + g * conj(a[t-1:-1:1]), g] - v *= 1 - abs2(g) - ref[t] = g - end - pushfirst!(a, 1) - end - return (a, v) -end - -function levinson(acf::Array{T}, p::Int) where {T<:Real} - (nr,nc) = size(acf) - a = zeros(p + 1, nc) - v = zeros(p + 1, nc) - for i in 1:nc - a[:,i], v[:,i] = levinson(acf[:,i], p) - end - return (a, v) -end - -## Freely after octave's implementation, ver 3.2.4, by jwe && jh -## skipped sparse implementation -function toeplitz(c::Vector{T}, r::Vector{T}=c) where {T<:Real} - nc = length(r) - nr = length(c) - res = zeros(typeof(c[1]), nr, nc) - if nc == 0 || nr == 0 - return res - end - if r[1] != c[1] - ## warn - end - if typeof(c) <: Complex - conj!(c) - c[1] = conj(c[1]) # bug in julia? - end - ## if issparse(c) && ispsparse(r) - data = [r[end:-1:2], c] - for (i, start) in zip(1:nc, nc:-1:1) - res[:,i] = data[start:start+nr-1] - end - return res -end diff --git a/src/Phonetics.jl b/src/Phonetics.jl index 82e56a1..8b3a59e 100644 --- a/src/Phonetics.jl +++ b/src/Phonetics.jl @@ -1,7 +1,5 @@ module Phonetics -include("MFCC/MFCC.jl") - include("sound.jl") export Sound diff --git a/src/acdist.jl b/src/acdist.jl index 93cb2eb..9c2e1b1 100644 --- a/src/acdist.jl +++ b/src/acdist.jl @@ -1,5 +1,5 @@ using DynamicAxisWarping -using Phonetics.MFCC: mfcc +using MFCC: mfcc using Distances using DataFrames using Statistics diff --git a/test/MFCC/LICENSE b/test/MFCC/LICENSE deleted file mode 100644 index b19bab2..0000000 --- a/test/MFCC/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2013--2014 David A. van Leeuwen, (c) 2005--2012, Dan Ellis -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the -following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this list of conditions and -the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and -the following disclaimer in the documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - diff --git a/test/MFCC/bl2.mfcc b/test/MFCC/bl2.mfcc deleted file mode 100644 index cef7d6146fcab2a967edd9fe48be0bcd49c79598..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19072 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

?z8U>*n-o& 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�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 KD+Vp&ivI%`7O?jK diff --git a/test/MFCC/runtests.jl b/test/MFCC/runtests.jl deleted file mode 100644 index e73ea34..0000000 --- a/test/MFCC/runtests.jl +++ /dev/null @@ -1,27 +0,0 @@ -## runtests.jl Unit tests for MFCC -## (c) 2015 David A. van Leeuwen -## -## Licensed under the MIT software license, see LICENSE.md in MFCC module -## -## Updated (trivially) 2022 by Matthew C. Kelley - -using WAV -using SpecialFunctions -using Statistics - -base, _ = splitdir(@__FILE__) -x, meta, params = feacalc(joinpath(base, "bl2.wav"), normtype=:none, method=:wav, augtype=:none, sadtype=:none) -y = feaload(joinpath(base, "bl2.mfcc")) - -@assert x == y - -z = warp(x) -z = deltas(x) -z = znorm(x) -z = stmvn(x) - -x = randn(100000) -p = powspec(x) -a = audspec(p) - -println("Tests passed") diff --git a/test/runtests.jl b/test/runtests.jl index 2cbe37a..cb50a21 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,5 +1,5 @@ using Phonetics -using Phonetics.MFCC +using MFCC using Test using DelimitedFiles using StatsBase @@ -324,8 +324,3 @@ end res = sort(join.(res, " ")) @test res == ["B AE1 T", "K AE1 T"] end - -@testset "MFCC" begin - - include("MFCC/runtests.jl") -end From df6fbd4d555260aa136612be9423c2a76e2364d2 Mon Sep 17 00:00:00 2001 From: "Matthew C. Kelley" Date: Sat, 19 Nov 2022 15:33:34 -0800 Subject: [PATCH 2/2] Add compat for MFCC --- Project.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Project.toml b/Project.toml index d783dc5..7092291 100644 --- a/Project.toml +++ b/Project.toml @@ -47,6 +47,7 @@ QHull = "0.2" SpecialFunctions = "2.1" StatsBase = "0.33" WAV = "1.2" +MFCC = "0.3.3" julia = "1.6 - 1.8" [extras]