Android实现 Eq的频响曲线,可以调节峰值,高低通。曲线为算法实现。 - Go语言中文社区

Android实现 Eq的频响曲线,可以调节峰值,高低通。曲线为算法实现。


做过音频相关的应该见过这种Eq曲线,每一个点都有一个影响范围,并对整体曲线有影响。

图片为前半部分。之前做的时候在网上并没有找到,Eq曲线的计算和画法。这里拿出来分享一下。这里只提供画图的方法,曲线的算法不在这里提供(公司资产)。如有需要请私聊。(本人也是翻译mathlib获取的)

 



import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import com.iszcc.x5audio.bean.CarAudioConfig;
import com.iszcc.x5audio.bean.param.base.EQ;
import com.iszcc.x5audio.bean.param.base.FILTER;
import com.iszcc.x5audio.constans.Constants;
import com.iszcc.x5audio.eqcalc.CalcEqueal;
import com.iszcc.x5audio.eqcalc.EqParam;
import com.iszcc.x5audio.uitl.DataUtil;

import java.math.BigDecimal;
import java.util.ArrayList;

import static com.iszcc.x5audio.constans.Constants.EQ_freq;
import static com.iszcc.x5audio.constans.Constants.pointColor;

/**
 * Created by DB on 2017/6/9.
 */

