B4J Question Convert JS to B4J Math

techknight

Well-Known Member
Licensed User
Longtime User
I am writing a program to control VolumIO based off another members work here on a Raspberry Pi.

Difference is, I am hooking an IS31AP2111 Power Amplifier IC into the Pi. it has its own I2S receiver that is compatible with all 3 protocols. Still not sure about the Master Clock yet.

anyways, it has a built in parametric EQ that is setup with biquad coefficients. I found some Javascript code that will generate the coefficients, but I am not sure how to convert the math into something that B4X can handle.

Here is the code for JS: (only posting code relevant to what I want to do:

B4X:
function calcBiquad(type, Fc, Fs, Q, peakGain, plotType) {
    var a0,a1,a2,b1,b2,norm;
    var ymin, ymax, minVal, maxVal;
   
    var V = Math.pow(10, Math.abs(peakGain) / 20);
    var K = Math.tan(Math.PI * Fc / Fs);
    switch (type) {
        case "peak":
            if (peakGain >= 0) {
                norm = 1 / (1 + 1/Q * K + K * K);
                a0 = (1 + V/Q * K + K * K) * norm;
                a1 = 2 * (K * K - 1) * norm;
                a2 = (1 - V/Q * K + K * K) * norm;
                b1 = a1;
                b2 = (1 - 1/Q * K + K * K) * norm;
            }
            else {   
                norm = 1 / (1 + V/Q * K + K * K);
                a0 = (1 + 1/Q * K + K * K) * norm;
                a1 = 2 * (K * K - 1) * norm;
                a2 = (1 - 1/Q * K + K * K) * norm;
                b1 = a1;
                b2 = (1 - V/Q * K + K * K) * norm;
            }
            break;
    }

    // list coefficients
    var coefsList = "a0 = " + a0 + "\n";
    coefsList += "a1 = " + a1 + "\n";
    coefsList += "a2 = " + a2 + "\n";
    coefsList += "b1 = " + b1 + "\n";
    coefsList += "b2 = " + b2;
    var taNode = document.getElementById("biquad_coefsList");
    // remove existing child txt node
    while (taNode.firstChild)
      taNode.removeChild(taNode.firstChild);
    var listNode = document.createTextNode(coefsList);
    taNode.appendChild(listNode);
}

The code conversion seems streight forward for the Select case statement becuase it is almost a copy and paste. Problem is the value for K and value for V is a Math.Pow and Math.Tan which I have no idea what that does or how to convert to b4X.

any ideas?
 

Daestrum

Expert
Licensed User
Longtime User
You can just put that code into the Nashorn engine and get the results from it (needs jInvokeNashorn library)
eg: ( I changed the code slightly to make it run)
B4X:
ub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Dim nash As jInvokeNashorn
    Dim script As String
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    'MainForm.RootPane.LoadLayout("Layout1") 'Load the layout file.
    MainForm.Show
    script =$"
function calcBiquad(type, Fc, Fs, Q, peakGain, plotType) {
    var a0,a1,a2,b1,b2,norm
    var ymin, ymax, minVal, maxVal
 
    var V = Math.pow(10, Math.abs(peakGain) / 20)
    var K = Math.tan(Math.PI * Fc / Fs)
    if (peakGain >= 0) {
        norm = 1 / (1 + 1/Q * K + K * K)
        a0 = (1 + V/Q * K + K * K) * norm
        a1 = 2 * (K * K - 1) * norm
        a2 = (1 - V/Q * K + K * K) * norm
        b1 = a1;
        b2 = (1 - 1/Q * K + K * K) * norm
    }
    // create an arraylist to return the results
    var List = Java.type("java.util.ArrayList")
    var res = new List()
    res.addAll([norm,a0,a1,a2,b1,b2])
    return res
}
"$
    nash.InitInvocable(script)
    ' returns norm,a0,a1,a2,b1,b2 in an array
    Log(nash.Invoke("calcBiquad",Array("peak",20,50,7,2,5))) ' no idea what figures should be here lol
 
End Sub
 
Upvote 0

techknight

Well-Known Member
Licensed User
Longtime User
Awesome. Thanks for the help guys.

This one is a hobby project, I am building a "RetroModernPi" media player. Retro because it has vacuum fluorescent displays, and its inside an old 80s/90s style enclosure, but modern because its running a Pi with VolumIO and other stuffs.

I know volumeio contains its own web configuration interface, but since its going to have alot of custom stuff in it on top of it, I will probably run ABMaterial along-side to control the on-board power amplifier. it is I2C based control, with parametric EQ, error reporting, gain, bass/treble boost, etc..

I still have to spin a PCB that contains the DAC as well as buffers to go into the power amp, line level output, and then the VU meter. Plus all the different DC-DC converters needed for the support circuitry like 5V for the Pi, +/-12V for the op-amp stages, and then 24V for the Power amp and VFD displays. I will probably feed it with 24V and get the rest of the other voltages from DC-dC circuits. Plus the inverter circuit for the Filament on the VFD display as well.

I was going to use the I2S engine built into the power amplifier IC, but decided against that because I cannot get line-level out from it. So I went with a cirrus chip which is supported by the Pi, as well as its matching ADC to go into the power amp.
 
Upvote 0

techknight

Well-Known Member
Licensed User
Longtime User
Last thing I need to do on this project is figure out how to manage the Pi shutdown. I want to potentially add a standby microcontroller into the mix, and when the linux kernel gets to the point of "shutdown", have it toggle or set a GPIO pin that my microcontroller senses, and then cuts the 5V supply to the Pi. Press the power button on the front faceplate, it switches the 5V on again.

then again, a simple set-reset latch would work for that.
 
Upvote 0
Top