SigmaStudio export human-readable values

Dear EngineerZone,

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, 

Eric

Parents
  • 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):

    #!/usr/bin/python3
    
    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:

    • peaking EQ:  gL=0,  gH=0,  gC is the gain of the peak
    • low shelf:  gH=0,  gC=gL/2,  gL is the gain of the shelf
    • high shelf:  gL=0,  gC=gH/2,  gH is the gain of the shelf

    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():

    • high-pass:  b0+b1+b2 == 0  (i.e. bL == 0)
    • low-pass:  b0-b1+b2 == 0  (i.e. bH == 0)
    • notch: b0-b2 == 0  (i.e. bC == 0)

    But again, these constraints might not hold exactly anymore after rounding.

  • 0
    •  Super User 
    on Jul 29, 2019 11:56 PM over 1 year ago in reply to matthijs

         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.

  • HI Bob, 

    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? 

Reply Children