public class EQSurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
    private static final String TAG = "SurfaceView";
    //SurfaceHolder
    private SurfaceHolder mHolder;

    private byte passByte = 0;

    //用于绘图的Canvas
    private Canvas canvas;
    //子线程标志位
    private boolean mIsDrawing;
    private Context mContext;

    private Paint paintXy;//xy轴画笔

    private Paint paintText;//文字画笔

    private Paint mWrapPaint;//曲线笔

    private Paint mPaintPoint;//

    private Paint mPaintCurve;//主曲线笔

    private Paint mPaintPass;// 显示EQ旁路的画笔


    // 坐标轴上描述性文字的空间大小
    private int mTopUnitHeight;// 顶部Y轴单位高度
    private int mBottomTextHeight;//X轴底部字体的高度
    private int mLeftTextWidth;
    // 网格尺寸
    private int mGridWidth, mGridHeight;

    private int yHeight, xWeith;//x y 轴的长度

    private ArrayList<Point> pointsList = new ArrayList<>();//点的集合
    private Point hPFPoint = new Point();//高通点
    private Point lPFPoint = new Point();//低通点


    private boolean isDrawWrap = false;//是否画阴影的曲线

    private boolean isDrawHLPF = false;//高低通

    private CalcEqueal calcEqueal = CalcEqueal.getInstance();

    //频响曲线
    private double[] freqX = new double[1024];
    private double[] freqY = new double[1024];

    //x y 轴坐标值
    private String[] xLineStr = new String[]{"-24dB", "-18dB", "-12dB", "-6dB", "0dB", "6dB", "12dB"};
    private String[] yLineStr = new String[]{"20HZ", "50HZ", "100HZ", "200HZ", "500HZ", "1kHZ", "2kHZ", "5kHZ", "10kHZ", "20kHZ"};
    //x轴什么所有线对应的频率值,对这些数取对数,在比上宽度值就是x坐标。
    private float[] yLin = new float[]{
            10,
            20.0f, 30.0f, 40.0f,
            50.0f, 60.0f, 70.0f, 80.0f, 90.0f,
            100.0f,
            200.0f, 300.0f, 400.0f,
            500.0f, 600.0f, 700.0f, 800.0f, 900.0f,
            1000.0f,
            2000.0f, 3000.0f, 4000.0f,
            5000.0f, 6000.0f, 7000.0f, 8000.0f, 9000.0f,
            10000.0f,
            20000.0f, 24000.0f};

    public EQSurfaceView(Context context) {
        super(context);
        mContext = context;
        initView();
    }


    public EQSurfaceView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        initView();
    }

    public EQSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        initView();
    }

    private void initView() {
        mHolder = getHolder();
        //添加回调
        mHolder.addCallback(this);

        {
            mBottomTextHeight = dp2px(20);// X轴底部字体的高度
            mLeftTextWidth = mBottomTextHeight;// Y轴左边字体的宽度
            mTopUnitHeight = dp2px(20);// 顶部Y轴的单位

            // 初始化坐标轴Paint
            paintXy = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
            paintXy.setStrokeWidth(dp2px(1));
            paintXy.setColor(Color.parseColor("#71737171"));
            // 初始化文本Paint
            paintText = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
            paintText.setColor(Color.GRAY);
            paintText.setTextSize(sp2px(8));

            //Eq 旁路的画笔

            mPaintPass = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
            mPaintPass.setColor(Color.GRAY);
            mPaintPass.setTextSize(sp2px(40));

            // 初始化曲线Paint
            mWrapPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
            // mWrapPaint.setPathEffect(new CornerPathEffect(50f));//设置转角度数

            //初始化主曲线笔
            mPaintCurve = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);

            //画点
            mPaintPoint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
            mPaintPoint.setColor(Color.RED);
            mPaintPoint.setStrokeWidth(dp2px(2));
            mPaintPoint.setStyle(Paint.Style.FILL);

        }

        setFocusable(true);
        setFocusableInTouchMode(true);
        this.setKeepScreenOn(true);
    }

    //Surface的生命周期
    @Override
    public void surfaceCreated(SurfaceHolder holder) {

        mIsDrawing = true;
        new Thread(this).start();
        isFristDraw = true;
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {


    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        mIsDrawing = false;

    }

    private boolean isFristDraw = false;

    @Override
    public void run() {
        while (mIsDrawing) {
            draw();
            //通过线程休眠以控制刷新速度
            try {
                Thread.sleep(50);
                if (isFristDraw) {

                    CarAudioConfig carAudioConfig = CarAudioConfig.getInstance();
                    byte eqPass = (byte) ((carAudioConfig.getMusic().getMusicL_EQSel().getValue() & 0x80) >> 7);
                    calcEq(carAudioConfig.getMusic().getMusicL_EQ_Show(),
                            carAudioConfig.getMusic().getMusicL_HPF(),
                            carAudioConfig.getMusic().getMusicL_LPF(), eqPass);
                    isFristDraw = false;
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private void draw() {
        try {
            //锁定画布并返回画布对象
            canvas = mHolder.lockCanvas();
            //接下去就是在画布上进行一下draw
            if (canvas != null) {
                canvas.drawRGB(0, 0, 0);//设置画布为黑色

                drawLineXY(canvas);//绘制xy

                drawWrap(canvas);//绘制阴影曲线

                drawPoint(canvas);//绘制点

                drawFrequencyCurve(canvas);

                drawEqPass(canvas);

            }

        } catch (Exception e) {
            mIsDrawing = false;
        } finally {
            //当画布内容不为空时,才post,避免出现黑屏的情况。
            if (canvas != null) {
                mHolder.unlockCanvasAndPost(canvas);
            }
        }
    }

    private String passText = "EQ BYPASS";

    /**
     * Eq 旁路
     *
     * @param canvas
     */
    private void drawEqPass(Canvas canvas) {
        if (passByte == 0) {
            return;
        }
        float textWieth = mPaintPass.measureText(passText);

        canvas.drawText(passText, getWidth() / 2 - textWieth / 2, getHeight() / 2 + dp2px(40) / 2, mPaintPass);
    }

    /**
     * 绘制点
     *
     * @param canvas
     */
    private void drawPoint(Canvas canvas) {

        for (int i = 0; i < pointsList.size(); i++) {
            mPaintPoint.setColor(pointColor[i]);
            canvas.drawCircle(pointsList.get(i).x, pointsList.get(i).y, dp2px(2), mPaintPoint);
        }

        //高通
        mPaintPoint.setColor(Color.YELLOW);
        canvas.drawCircle(hPFPoint.x, hPFPoint.y, dp2px(2), mPaintPoint);
        //低通
        mPaintPoint.setColor(Color.RED);
        canvas.drawCircle(lPFPoint.x, lPFPoint.y, dp2px(2), mPaintPoint);


    }

    /**
     * 绘制阴影部分曲线
     */
    private void drawWrap(Canvas canvas) {

        canvas.clipRect(new RectF(
                getPaddingLeft() + mLeftTextWidth,
                0,
                getRight() - getPaddingRight(),
                getHeight() - getPaddingBottom() - mBottomTextHeight)
        );
        if (!isDrawWrap) {
            return;
        }

        if (!isDrawHLPF) {
            //eq划线
            Path path = new Path();
            path.moveTo((float) eqX[0], (float) calcPointY(0));

            for (int index = 0; index < eqX.length; index++) {
                path.lineTo((float) eqX[index], (float) eqY[index]);
            }

            mWrapPaint.setStyle(Paint.Style.FILL);
            path.lineTo(getRight() - getPaddingRight(), (float) calcPointY(0));
            path.close();

            mWrapPaint.setColor(Color.parseColor("#71c2bbbb"));
            canvas.drawPath(path, mWrapPaint);

        } else {
            //高低通划线

            Path path = new Path();
            path.moveTo((float) eqX[0], (float) calcPointY(-24));

            for (int index = 0; index < eqX.length; index++) {
                path.lineTo((float) eqX[index], (float) eqY[index]);
            }

            mWrapPaint.setStyle(Paint.Style.FILL);
            path.lineTo((float) eqX[eqX.length - 1], (float) calcPointY(-24));
            path.close();

            mWrapPaint.setColor(Color.parseColor("#71c2bbbb"));
            canvas.drawPath(path, mWrapPaint);


        }

        // isDrawWrap = false;

    }

    /**
     * 绘制主曲线
     *
     * @param canvas
     */
    private void drawFrequencyCurve(Canvas canvas) {

        Path path = new Path();
        path.moveTo((float) freqX[0], (float) freqY[0]);

        for (int index = 1; index < freqX.length; index++) {
            path.lineTo((float) freqX[index], (float) freqY[index]);
        }

        //  path.lineTo(getRight() - getPaddingRight(), (float) calcPointY(0));
        // path.close(); 曲线闭合

        mPaintCurve.setColor(Color.GREEN);
        mPaintCurve.setStrokeWidth(dp2px(1.0f));
        mPaintCurve.setStyle(Paint.Style.STROKE);

        canvas.drawPath(path, mPaintCurve);

    }

    /**
     * 绘制 X Y 坐标系
     */
    private void drawLineXY(Canvas canvas) {

        Point start = new Point();
        Point stop = new Point();

        int xLineCount = xLineStr.length;


        yHeight = getHeight() - getPaddingTop() - getPaddingBottom() - mBottomTextHeight - mTopUnitHeight;//y轴高度
        mGridHeight = yHeight / (xLineCount - 1);

        for (int i = 0; i < xLineCount; i++) {
            start.x = getPaddingLeft() + mLeftTextWidth;
            start.y = getHeight() - getPaddingBottom() - mBottomTextHeight - mGridHeight * i;
            stop.x = getRight() - getPaddingRight();
            stop.y = start.y;
            // 绘制横轴线
            canvas.drawLine(start.x, start.y, stop.x, stop.y, paintXy);


            // 绘制纵坐标单位
            String drawText = xLineStr[i];
            Paint.FontMetricsInt fontMetrics = paintText.getFontMetricsInt();
            float offsetY = ((fontMetrics.bottom - fontMetrics.top) / 2 + fontMetrics.bottom) / 2;
            float baseLine = start.y + offsetY;
            float left = getPaddingLeft() + mLeftTextWidth / 2 - paintText.measureText(drawText) / 2;
            canvas.drawText(drawText, left, baseLine, paintText);

            if (i != xLineCount - 1) {

                start.x = getPaddingLeft() + mLeftTextWidth;
                start.y = getHeight() - getPaddingBottom() - mBottomTextHeight - mGridHeight * i - mGridHeight / 2;
                stop.x = getRight() - getPaddingRight();
                stop.y = start.y;
                // 绘制横轴线
                canvas.drawLine(start.x, start.y, stop.x, stop.y, paintXy);
            }

        }

        // 2. 绘制纵轴线和横坐标单位
       /* int yLineCount = yLineStr.length;
        mGridWidth = (getWidth() - getPaddingLeft() - getPaddingRight() - mLeftTextWidth) / (yLineCount - 1);*/

        xWeith = getWidth() - getPaddingLeft() - getPaddingRight() - mLeftTextWidth;

        double[] yJuli = calcYlin(xWeith);//计算y坐标的位置
        int textInt = 0;
        for (int i = 0; i < yJuli.length; i++) {
            start.x = (int) (getPaddingLeft() + mLeftTextWidth + yJuli[i]);
            start.y = getPaddingTop() + mTopUnitHeight;
            stop.x = start.x;
            stop.y = getHeight() - mBottomTextHeight - getPaddingBottom();
            // 绘制纵轴线
            canvas.drawLine(start.x, start.y, stop.x, stop.y, paintXy);

            // 绘制横坐标单位

            if (i == 1 || i == 4 || i == 9 || i == 10 || i == 13 || i == 18 || i == 19 || i == 22 || i == 27 || i == 28) {
                String drawText = yLineStr[textInt];
                Paint.FontMetricsInt fontMetrics = paintText.getFontMetricsInt();
                float offsetY = ((fontMetrics.bottom - fontMetrics.top) / 2 + fontMetrics.bottom) / 2;
                float baseLine = getHeight() - getPaddingBottom() - mBottomTextHeight / 2 + offsetY;
                float left = start.x - paintText.measureText(drawText) / 2;

                canvas.drawText(drawText, left, baseLine, paintText);
                textInt++;
            }
        }


    }

    /**
     * 将增益和频率转化为坐标上的点
     *
     * @param gain 增益
     * @param freq 频率
     * @return
     */
    private Point calcPoint(float gain, float freq) {

        return new Point((int) calcPointX(freq), (int) calcPointY(gain));
    }


    /**
     * 将y坐标点转化为增益
     *
     * @param y
     * @return
     */
    private float calcYToGain(int y) {

        float hBili = ((getHeight() - getPaddingBottom() - mBottomTextHeight) - y) / (float) yHeight;//高度比例


        float T = 36 * hBili - 24;
        BigDecimal b = new BigDecimal(T);

        return b.setScale(1, BigDecimal.ROUND_HALF_UP).floatValue();

    }


    /**
     * 将y坐标转化为频率
     *
     * @param x
     * @return
     */
    private float calcXToFreq(int x) {

        double bili = (x - (getPaddingLeft() + mLeftTextWidth)) / (double) xWeith; //getWidth() - getPaddingLeft() - getPaddingRight() - mLeftTextWidth;

        Log.e("calcPoint:", "calcXToFreq :比例11 :" + (x - (getPaddingLeft() + mLeftTextWidth)) + " 对数22:" + xWeith);

        //最大值和最小值取对数的的差值(对应x轴长度)
        double duiShuCha = logarithm(24000.0f, 10.0) - 1;// logarithm(10.0f, 10.0)=1

        double v = duiShuCha * bili + 1;

        Log.e("calcPoint:", "calcXToFreq :比例 :" + bili + " 对数:" + v);

        float T = (float) Math.pow(10.0f, v);//求平方值

        //保留一位小数的返回值
        BigDecimal b = new BigDecimal(T);
        return b.setScale(1, BigDecimal.ROUND_HALF_UP).floatValue();
    }

    /**
     * 计算增益对应的y轴高度
     */
    private double calcPointY(double gain) {

        //y坐标高度


        return (getHeight() - getPaddingBottom() - mBottomTextHeight) - ((double) (gain - (-24)) / (double) 36) * yHeight;

    }

    /**
     * 计算增益对应的X轴高度
     */
    private double calcPointX(double freq) {
        //最大值和最小值取对数的的差值(对应x轴长度)
        double duiShuCha = logarithm(24000.0f, 10.0) - 1;// logarithm(10.0f, 10.0)=1

        return (double) ((getPaddingLeft() + mLeftTextWidth) + (((logarithm((double) freq, 10.0f) - 1) / duiShuCha) * xWeith));
    }

    /**
     * 计算y坐标的位置
     * <p>
     * y坐标为相应的值去对数,然后根据对数比例来确定坐标位置
     * weith x轴长度
     */
    private double[] calcYlin(int weith) {

        //最大值和最小值取对数的的差值(对应x轴长度)
        double duiShuCha = logarithm(24000.0f, 10.0) - 1;// logarithm(10.0f, 10.0)=1

        double[] yJuli = new double[yLin.length];//保存各个点到原点的距离
        for (int i = 0; i < yLin.length; i++) {
            //x轴上的值去对数 - 1 与最大最小对数差值比例 *  x轴长度
            yJuli[i] = ((logarithm(yLin[i], 10.0f) - 1) / duiShuCha) * weith;
        }
        return yJuli;

    }


    private double[] eqX = new double[1024];
    private double[] eqY = new double[1024];

    public void setEq(int eqItem, Constants.DRAW_EQ drawHLPF, EQ[] eqs, FILTER hPF, FILTER lPF, byte eqPass) {

        int selectItem = 0;


        if (drawHLPF == Constants.DRAW_EQ.PEQ) {
            selectItem = eqItem;//选中为具体的eq段
        } else if (drawHLPF == Constants.DRAW_EQ.HPF) {
            selectItem = eqs.length;//选中为高通
        } else if (drawHLPF == Constants.DRAW_EQ.LPF) {
            selectItem = eqs.length + 1;//选中为低通
        }

        //传递selectItem的作用就是在计算eq曲线的时候,初始化全部的eq段和高低通全部要计算一遍,
        // 传递selectItem就是接下来只计算调节之后的那一段曲线,其他复用之前的,减少计算量。
        EqParam[] eqParams = initEq(eqs, hPF, lPF, selectItem);


        eqX = freqX;

        if (drawHLPF == Constants.DRAW_EQ.PEQ) {
            isDrawHLPF = false;

            isDrawWrap = true;

            for (int i = 0; i < eqY.length; i++) {
                eqY[i] = calcPointY(eqParams[eqItem].getPts()[i]);
            }

        } else if (drawHLPF == Constants.DRAW_EQ.HPF) {
            if (calcHLPFFreq(hPF) == 0) {//如果频率为0,不显示阴影
                isDrawWrap = false;
            } else {
                isDrawWrap = true;
            }
            isDrawHLPF = true;


            for (int i = 0; i < eqY.length; i++) {
                eqY[i] = calcPointY(eqParams[eqs.length].getPts()[i]);
            }

        } else if (drawHLPF == Constants.DRAW_EQ.LPF) {
            if (calcHLPFFreq(lPF) == 0) {
                isDrawWrap = false;
            } else {
                isDrawWrap = true;
            }
            isDrawHLPF = true;
            for (int i = 0; i < eqY.length; i++) {
                eqY[i] = calcPointY(eqParams[eqs.length + 1].getPts()[i]);
            }
        }

        //   invalidate();
    }

    public void setEqEffect(int eqItem, Constants.DRAW_EQ drawHLPF, EQ[] eqs, int hPF, int lPF, byte eqPass) {

        int selectItem = 0;


        if (drawHLPF == Constants.DRAW_EQ.PEQ) {
            selectItem = eqItem;//选中为具体的eq段
        } else if (drawHLPF == Constants.DRAW_EQ.HPF) {
            selectItem = eqs.length;//选中为高通
        } else if (drawHLPF == Constants.DRAW_EQ.LPF) {
            selectItem = eqs.length + 1;//选中为低通
        }

        //传递selectItem的作用就是在计算eq曲线的时候,初始化全部的eq段和高低通全部要计算一遍,传递selectItem就是接下来只计算调节之后的那一段曲线,其他复用之前的,减少计算量。
        EqParam[] eqParams = initEqEffect(eqs, hPF, lPF, selectItem);


        eqX = freqX;

        if (drawHLPF == Constants.DRAW_EQ.PEQ) {
            isDrawHLPF = false;

            isDrawWrap = true;

            for (int i = 0; i < eqY.length; i++) {
                eqY[i] = calcPointY(eqParams[eqItem].getPts()[i]);
            }

        } else if (drawHLPF == Constants.DRAW_EQ.HPF) {
            if (Constants.LHFP_freq[hPF] == 0) {//如果频率为0,不显示阴影
                isDrawWrap = false;
            } else {
                isDrawWrap = true;
            }
            isDrawHLPF = true;


            for (int i = 0; i < eqY.length; i++) {
                eqY[i] = calcPointY(eqParams[eqs.length].getPts()[i]);
            }

        } else if (drawHLPF == Constants.DRAW_EQ.LPF) {
            if (Constants.LFP_freq[lPF] == 0) {
                isDrawWrap = false;
            } else {
                isDrawWrap = true;
            }
            isDrawHLPF = true;
            for (int i = 0; i < eqY.length; i++) {
                eqY[i] = calcPointY(eqParams[eqs.length + 1].getPts()[i]);
            }
        }

        //   invalidate();
    }


    public void calcEq(EQ[] eqs, FILTER hPF, FILTER lPF, byte eqPass) {
        this.passByte = eqPass;

        initEq(eqs, hPF, lPF, -1);
        isDrawWrap = false;
        //   invalidate();

    }

    public void calcEqEffect(EQ[] eqs, int hPF, int lPF, byte eqPass) {

        initEqEffect(eqs, hPF, lPF, -1);
        isDrawWrap = false;
        //   invalidate();

    }


    public EqParam[] initEq(EQ[] eqs, FILTER hPF, FILTER lPF, int eqItem) {


        //高低通
        float lhPFGain = -15;//高低通位置放在-14的增益位置

        //高通
        float hPFFreq = calcHLPFFreq(hPF);
        hPFPoint = calcPoint(lhPFGain, hPFFreq);

        //低通
        float lPFFreq = calcHLPFFreq(lPF);
        lPFPoint = calcPoint(lhPFGain, lPFFreq);

        EqParam[] eqParams = drawEq(eqs, eqItem,
                hPF.getFilter_Type().getValueInt(), hPFFreq, (Constants.EQ_q[hPF.getFilter_Q().getValueInt()]),
                lPF.getFilter_Type().getValueInt(), lPFFreq, (Constants.EQ_q[lPF.getFilter_Q().getValueInt()]));


        return eqParams;
    }


    /**
     * 效果部分的高低通只有频率,没有q值和类型等参数所以不能传递FILTER
     *
     * @param eqs
     * @param hPF
     * @param lPF
     */
    public EqParam[] initEqEffect(EQ[] eqs, int hPF, int lPF, int eqItem) {


        //高低通
        float lhPFGain = -15;//高低通位置放在-15的增益位置

        //高通
        double hPFFreq = Constants.LHFP_freq[hPF];

        hPFPoint = calcPoint(lhPFGain, (float) hPFFreq);

        //低通
        double lPFFreq = Constants.LFP_freq[lPF];

        lPFPoint = calcPoint(lhPFGain, (float) lPFFreq);

        EqParam[] eqParams = drawEq(eqs, eqItem,
                3, hPFFreq, (Constants.EQ_q[9]),
                3, lPFFreq, (Constants.EQ_q[9]));

        return eqParams;
    }


    /**
     * 显示eq曲线的公共方法
     *
     * @param eqs     eq
     * @param hType   高通类型
     * @param hPFFreq 高通频率
     * @param hQ      高通q值
     * @param lType   低通类型
     * @param lPFFreq 低通频率
     * @param lQ      低通q值
     */
    private EqParam[] drawEq(EQ[] eqs, int eqItem, int hType, double hPFFreq, double hQ, int lType, double lPFFreq, double lQ) {
        pointsList.clear();
        for (int i = 0; i < eqs.length; i++) {
            int gain = DataUtil.pinJie2ByteToInt(eqs[i].getEQ_Gain().getValue()[1], eqs[i].getEQ_Gain().getValue()[0]);
            int freq = DataUtil.pinJie2ByteToInt(eqs[i].getEQ_Freq().getValue()[1], eqs[i].getEQ_Freq().getValue()[0]);


            Point point = calcPoint(gain / 10.0f - 24, (float) EQ_freq[freq]);

            pointsList.add(point);
        }

        //主曲线
        ArrayList<EqParam> eqParamList = new ArrayList<>();

        //添加峰值
        for (int i = 0; i < eqs.length; i++) {
            EqParam eqParam = new EqParam();

            //滤波器
            if (eqs[i].getEQ_Mode().getValueInt() == 0) {
                eqParam.setType(0);//类型
                eqParam.setFilter(Constants.ENUM_FILTER_TYPE.eParametric);
                eqParam.setQ(Constants.EQ_q[eqs[i].getEQ_PEQ_Q().getValueInt()]);
            } else if (eqs[i].getEQ_Mode().getValueInt() == 1) {
                eqParam.setType(1);//类型
                eqParam.setFilter(Constants.ENUM_FILTER_TYPE.eShelving);
                eqParam.setQ2(Constants.EQ_q[eqs[i].getEQ_HLSEQ_Q().getValueInt()]);
            } else if (eqs[i].getEQ_Mode().getValueInt() == 2) {
                eqParam.setType(2);//类型
                eqParam.setFilter(Constants.ENUM_FILTER_TYPE.eShelving);
                eqParam.setQ2(Constants.EQ_q[eqs[i].getEQ_HLSEQ_Q().getValueInt()]);
            }
            //频率
            int freq = DataUtil.pinJie2ByteToInt(eqs[i].getEQ_Freq().getValue()[1], eqs[i].getEQ_Freq().getValue()[0]);
            eqParam.setFreq(EQ_freq[freq]);
            //增益
            int gain = DataUtil.pinJie2ByteToInt(eqs[i].getEQ_Gain().getValue()[1], eqs[i].getEQ_Gain().getValue()[0]);
            eqParam.setGain(gain / 10.0f - 24);


            eqParamList.add(eqParam);
        }

        //高通
        EqParam eqParamH = new EqParam();
        eqParamH.setType(2);
        if (hType == 0) {
            eqParamH.setFilter(Constants.ENUM_FILTER_TYPE.eBessel);
            eqParamH.setGain(-24);
        } else if (hType == 1) {
            eqParamH.setFilter(Constants.ENUM_FILTER_TYPE.eButterWorth);
            eqParamH.setGain(-24);
        } else if (hType == 2) {
            eqParamH.setFilter(Constants.ENUM_FILTER_TYPE.eLinkWitz_Riley);
            eqParamH.setGain(-24);
        } else if (hType == 3) {
            eqParamH.setFilter(Constants.ENUM_FILTER_TYPE.eUserFilter);
            eqParamH.setGain(-12);
        } else if (hType == 4) {
            eqParamH.setFilter(Constants.ENUM_FILTER_TYPE.eUserFilter);
            eqParamH.setGain(-24);
        }

        eqParamH.setFreq(hPFFreq);
        eqParamH.setQ(hQ);

        //低通
        EqParam eqParamL = new EqParam();
        eqParamL.setType(1);
        if (lType == 0) {
            eqParamL.setFilter(Constants.ENUM_FILTER_TYPE.eBessel);
            eqParamL.setGain(-24);
        } else if (lType == 1) {
            eqParamL.setFilter(Constants.ENUM_FILTER_TYPE.eButterWorth);
            eqParamL.setGain(-24);
        } else if (lType == 2) {
            eqParamL.setFilter(Constants.ENUM_FILTER_TYPE.eLinkWitz_Riley);
            eqParamL.setGain(-24);
        } else if (lType == 3) {
            eqParamL.setFilter(Constants.ENUM_FILTER_TYPE.eUserFilter);
            eqParamL.setGain(-12);
        } else if (lType == 4) {
            eqParamL.setFilter(Constants.ENUM_FILTER_TYPE.eUserFilter);
            eqParamL.setGain(-24);
        }

        eqParamL.setFreq(lPFFreq);
        eqParamL.setQ(lQ);//EqDatebase.Qx100[lPF.getFilter_Q().getValueInt()

        eqParamList.add(eqParamH);
        eqParamList.add(eqParamL);

        //集合转数组
        EqParam[] eqParams = new EqParam[eqParamList.size()];
        eqParamList.toArray(eqParams);


        double[] doubles = calcEqueal.setCalcEqueal(eqs.length, eqParams, eqItem);

        freqCurve(doubles);


        return calcEqueal.getmEqParams();

    }


    /**
     * 主曲线
     *
     * @param freqs
     */
    private void freqCurve(double[] freqs) {

        double x = (double) xWeith / 1023.00;
        freqX[0] = (getPaddingLeft() + mLeftTextWidth);
        for (int i = 1; i < freqX.length; i++) {
            freqX[i] = freqX[i - 1] + x;
        }

        for (int i = 0; i < freqY.length; i++) {
            freqY[i] = calcPointY(freqs[i]);

        }
    }


    /**
     * 计算高低通频率
     *
     * @param filter
     * @return
     */
    private float calcHLPFFreq(FILTER filter) {

        int feqMulH = filter.getFilter_FeqMul().getValueInt();//倍数 0 x1, 1 x10 2 x100
        int beishuH = 1;
        if (feqMulH == 0) {
            beishuH = 1;
        } else if (feqMulH == 1) {
            beishuH = 10;
        } else if (feqMulH == 2) {
            beishuH = 100;
        }
        float hPFFreq = (float) (Constants.LHFP_freq[filter.getFilter_Freq().getValueInt()] * beishuH);

        return hPFFreq > 20600 ? 20600 : hPFFreq;
    }

    /**
     * 对数计算公式
     *
     * @return
     */
    private double logarithm(double value, double base) {
        return Math.log(value) / Math.log(base);
    }


    private int dp2px(float dp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                dp, getResources().getDisplayMetrics());
    }

    private int sp2px(float sp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
                sp, getResources().getDisplayMetrics());
    }


    public Canvas getCanvas() {
        return canvas;
    }

    public void setCanvas(Canvas canvas) {
        this.canvas = canvas;
    }
}

 

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/zhongruichun/article/details/88656273
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-04-19 16:55:37
  • 阅读 ( 1601 )
  • 分类:算法

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