Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LPC burg: ar_burg() interface - returns reflection coeffs - same as … #171

Closed
wants to merge 4 commits into from

Conversation

oyd11
Copy link

@oyd11 oyd11 commented Aug 1, 2017

…matlab call as well, lpc() - call - returns 2 params - same as Levinson version

…matlab call as well, lpc() - call - returns 2 params - same as Levinson version
@oyd11
Copy link
Author

oyd11 commented Aug 1, 2017

Hi, I wrote the function @staticfloat integrated here before (see: #156 ) - this is great, but to be able to use this version in my own code - I also need the Reflection-Coefficients as a return value (they can be re-evaluated - but there's a numerical stability cost)
I've wrapped the lpc() call in a unified interface - just like Static did, but provided a 'ar_burg()' function call with the specific Burg algorithm which includes the Reflection-Coefficients as a side effect. This is the same as the Matlab "arburg()" call [ https://www.mathworks.com/help/signal/ref/arburg.html ], feel free to remove the extra dash (now that I see that Matlab doesn't have that.

@oyd11
Copy link
Author

oyd11 commented Aug 1, 2017

note: the non passing CI test seems to be due to some non-related incompatibility issue with Julia nightly (0.7 line) - something about some functions to have moved out of base into DSP

Copy link
Contributor

@staticfloat staticfloat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me!

src/lpc.jl Outdated

# Dispatch types for lpc()
mutable struct LPCBurg; end
mutable struct LPCLevinson; end

"""
`lpc_burg(x::AbstractVector, p::Int)`
`ar_burg(x::AbstractVector, p::Int)`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be arburg() not ar_burg()

@@ -59,7 +66,7 @@ function implements the mathematics described in [1].
"""
function lpc{T <: Number}(x::AbstractVector{T}, p::Int, ::LPCLevinson)
R_xx = xcorr(x,x)[length(x):end]
a = zeros(p,p)
a = zeros(T,p,p)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've tested the versions for type stability - the Burg versions works with Float(16/32/64)/BigFloat - where as the Levinson version works only with Float(32/64) - because of conv() doing an FFT (which is alright for now I guess).
Anyhow - the Levinson version can also have the reflection coeffs returns eventually.
Test is cool, I'll try to add a Ladder(Lattice) filter - where the reflection coeffs are used, and that can also be added to the test

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this accurate for integer T?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would try to add a test with a Fixed-Point implementation ( like https://github.com/JuliaMath/FixedPointNumbers.jl ) the accepted base time might have to be "Real" , "Integer" as is - should probably be excluded, but stability of Rational + FixedPoint might be nice to have. A 'trait' of "invertible" (or 'semi-field' or anything similar ) might be required.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I wasn't even thinking about fixed point arithmetic. That would be cool.

My point with these comments is that the current PR will error if x is an abstract vector with Integer elements, because of the type assertions and container types used in the code. I think you should either change the type assertions and container types to reflect the actual types, or restrict the type bounds in the method definitions to types that will work as you expect (e.g. AbstractFloat).

Because restricting the type bounds will change the API for this function, I think it would be best to be more careful about the container types. If T = eltype(x) and T <: AbstractFloat or T <: FixedPoint then prediciton_error, reflection_coeffs, and a will be type T (or have eltype T). If T <: Integer then prediction_error and reflection_coeffs will be type Float64, and the Levinson algorithm will error because xcorr errors with integer inputs.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed-Point is quite common for LPC implementations, it's an import use-case as LPC is used in some analysis and compression algorithms in some embedded systems with Integer-Only hardware (still I believe); the few integer LPC's I've seen had the Fixed-Point arithmetics inlined by hand (for example in Speex), but this could actually be an interesting use case to see whether we can produce efficient machine code with an abstract type here (might change the abstraction for that). Anyhow, I think I've even tested this with Rational before, it's quite cool that it works.

src/lpc.jl Outdated
# Initialize prediction error wtih the variance of the signal
prediction_err = (sum(abs2, x) ./ length(x))[1]
prediction_err :: T = sum(abs2, x) ./ length(x)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/ instead of ./? Or is there some reason for the broadcasting I'm not aware of?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, change it to / if you see fit.
This was not changed in the current commit, I probably wrote it as to be explicit about doing a scalar operation (rather than a broadcast)

# Initialize prediction error wtih the variance of the signal
prediction_err = (sum(abs2, x) ./ length(x))[1]
prediction_err :: T = sum(abs2, x) / length(x)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is prediction_err always type T? What if T is an integer? It may be good to change the tests to include integer data.

# Initialize prediction error wtih the variance of the signal
prediction_err = (sum(abs2, x) ./ length(x))[1]
prediction_err :: T = sum(abs2, x) / length(x)
reflection_coeffs = zeros(T, p)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If x is a vector of integers, then it seems like reflections_coeffs would not also be integers, would they? I'm not sure if T is the right type of reflection_coeffs.

end

function lpc{T <: Number}(x::AbstractVector{T}, p::Int, ::LPCBurg)
a, prediction_err, _ = arburg(x, p)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added _ to take care of the reflection_coeffs return value here. Is that ok?

@@ -59,7 +66,7 @@ function implements the mathematics described in [1].
"""
function lpc{T <: Number}(x::AbstractVector{T}, p::Int, ::LPCLevinson)
R_xx = xcorr(x,x)[length(x):end]
a = zeros(p,p)
a = zeros(T,p,p)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this accurate for integer T?

@wheeheee
Copy link
Contributor

wheeheee commented Feb 8, 2024

Superseded by #517, although more tests e.g. for FixedPoint types could be added.

@wheeheee wheeheee closed this Feb 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants