页面优化
This commit is contained in:
@@ -35,7 +35,7 @@ export default function BottomNav() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<nav
|
<nav
|
||||||
className="fixed bottom-0 left-0 right-0 z-50 lg:hidden"
|
className="fixed bottom-0 left-0 right-0 z-50"
|
||||||
style={{
|
style={{
|
||||||
background: "rgba(10, 10, 12, 0.96)",
|
background: "rgba(10, 10, 12, 0.96)",
|
||||||
backdropFilter: "blur(40px) saturate(200%)",
|
backdropFilter: "blur(40px) saturate(200%)",
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
class Coeff{
|
|
||||||
constructor() {
|
|
||||||
this.b0 = 0;
|
|
||||||
this.b1 = 0;
|
|
||||||
this.b2 = 0;
|
|
||||||
this.a0 = 0;
|
|
||||||
this.a1 = 0;
|
|
||||||
this.a2 = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
setB0(value){
|
|
||||||
this.b0 = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
setB1(value){
|
|
||||||
this.b1 = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
setB2(value){
|
|
||||||
this.b2 = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
setA0(value){
|
|
||||||
this.a0 = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
setA1(value){
|
|
||||||
this.a1 = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
setA2(value){
|
|
||||||
this.a2 = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
getSectionsMatrix(gain, fc, bw, type, bypass, fs){
|
|
||||||
const w = 2 * fc / fs;
|
|
||||||
const q = fc / bw;
|
|
||||||
const bypassStatus = bypass ? 1 : 0;
|
|
||||||
const bqtype = type + bypassStatus * 10;
|
|
||||||
const sA = Math.pow(10, gain / 40);
|
|
||||||
const sqrt_sA = Math.sqrt(sA);
|
|
||||||
const sin_w = Math.sin(Math.PI * w);
|
|
||||||
const cos_w = Math.cos(Math.PI * w);
|
|
||||||
const alpha = sin_w / (2 * q);
|
|
||||||
|
|
||||||
let b0, b1, b2, a0, a1, a2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,512 +0,0 @@
|
|||||||
import * as echarts from 'echarts'
|
|
||||||
|
|
||||||
export const TYPE_PEAK = 0;
|
|
||||||
export const TYPE_LOWSHELF = 1;
|
|
||||||
export const TYPE_HIGHSHELF = 2;
|
|
||||||
export const TYPE_LOWPASS = 3;
|
|
||||||
export const TYPE_HIGHPASS = 4;
|
|
||||||
export const TYPE_BANDPASS = 5;
|
|
||||||
export const TYPE_NOTCH = 6;
|
|
||||||
export const TYPE_ALLPASS = 7;
|
|
||||||
export const LPF_1ST = 8;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Audio bean
|
|
||||||
export class AudioBean {
|
|
||||||
constructor(gain, fc, fs, type, bypass, q) {
|
|
||||||
this.gain = gain;
|
|
||||||
this.fc = fc;
|
|
||||||
this.fs = fs;
|
|
||||||
this.type = type;
|
|
||||||
this.bypass = bypass;
|
|
||||||
this.q = q;
|
|
||||||
}
|
|
||||||
|
|
||||||
getGain(){return this.gain;}
|
|
||||||
getFc(){return this.fc;}
|
|
||||||
getFs(){return this.fs;}
|
|
||||||
getType(){return this.type;}
|
|
||||||
getBypass(){return this.bypass;}
|
|
||||||
getQ(){return this.q;}
|
|
||||||
setGain(gain){this.gain = gain;}
|
|
||||||
setFc(fc){this.fc = fc;}
|
|
||||||
setFs(fs){this.fs = fs;}
|
|
||||||
setType(type){this.type = type;}
|
|
||||||
setBypass(bypass){this.bypass = bypass;}
|
|
||||||
setQ(q){this.q = q;}
|
|
||||||
|
|
||||||
toString(){
|
|
||||||
return "AudioTunningEQ [gain=" + this.gain + ", fc=" + this.fc + ", fs=" + this.fs + ", type=" + this.type + ", bypass=" + this.bypass + ", q=" + this.q + "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//Coeff bean
|
|
||||||
class Coeff {
|
|
||||||
constructor(props) {
|
|
||||||
this.b0 = 0;
|
|
||||||
this.b1 = 0;
|
|
||||||
this.b2 = 0;
|
|
||||||
this.a0 = 0;
|
|
||||||
this.a1 = 0;
|
|
||||||
this.a2 = 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
setB0(b0) {this.b0 = b0;}
|
|
||||||
setB1(b1) {this.b1 = b1;}
|
|
||||||
setB2(b2) {this.b2 = b2;}
|
|
||||||
setA0(a0) {this.a0 = a0;}
|
|
||||||
setA1(a1) {this.a1 = a1;}
|
|
||||||
setA2(a2) {this.a2 = a2;}
|
|
||||||
getB0(){return this.b0;}
|
|
||||||
getB1(){return this.b1;}
|
|
||||||
getB2(){return this.b2;}
|
|
||||||
getA0(){return this.a0;}
|
|
||||||
getA1(){return this.a1;}
|
|
||||||
getA2(){return this.a2;}
|
|
||||||
|
|
||||||
toString() {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Complex bean
|
|
||||||
class Complex {
|
|
||||||
constructor(real, image) {
|
|
||||||
this.real = real;
|
|
||||||
this.image = image;
|
|
||||||
}
|
|
||||||
|
|
||||||
getReal() {return this.real;}
|
|
||||||
getImage() {return this.image;}
|
|
||||||
setReal(real) {this.real = real;}
|
|
||||||
setImage(image) {this.image = image;}
|
|
||||||
|
|
||||||
add(a) {
|
|
||||||
return new Complex(this.real + a.real, this.image + a.image);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub(a) { // 复数相减
|
|
||||||
return new Complex(this.real - a.real, this.image - a.image);
|
|
||||||
}
|
|
||||||
|
|
||||||
div(a) { // 复数相除
|
|
||||||
const denominator = a.real * a.real + a.image * a.image;
|
|
||||||
const newReal = (this.real * a.real + this.image * a.image) / denominator;
|
|
||||||
const newImage = (this.image * a.real - this.real * a.image) / denominator;
|
|
||||||
return new Complex(newReal, newImage);
|
|
||||||
}
|
|
||||||
|
|
||||||
mul(a) { // 复数相乘
|
|
||||||
const newReal = this.real * a.real - this.image * a.image;
|
|
||||||
const newImage = this.image * a.real + this.real * a.image;
|
|
||||||
return new Complex(newReal, newImage);
|
|
||||||
}
|
|
||||||
|
|
||||||
mulScalar(a) { // 复数与实数相乘
|
|
||||||
return new Complex(this.real * a, this.image * a);
|
|
||||||
}
|
|
||||||
|
|
||||||
addScalar(a) { // 复数与实数相加
|
|
||||||
return new Complex(this.real + a, this.image);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getFreqznList(coeffList, fs, f) {
|
|
||||||
let n = f.length;
|
|
||||||
let h = new Array(n);
|
|
||||||
for (let i = 0; i < n; i++) {
|
|
||||||
let w = 2*Math.PI*(f[i])/fs;
|
|
||||||
let complex = getFreqwList(coeffList, w);
|
|
||||||
h[i] = 20*Math.log10(Math.abs(getAmplitude(complex)));
|
|
||||||
}
|
|
||||||
return h;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getFreqzn(coeff, fs, f) {
|
|
||||||
let n = f.length;
|
|
||||||
let h = new Array(n);
|
|
||||||
for (let i = 0; i < n; i++) {
|
|
||||||
let w = 2*Math.PI*(f[i])/fs;
|
|
||||||
let complex = getFreqw(coeff, w);
|
|
||||||
h[i] = 20*Math.log10(Math.abs(getAmplitude(complex)));
|
|
||||||
}
|
|
||||||
return h;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getAmplitude(complex) {
|
|
||||||
return Math.sqrt(Math.pow(complex.getReal(),2)+Math.pow(complex.getImage(),2));
|
|
||||||
}
|
|
||||||
|
|
||||||
function getFreqw(coeff, w) {
|
|
||||||
const complex = new Complex(Math.cos(w), -Math.sin(w));
|
|
||||||
const b2 = (complex.mul(complex)).mulScalar(coeff.getB2());
|
|
||||||
const b1 = complex.mulScalar(coeff.getB1());
|
|
||||||
const hup = b2.add(b1).addScalar(coeff.getB0());
|
|
||||||
const a2 = (complex.mul(complex)).mulScalar(coeff.getA2());
|
|
||||||
const a1 = complex.mulScalar(coeff.getA1());
|
|
||||||
const hdown = a2.add(a1).addScalar(coeff.getA0());
|
|
||||||
return hup.div(hdown);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getFreqwList(coeffList, w){
|
|
||||||
let h = getFreqw(coeffList[0], w);
|
|
||||||
coeffList.slice(1).forEach((item) => {
|
|
||||||
h = h.mul(getFreqw(item, w));
|
|
||||||
});
|
|
||||||
return h;
|
|
||||||
}
|
|
||||||
|
|
||||||
function test(fc, q) {
|
|
||||||
let w = fc * 2 / (48000*1000);
|
|
||||||
let down = Math.sqrt(Math.pow((1 - w * w), 2) + w * w / (q * q));
|
|
||||||
let gain = 1 / down;
|
|
||||||
let db = 20 * Math.log10(gain);
|
|
||||||
return db;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function visualizeResponse(coeffList, fs) {
|
|
||||||
let validCoeffList = []
|
|
||||||
let n = 349
|
|
||||||
let startF = 20
|
|
||||||
let endF = 20000
|
|
||||||
let logStep = (Math.log10(20000) - Math.log10(20)) / n
|
|
||||||
let f = new Array(n)
|
|
||||||
let step = Math.pow(10, logStep)
|
|
||||||
for (let i = 0; i < n; i++) {
|
|
||||||
f[i] = startF * Math.pow(step, i)
|
|
||||||
}
|
|
||||||
|
|
||||||
let semilogf = new Array(n)
|
|
||||||
// 注意:此函数逻辑不能改动,保持与原项目一致,仅计算前 200 个点
|
|
||||||
for (let i = 0; i < 200; i++) {
|
|
||||||
semilogf[i] = Math.log10(f[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
let xValues = []
|
|
||||||
let yValues = []
|
|
||||||
let titleList = []
|
|
||||||
coeffList.forEach((coeff, i) => {
|
|
||||||
if (
|
|
||||||
!Number.isNaN(coeff.getB0()) &&
|
|
||||||
!Number.isNaN(coeff.getB1()) &&
|
|
||||||
!Number.isNaN(coeff.getB2()) &&
|
|
||||||
!Number.isNaN(coeff.getA0()) &&
|
|
||||||
!Number.isNaN(coeff.getA1()) &&
|
|
||||||
!Number.isNaN(coeff.getA2())
|
|
||||||
) {
|
|
||||||
validCoeffList.push(coeff)
|
|
||||||
let h = getFreqzn(coeff, fs, f)
|
|
||||||
xValues.push(semilogf)
|
|
||||||
yValues.push(h)
|
|
||||||
titleList.push('Band' + i)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if (yValues.length > 1) {
|
|
||||||
let overall = getFreqznList(validCoeffList, fs, f)
|
|
||||||
xValues.push(semilogf)
|
|
||||||
yValues.push(overall)
|
|
||||||
titleList.push('overall')
|
|
||||||
}
|
|
||||||
|
|
||||||
let testArray = new Array(n)
|
|
||||||
for (let i = 0; i < f.length; i++) {
|
|
||||||
testArray[i] = test(f[i], 1)
|
|
||||||
}
|
|
||||||
return [xValues[xValues.length - 1], yValues[yValues.length - 1]]
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getSectionsMatrix(gain, fc, q, type, bypass, fs) {
|
|
||||||
let w = 2*fc/fs;
|
|
||||||
let bypassStatus = bypass ? 1 : 0;
|
|
||||||
let bqtype = type + bypassStatus * 10;
|
|
||||||
const sA = Math.pow(10, gain / 40);
|
|
||||||
const sqrt_sA = Math.sqrt(sA);
|
|
||||||
const sin_w = Math.sin(Math.PI * w);
|
|
||||||
const cos_w = Math.cos(Math.PI * w);
|
|
||||||
const alpha = sin_w / (2*q);
|
|
||||||
let b0, b1, b2, a0, a1, a2;
|
|
||||||
switch (bqtype){
|
|
||||||
case TYPE_PEAK:
|
|
||||||
b0 = 1 + alpha * sA;
|
|
||||||
b1 = -2 * cos_w;
|
|
||||||
b2 = 1 - alpha * sA;
|
|
||||||
a0 = 1 + alpha / sA;
|
|
||||||
a1 = b1;
|
|
||||||
a2 = 1 - alpha / sA;
|
|
||||||
break;
|
|
||||||
case TYPE_LOWSHELF:
|
|
||||||
b0 = sA * ((sA + 1) - (sA - 1) * cos_w + 2 * sqrt_sA * alpha);
|
|
||||||
b1 = 2 * sA * ((sA - 1) - (sA + 1) * cos_w);
|
|
||||||
b2 = sA * ((sA + 1) - (sA - 1) * cos_w - 2 * sqrt_sA * alpha);
|
|
||||||
a0 = (sA + 1) + (sA - 1) * cos_w + 2 * sqrt_sA * alpha;
|
|
||||||
a1 = -2 * ((sA - 1) + (sA + 1) * cos_w);
|
|
||||||
a2 = (sA + 1) + (sA - 1) * cos_w - 2 * sqrt_sA * alpha;
|
|
||||||
break;
|
|
||||||
case TYPE_HIGHSHELF:
|
|
||||||
b0 = sA * ((sA + 1) + (sA - 1) * cos_w + 2 * sqrt_sA * alpha);
|
|
||||||
b1 = -2 * sA * ((sA - 1) + (sA + 1) * cos_w);
|
|
||||||
b2 = sA * ((sA + 1) + (sA - 1) * cos_w - 2 * sqrt_sA * alpha);
|
|
||||||
a0 = (sA + 1) - (sA - 1) * cos_w + 2 * sqrt_sA * alpha;
|
|
||||||
a1 = 2 * ((sA - 1) - (sA + 1) * cos_w);
|
|
||||||
a2 = (sA + 1) - (sA - 1) * cos_w - 2 * sqrt_sA * alpha;
|
|
||||||
break;
|
|
||||||
case TYPE_LOWPASS:
|
|
||||||
b0 = (1 - cos_w) / 2;
|
|
||||||
b1 = 1 - cos_w;
|
|
||||||
b2 = b0;
|
|
||||||
a0 = 1 + alpha;
|
|
||||||
a1 = -2 * cos_w;
|
|
||||||
a2 = 1 - alpha;
|
|
||||||
break;
|
|
||||||
case TYPE_HIGHPASS:
|
|
||||||
b0 = (1 + cos_w) / 2;
|
|
||||||
b1 = -(1 + cos_w);
|
|
||||||
b2 = b0;
|
|
||||||
a0 = 1 + alpha;
|
|
||||||
a1 = -2 * cos_w;
|
|
||||||
a2 = 1 - alpha;
|
|
||||||
break;
|
|
||||||
case TYPE_BANDPASS:
|
|
||||||
b0 = alpha;
|
|
||||||
b1 = 0;
|
|
||||||
b2 = -alpha;
|
|
||||||
a0 = 1 + alpha;
|
|
||||||
a1 = -2 * cos_w;
|
|
||||||
a2 = 1 - alpha;
|
|
||||||
break;
|
|
||||||
case TYPE_NOTCH:
|
|
||||||
b0 = 1;
|
|
||||||
b1 = -2 * cos_w;
|
|
||||||
b2 = 1;
|
|
||||||
a0 = 1 + alpha;
|
|
||||||
a1 = -2 * cos_w;
|
|
||||||
a2 = 1 - alpha;
|
|
||||||
break;
|
|
||||||
case TYPE_ALLPASS:
|
|
||||||
b0 = 1 - alpha;
|
|
||||||
b1 = -2 * cos_w;
|
|
||||||
b2 = 1 + alpha;
|
|
||||||
a0 = b2;
|
|
||||||
a1 = b1;
|
|
||||||
a2 = b0;
|
|
||||||
break;
|
|
||||||
case LPF_1ST:
|
|
||||||
let alpha_1st = sin_w / (cos_w + 1);
|
|
||||||
b0 = alpha_1st / (1 + alpha_1st);
|
|
||||||
b1 = b0;
|
|
||||||
b2 = 0;
|
|
||||||
a0 = 1;
|
|
||||||
a1 = (alpha_1st - 1) / (1 + alpha_1st);
|
|
||||||
a2 = 0;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
b0 = 1;
|
|
||||||
b1 = 0;
|
|
||||||
b2 = 0;
|
|
||||||
a0 = 1;
|
|
||||||
a1 = 0;
|
|
||||||
a2 = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
let coeff = new Coeff();
|
|
||||||
coeff.setB0(b0/a0);
|
|
||||||
coeff.setB1(b1/a0);
|
|
||||||
coeff.setB2(b2/a0);
|
|
||||||
coeff.setA0(a0/a0);
|
|
||||||
coeff.setA1(a1/a0);
|
|
||||||
coeff.setA2(a2/a0);
|
|
||||||
return coeff;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getFilterShortName(type){
|
|
||||||
switch (type){
|
|
||||||
case "LOW_PASS": return "LPF";
|
|
||||||
case "HIGH_PASS": return "HPF";
|
|
||||||
case "BAND_PASS": return "BPF";
|
|
||||||
case "LOW_SHELF": return "LSHELF";
|
|
||||||
case "HIGH_SHELF": return "HSHELF";
|
|
||||||
case "ALL_PASS": return "APF";
|
|
||||||
case "PEAKING": return "PEAK";
|
|
||||||
default: return type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getFilterTypeName(val){
|
|
||||||
switch(val){
|
|
||||||
case TYPE_LOWPASS: return "LPF";
|
|
||||||
case TYPE_HIGHPASS: return "HPF";
|
|
||||||
case TYPE_BANDPASS: return "BPF";
|
|
||||||
case TYPE_NOTCH: return "NOTCH";
|
|
||||||
case TYPE_PEAK: return "PEAK";
|
|
||||||
case TYPE_LOWSHELF: return "LSHELF";
|
|
||||||
case TYPE_HIGHSHELF: return "HSHELF";
|
|
||||||
case TYPE_ALLPASS: return "APF";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getFilterType(typeName) {
|
|
||||||
if(typeName === 'LPF' || typeName === 'LOWP_ASS'){
|
|
||||||
return TYPE_LOWPASS;
|
|
||||||
}
|
|
||||||
else if(typeName === 'HPF' || typeName === 'HIGH_PASS'){
|
|
||||||
return TYPE_HIGHPASS;
|
|
||||||
}
|
|
||||||
else if(typeName === 'BPF' || typeName === 'BAND_PASS'){
|
|
||||||
return TYPE_BANDPASS;
|
|
||||||
}
|
|
||||||
else if(typeName === 'NOTCH'){
|
|
||||||
return TYPE_NOTCH;
|
|
||||||
}
|
|
||||||
else if(typeName === 'PEAK' || typeName === 'PEAKING'){
|
|
||||||
return TYPE_PEAK;
|
|
||||||
}
|
|
||||||
else if(typeName === 'LSHELF' || typeName === 'LOW_SHELF'){
|
|
||||||
return TYPE_LOWSHELF;
|
|
||||||
}
|
|
||||||
else if(typeName === 'HSHELF' || typeName === 'HIGH_SHELF'){
|
|
||||||
return TYPE_HIGHSHELF;
|
|
||||||
}
|
|
||||||
else if(typeName === 'APF' || typeName === 'ALL_PASS'){
|
|
||||||
return TYPE_ALLPASS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getChartOps(dataSet, yMax, yMin, lineColor) {
|
|
||||||
//要显示的x轴刻度
|
|
||||||
const labelsToShow = [0, 43, 85, 116, 160, 200, 233, 281, 320, 348]
|
|
||||||
|
|
||||||
return {
|
|
||||||
xAxis: {
|
|
||||||
type: 'category',
|
|
||||||
data: dataSet[0],
|
|
||||||
axisLabel: {
|
|
||||||
formatter: function (value, index) {
|
|
||||||
// 指定只显示 index 在(0,47,93,115)的标签
|
|
||||||
if (labelsToShow.includes(index)) {
|
|
||||||
switch (index) {
|
|
||||||
case 0:
|
|
||||||
return '20'
|
|
||||||
case 43:
|
|
||||||
return '50'
|
|
||||||
case 85:
|
|
||||||
return '100'
|
|
||||||
case 116:
|
|
||||||
return '200'
|
|
||||||
case 160:
|
|
||||||
return '500'
|
|
||||||
case 200:
|
|
||||||
return '1K'
|
|
||||||
case 233:
|
|
||||||
return '2K'
|
|
||||||
case 281:
|
|
||||||
return '5K'
|
|
||||||
case 320:
|
|
||||||
return '10K'
|
|
||||||
case 348:
|
|
||||||
return '20K'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
interval: function (index) {
|
|
||||||
return labelsToShow.includes(index)
|
|
||||||
},
|
|
||||||
fontSize: 14,
|
|
||||||
color: '#999'
|
|
||||||
},
|
|
||||||
splitLine: {
|
|
||||||
show: true,
|
|
||||||
lineStyle: {
|
|
||||||
type: 'solid',
|
|
||||||
color: '#3A4348'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
axisLine: {
|
|
||||||
lineStyle: {
|
|
||||||
color: '#3A4348'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
type: 'value',
|
|
||||||
min: yMin,
|
|
||||||
max: yMax,
|
|
||||||
interval: 5,
|
|
||||||
|
|
||||||
axisLabel: {
|
|
||||||
fontSize: 14,
|
|
||||||
color: '#999'
|
|
||||||
},
|
|
||||||
splitLine: {
|
|
||||||
show: true,
|
|
||||||
lineStyle: {
|
|
||||||
type: 'solid',
|
|
||||||
color: '#3A4348'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
axisLine: {
|
|
||||||
lineStyle: {
|
|
||||||
color: '#3A4348'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
show: true,
|
|
||||||
top: 15,
|
|
||||||
data: [
|
|
||||||
{
|
|
||||||
name: 'Equalizer',
|
|
||||||
icon: 'circle',
|
|
||||||
textStyle: { color: lineColor }, // 单独设置颜色
|
|
||||||
itemStyle: {
|
|
||||||
color: lineColor, // 设置图标颜色
|
|
||||||
borderColor: lineColor // 如果需要边框
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Raw',
|
|
||||||
icon: 'circle',
|
|
||||||
textStyle: { color: '#ffffff' },
|
|
||||||
itemStyle: {
|
|
||||||
color: '#ffffff', // 设置图标颜色
|
|
||||||
borderColor: '#ffffff' // 如果需要边框
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Equalized',
|
|
||||||
icon: 'circle',
|
|
||||||
textStyle: { color: '#23d2fe' },
|
|
||||||
itemStyle: {
|
|
||||||
color: '#23d2fe', // 设置图标颜色
|
|
||||||
borderColor: '#23d2fe' // 如果需要边框
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
textStyle: {
|
|
||||||
fontSize: 13
|
|
||||||
}
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: 'Equalizer',
|
|
||||||
data: dataSet[1],
|
|
||||||
type: 'line',
|
|
||||||
showSymbol: false,
|
|
||||||
lineStyle: {
|
|
||||||
color: lineColor
|
|
||||||
},
|
|
||||||
areaStyle: {
|
|
||||||
opacity: 0.3,
|
|
||||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
|
||||||
{ offset: 0, color: '#578400' },
|
|
||||||
{
|
|
||||||
offset: 1,
|
|
||||||
color: '#578400'
|
|
||||||
}
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,314 +0,0 @@
|
|||||||
import axios from 'axios'
|
|
||||||
import { base64DecodedToString, base64Encoded, PEQAPI, setProperty, UPGRADEPEQ } from '@/api/common.js'
|
|
||||||
import { ref } from 'vue'
|
|
||||||
|
|
||||||
import {
|
|
||||||
AudioBean,
|
|
||||||
getChartOps,
|
|
||||||
getFilterType,
|
|
||||||
getSectionsMatrix,
|
|
||||||
visualizeResponse
|
|
||||||
} from '@/api/audio.js'
|
|
||||||
import * as echarts from 'echarts'
|
|
||||||
import { i18n } from '@/main.js'
|
|
||||||
import { ElMessageBox } from 'element-plus'
|
|
||||||
export const getPeqData = async () => {
|
|
||||||
const peqItems = ref([])
|
|
||||||
const peqSelect = ref(0)
|
|
||||||
const resp = await axios.get(PEQAPI)
|
|
||||||
const peqEnable = ref(0)
|
|
||||||
const msgCount = ref(0);
|
|
||||||
const data = JSON.parse(base64DecodedToString(resp.data));
|
|
||||||
|
|
||||||
console.log('peq 数据=', data);
|
|
||||||
if(data.peq.length > 0){
|
|
||||||
data.peq.forEach((item, index) => {
|
|
||||||
item['index'] = index
|
|
||||||
item['filters'] = JSON.parse(item.filters)
|
|
||||||
})
|
|
||||||
peqItems.value = data.peq
|
|
||||||
peqSelect.value = data.peqSelect
|
|
||||||
}
|
|
||||||
peqEnable.value = data.peqEnable
|
|
||||||
msgCount.value = data.msgCount
|
|
||||||
return {
|
|
||||||
peqItems,
|
|
||||||
peqSelect,
|
|
||||||
peqEnable,
|
|
||||||
msgCount
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function changePeq(val, peqItems) {
|
|
||||||
setProperty('peqSelect', val)
|
|
||||||
|
|
||||||
const selectedItem = peqItems.find((item) => item.index === val)
|
|
||||||
if (selectedItem) {
|
|
||||||
console.log('选中了:' + selectedItem.name + ' filters = ' + selectedItem.filters)
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
export const renderCharts = (peq, raw, changeParam) => {
|
|
||||||
const list = []
|
|
||||||
const fs = 48000
|
|
||||||
peq.filters.forEach((item) => {
|
|
||||||
const bean = new AudioBean(item.gain, item.fc, fs, getFilterType(item.type), false, item.q)
|
|
||||||
list.push(
|
|
||||||
getSectionsMatrix(
|
|
||||||
bean.getGain(),
|
|
||||||
bean.getFc(),
|
|
||||||
bean.getQ(),
|
|
||||||
bean.getType(),
|
|
||||||
bean.getBypass(),
|
|
||||||
bean.getFs()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
})
|
|
||||||
const dataSet = visualizeResponse(list, fs)
|
|
||||||
const ops = getChartOps(dataSet, 20, -20, '#FFED00')
|
|
||||||
|
|
||||||
// 统一获取DOM元素
|
|
||||||
const chartDom = document.getElementById('main')
|
|
||||||
|
|
||||||
// 尝试获取已存在的实例
|
|
||||||
let myChart = echarts.getInstanceByDom(chartDom)
|
|
||||||
|
|
||||||
// 如果实例不存在,则初始化
|
|
||||||
if (!myChart) {
|
|
||||||
myChart = echarts.init(chartDom)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changeParam && myChart) {
|
|
||||||
// 只有在changeParam为true且图表存在时才获取原始数据
|
|
||||||
raw = myChart.getOption().series[1].data
|
|
||||||
}
|
|
||||||
|
|
||||||
// 不再重新初始化,直接使用现有的myChart实例
|
|
||||||
myChart.clear()
|
|
||||||
|
|
||||||
if (raw) {
|
|
||||||
ops.series.push({
|
|
||||||
name: 'Raw',
|
|
||||||
data: raw,
|
|
||||||
type: 'line',
|
|
||||||
showSymbol: false,
|
|
||||||
lineStyle: {
|
|
||||||
color: '#ffffff'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const equalized_raw = dataSet[1].map((value, index) => value + raw[index])
|
|
||||||
ops.series.push({
|
|
||||||
name: 'Equalized',
|
|
||||||
data: equalized_raw,
|
|
||||||
type: 'line',
|
|
||||||
showSymbol: false,
|
|
||||||
lineStyle: {
|
|
||||||
color: '#23d2fe',
|
|
||||||
width: 6,
|
|
||||||
opacity: 0.7
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
myChart.setOption(ops, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 切换auto开关
|
|
||||||
* @param peq
|
|
||||||
*/
|
|
||||||
export const upgradeAutoPre = (peq, autoPre) => {
|
|
||||||
const filters = peq.filters.map((item) => ({
|
|
||||||
type: getFilterVal(item.type),
|
|
||||||
fc: item.fc,
|
|
||||||
gain: item.gain,
|
|
||||||
q: item.q
|
|
||||||
}))
|
|
||||||
const data = {
|
|
||||||
peqChange: {
|
|
||||||
name: peq.name,
|
|
||||||
filters: filters,
|
|
||||||
autoPre: autoPre ? 1 : 0,
|
|
||||||
preamp: peq.preamp,
|
|
||||||
canDel: peq.canDel
|
|
||||||
}
|
|
||||||
}
|
|
||||||
upgradePeq(data)
|
|
||||||
peq.autoPre = autoPre ? 1 : 0
|
|
||||||
}
|
|
||||||
|
|
||||||
//修改总增益
|
|
||||||
export const upgradePreamp = (peq, preamp) => {
|
|
||||||
const filters = peq.filters.map((item) => ({
|
|
||||||
type: getFilterVal(item.type),
|
|
||||||
fc: item.fc,
|
|
||||||
gain: item.gain,
|
|
||||||
q: item.q
|
|
||||||
}))
|
|
||||||
const data = {
|
|
||||||
peqChange: {
|
|
||||||
name: peq.name,
|
|
||||||
filters: filters,
|
|
||||||
autoPre: peq.autoPre,
|
|
||||||
preamp: preamp,
|
|
||||||
canDel: peq.canDel
|
|
||||||
}
|
|
||||||
}
|
|
||||||
upgradePeq(data)
|
|
||||||
|
|
||||||
peq.preamp = preamp
|
|
||||||
}
|
|
||||||
|
|
||||||
export const upgradeEdit = (peq) => {
|
|
||||||
const filters = peq.filters.map((item) => ({
|
|
||||||
type: getFilterVal(item.type),
|
|
||||||
fc: item.fc,
|
|
||||||
gain: item.gain,
|
|
||||||
q: item.q
|
|
||||||
}))
|
|
||||||
const data = {
|
|
||||||
peqChange: {
|
|
||||||
name: peq.name,
|
|
||||||
filters: filters,
|
|
||||||
autoPre: peq.autoPre,
|
|
||||||
preamp: peq.preamp,
|
|
||||||
canDel: peq.canDel
|
|
||||||
}
|
|
||||||
}
|
|
||||||
upgradePeq(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
//这里有个问题,当接口超时时,由于代码是同步,所以会一直阻塞等待
|
|
||||||
export const upgradePeq = async (peq) => {
|
|
||||||
await axios.post(
|
|
||||||
UPGRADEPEQ,
|
|
||||||
{ json: base64Encoded(JSON.stringify(peq)) },
|
|
||||||
{ headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' } }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getFilterVal = (filterName) => {
|
|
||||||
let result = -1
|
|
||||||
if (filterName === 'HIGH_PASS' || filterName === 'HPF') {
|
|
||||||
result = 1
|
|
||||||
} else if (filterName === 'BAND_PASS' || filterName === 'BPF') {
|
|
||||||
result = 2
|
|
||||||
} else if (filterName === 'NOTCH') {
|
|
||||||
result = 3
|
|
||||||
} else if (filterName === 'PEAKING' || filterName === 'PEAK') {
|
|
||||||
result = 4
|
|
||||||
} else if (filterName === 'LOW_SHELF' || filterName === 'LSHELF') {
|
|
||||||
result = 5
|
|
||||||
} else if (filterName === 'HIGH_SHELF' || filterName === 'HSHELF') {
|
|
||||||
result = 6
|
|
||||||
} else if (filterName === 'ALL_PASS' || filterName === 'APF') {
|
|
||||||
result = 7
|
|
||||||
} else if (filterName === 'LOW_PASS' || filterName === 'LPF') {
|
|
||||||
result = 0
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 改变滤波器的属性(频率,gain,q, 类型)
|
|
||||||
* @param currentFilter 当前选中的滤波器
|
|
||||||
* @param val 值
|
|
||||||
*/
|
|
||||||
export const changeFilterVal = (currentFilter, val, name, peq) => {
|
|
||||||
//currentFilter !== undefined 表示当前有某一个滤波器被选中,才需要更新下面的值
|
|
||||||
if (currentFilter !== undefined) {
|
|
||||||
if (name === 'freq') {
|
|
||||||
currentFilter.fc = val
|
|
||||||
} else if (name === 'gain') {
|
|
||||||
currentFilter.gain = val
|
|
||||||
} else if (name === 'q') {
|
|
||||||
currentFilter.q = val
|
|
||||||
} else if (name === 'type') {
|
|
||||||
currentFilter.type = val
|
|
||||||
}
|
|
||||||
|
|
||||||
//调用接口,更新peq
|
|
||||||
//需要将滤波器类型转换为数字,因为是引用类型,所以这里还需要遍历filters,声明新的filters,将值传过去,不能直接用peq.filters
|
|
||||||
const filters = peq.filters.map((item) => ({
|
|
||||||
type: getFilterVal(item.type),
|
|
||||||
fc: item.fc,
|
|
||||||
gain: item.gain,
|
|
||||||
q: item.q
|
|
||||||
}))
|
|
||||||
|
|
||||||
const data = {
|
|
||||||
peqChange: {
|
|
||||||
name: peq.name,
|
|
||||||
filters: filters,
|
|
||||||
autoPre: peq.autoPre,
|
|
||||||
preamp: peq.preamp,
|
|
||||||
canDel: peq.canDel
|
|
||||||
}
|
|
||||||
}
|
|
||||||
upgradePeq(data)
|
|
||||||
renderCharts(peq)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 渲染添加耳机型号窗口数据
|
|
||||||
*/
|
|
||||||
export const renderAddHeadPhone = () => {
|
|
||||||
const menus = [
|
|
||||||
{ value: 'Brands', label: 'Brands' },
|
|
||||||
{ value: 'Models', label: 'Models' },
|
|
||||||
{ value: 'Target', label: 'Target' }
|
|
||||||
]
|
|
||||||
const selectedMenu = ref('Brands')
|
|
||||||
const targetList = ref([
|
|
||||||
{ name: 'Harman over-ear 2018', bassBoost: { fc: 105, q: 0.7, gain: 6 } , ear: 'over'},
|
|
||||||
{ name: 'HMS II.3 Harman over-ear 2018', bassBoost: { fc: 105, q: 0.7, gain: 6 }, ear: 'over'},
|
|
||||||
{ name: 'crinacle EARS + 711 Harman over-ear 2018', bassBoost: { fc: 105, q: 0.7, gain: 6 } , ear: 'over'},
|
|
||||||
{ name: 'Harman in-ear 2019', bassBoost: { fc: 105, q: 0.7, gain: 9.5 } ,ear: 'in'},
|
|
||||||
{ name: 'AutoEq in-ear', bassBoost: { fc: 105, q: 0.7, gain: 8 }, ear: 'in'},
|
|
||||||
{ name: 'HMS II.3 AutoEq in-ear', bassBoost: { fc: 105, q: 0.7, gain: 8 } ,ear: 'in'},
|
|
||||||
{ name: 'HMS II.3 Harman in-ear 2019', bassBoost: { fc: 105, q: 0.7, gain: 9.5 } ,ear: 'in'},
|
|
||||||
{ name: 'Diffuse Field 5128 (-1 dB/oct)', bassBoost: { fc: 105, q: 0.7, gain: 0 }, ear: 'over'},
|
|
||||||
{ name: 'LMG 5128 0.6 without bass', bassBoost: { fc: 105, q: 0.7, gain: 6 } ,ear: 'over'},
|
|
||||||
{ name: 'JM-1 with Harman filters', bassBoost: { fc: 105, q: 0.7, gain: 6.5 } ,ear: 'all'},
|
|
||||||
{ name: 'oratory1990 in-ear', bassBoost: { fc: 105, q: 0.7, gain: 9.5 } ,ear: 'in'},
|
|
||||||
{ name: 'oratory1990 over-ear', bassBoost: { fc: 105, q: 0.7, gain: 6 } ,ear: 'over'},
|
|
||||||
{ name: 'Harman over-ear 2013', bassBoost: { fc: 105, q: 0.7, gain: 6 } ,ear: 'over'},
|
|
||||||
{ name: 'Flat', bassBoost: { fc: 105, q: 0.7, gain: 0 } ,ear: 'all'}
|
|
||||||
]);
|
|
||||||
return { menus, selectedMenu, targetList }
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getCurve = async (brand, name, target) =>{
|
|
||||||
const resp = await axios.get('//api.luxsin.com.cn/audio/getCurve?brand='+encodeURIComponent(brand)+'&name='+encodeURIComponent(name)+'&target='+encodeURIComponent(target));
|
|
||||||
const data = JSON.parse(base64DecodedToString(resp.data));
|
|
||||||
|
|
||||||
if(data.hasOwnProperty('parametric_eq')) {
|
|
||||||
return data.parametric_eq;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getModelCurve = async (brand, name) => {
|
|
||||||
const resp = await axios.get(
|
|
||||||
'//api.luxsin.com.cn/audio/modelCurve?brand=' +
|
|
||||||
encodeURIComponent(brand) +
|
|
||||||
'&name=' +
|
|
||||||
encodeURIComponent(name)
|
|
||||||
)
|
|
||||||
const data = JSON.parse(base64DecodedToString(resp.data))
|
|
||||||
console.log('型号的原始数据:', data)
|
|
||||||
if (data.hasOwnProperty('fr')) {
|
|
||||||
return data.fr
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
export const msg = (context) => {
|
|
||||||
ElMessageBox.alert(context, i18n.global.t('prompt.prompt'), {
|
|
||||||
confirmButtonText: i18n.global.t('prompt.confirm')
|
|
||||||
})
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -7,6 +7,7 @@
|
|||||||
============================================================ */
|
============================================================ */
|
||||||
import { useDevice } from "@/contexts/DeviceContext";
|
import { useDevice } from "@/contexts/DeviceContext";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
import BottomNav from "@/components/BottomNav";
|
||||||
import { ChevronLeft } from "lucide-react";
|
import { ChevronLeft } from "lucide-react";
|
||||||
import { useLocation } from "wouter";
|
import { useLocation } from "wouter";
|
||||||
|
|
||||||
@@ -138,6 +139,7 @@ export default function IOPage() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<BottomNav />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
============================================================ */
|
============================================================ */
|
||||||
import { useDevice } from "@/contexts/DeviceContext";
|
import { useDevice } from "@/contexts/DeviceContext";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
import BottomNav from "@/components/BottomNav";
|
||||||
import { Check, ChevronLeft } from "lucide-react";
|
import { Check, ChevronLeft } from "lucide-react";
|
||||||
import { useLocation } from "wouter";
|
import { useLocation } from "wouter";
|
||||||
|
|
||||||
@@ -83,6 +84,7 @@ export default function VUPage() {
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
<BottomNav />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user