it is a long time ago i asked a similar question but the question is now closed. So I will ask again.
Is there any way to export all human-readable parameters out of sigma studio, like frequency, q, ripple and so on?
We are working on several projects where a microcontroller controls the DSP (ADAU1452). The user can change filter-frequency and a lot of different parameters or load whole presets. A very common use case. This means that we have to store all parameters inside the MCU to calculate the coefficiants. At the moment we have to copy all values from sigmastudio into our code by hand, which is a lot of work and not failure safe. Also when you think of whole presets. When we pepare a new preset in sigmastudio we have to copy everything again by hand.
It would be great if there is a way to get on these vaules instead of only the coefficiants.
Best regards and thanks in advance,
One solution would be to read the coefficients from the DSP and reverse-engineer the filter settings based on those. In general it's not too hard to run the algorithms in reverse. The main challenge is determining the filter type, especially since no filter type might hold exactly anymore after rounding of the cofficients.
For example, here's a python script that converts between close-to-"end-user" parameters and DSP coefficients for the subset of second-order filters that are "invertible" (peaking EQ, low shelf, and high shelf):
from math import pi, cos, sin, log10, floor, atan2, sqrt
tau = 2 * pi
def round( x ):
return floor( x + 0.5 )
# note: these two linear transforms are not exact inverses, their composition
# multiplies all coefficients by 4, but we renormalize anyway so that's no prob
def transform( gL, gC, gH ):
g0 = gL + 2*gC + gH
g1 = 2*gL - 2*gH
g2 = gL - 2*gC + gH
return ( g0, g1, g2 )
def itransform( g0, g1, g2 ):
gL = g0 + g1 + g2
gC = g0 - g2
gH = g0 - g1 + g2
return ( gL, gC, gH )
fS = 48000
def bq_to_dsp( f, Q, bL, bC, bH, aL=1, aC=1, aH=1 ):
assert f > 0
assert f < fS/2
assert Q > 0
f = f / fS * tau
x = cos( f )
y = sin( f )
ζ = 0.5 / Q
bL = ( 1 - x ) * bL; aL = ( 1 - x ) * aL;
bC = ( ζ * y ) * bC; aC = ( ζ * y ) * aC;
bH = ( 1 + x ) * bH; aH = ( 1 + x ) * aH;
( b0, b1, b2 ) = transform( bL, bC, bH )
( a0, a1, a2 ) = transform( aL, aC, aH )
b2 /= a0; a2 /= a0;
b1 /= a0; a1 /= a0;
b0 /= a0; a0 = 1;
return [ round( x * 2**24 ) for x in ( b2, b1, b0, -a2, -a1 ) ]
def ibq_to_dsp( f, Q, gL, gC, gH ):
# convert dB to sqrt of linear gain
bL = 10**( gL / 40 )
bC = 10**( gC / 40 )
bH = 10**( gH / 40 )
return bq_to_dsp( f, Q, bL, bC, bH, 1/bL, 1/bC, 1/bH )
def dsp_to_ibq( coeffs ):
( b2, b1, b0, a2, a1 ) = ( x / 2**24 for x in coeffs )
a0 = 1; a1 = -a1; a2 = -a2;
( bL, bC, bH ) = itransform( b0, b1, b2 )
( aL, aC, aH ) = itransform( a0, a1, a2 )
dL = sqrt( bL * aL )
dC = sqrt( bC * aC )
dH = sqrt( bH * aH )
x = ( dH - dL ) / ( dH + dL )
y = sqrt( 1 - x**2 )
f = atan2( y, x ) / tau * fS
Q = ( dH + dL ) * y / dC / 4
gL = log10( bL / aL ) * 20
gC = log10( bC / aC ) * 20
gH = log10( bH / aH ) * 20
return ( f, Q, gL, gC, gH )
f = 1500; Q = sqrt(2); gL = 0; gC = 4; gH = 0;
( fx, Qx, gLx, gCx, gHx ) = dsp_to_ibq( ibq_to_dsp( f, Q, gL, gC, gH ) )
print( "f = %7.1f -> %7.1f" % ( f, fx ) )
print( "Q = %7.3f -> %7.3f" % ( Q, Qx ) )
print( "gL = %+7.1f -> %+7.1f" % ( gL, gLx ) )
print( "gC = %+7.1f -> %+7.1f" % ( gC, gCx ) )
print( "gH = %+7.1f -> %+7.1f" % ( gH, gHx ) )
The parameters gL, gC, and gH here require some explanation: for each "standard" type of invertible second-order filter these are subject to two linear constraints:
However, after rounding the DSP coefficients, none of these might hold anymore. You'd need to find the best fit for the type-selection and the remaining parameter, and the result might not exactly match the original values (although I'd be surprised if the result dsp coefficients differ from the original ones by more than 1). In practice, with 24 fractional bits of precisioin, this problem is likely to be quite minor.
To make this complete, you'd also need to add detection of various other types. Many of them are in theory quite easy to detect, especially using (bL, bC, bH) as produced by itransform():
But again, these constraints might not hold exactly anymore after rounding.
Thanks Matthijs! Good solution since SigmaStudio doesn't offer the export feature that Eric is looking for. So his query amounts to a feature request.
Eric -- sorry I didn't understand your needs at first. Where I work, once completing my Sigma program I make a text file for the uC programming engineer with all the parameters and addresses he needs to put in his C code. This is because he sits 20 feet from me -- and having done a little C coding myself (forgetting numerous semicolons), there's no way I would dump a .dspproj file on him to open & chase the stuff on his own. "Real" programming is tough enough to begin with.
thanks a lot for your detailed answer. This script is very nice and I will definetly keep it. I think this can be very helpful in the future. But as you mentioned the filter-type and rounding can be a problem. It is very funny because I also played around with the inversion of filter-functions some days ago. Again thanks a lot.
okay I understand. We will do it first in the way you described. But of course automation would be faster and more save. Regarding the feature-request, can you tell me where I can add this function as a feature request?
It turns out that there is an official place for SigmaStudio feature requests:
And some of the previous items there have been implemented in present versions of SigmaStudio -- so there's hope that your idea won't go down the bit bucket.
For bugs, report them with a post in EZ, following the format described in this post:
thanks a lot for your reply. Mabye I am too stupid :), but how can I post into the wishlist. I can see the page and there is indicated how a request should look like. But I dont know how to post there? Can explain me how this works?