做过音频相关的应该见过这种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;
}
}