EQ频响曲线绘制和DRC特性曲线绘制

2023-11-07

目录

1 EQ 系数计算和频响曲线绘制

1.1 基本流程

1.2 EQ参数输入

1.3 滤波器系数计算

1.4 频率响应计算

1.5 曲线绘制

2.DRC特性曲线绘制

2.1 基本流程

2.2 参数输入

2.3 增益计算

2.4 静态特性曲线绘制

3 Android 工程实现


1 EQ 系数计算和频响曲线绘制

1.1 基本流程

整个计算和绘制流程如下

1.2 EQ参数输入

Matlab 和Android两个界面输入如下所示,Android 与Matlab保持一致

Matlab 界面输入

Android界面输入

1.3 滤波器系数计算

根据输入的EQ参数Gain(dB),Fc(Hz),BW(Hz),Type(滤波器类型:peak、lowshelf、highshelf、lowpass、highpass、bandpass、notch、allpass(0-7)),bypass,以及采样频率fs,可计算滤波器系数sos(b0,b1,b2,a0,a1,a2)。

Matlab 和Java 的调用和实现分别如下图所示

Matlab 调用

pre_eq_sos = biquad_design(2 * fc / fs, gain, fc ./ bw, type + bypass * 10);

(其中fs为采样率)

Java调用

Coeff coeff = BiquadDesign.getSectionsMatrix(gain, fc, bw, type, bypass, fs);
直接输入参数,将原matlab内调用时的相关计算整合到实现中

Matlab滤波器系数计算实现

function sos = biquad_design(w, g, q, bqtype)

%BIQUAD_DESIGN Biquad design.

%

% INPUTS

%

%   w       Normalized frequencies. 0 for DC and 1 for Nyquist frequency.

%   g       Gains in dB at center frequencies

%   q       Quality factors.

%   bqtype  Biquad types.

%                   0: peak

%                   1: lowshelf

%                   2: highshelf

%                   3: lowpass

%                   4: highpass

%                   5: bandpass

%                   6: notch

%                   7: allpass

%           otherwise: bypass

%

% OUTPUTS

%

%   sos     Output filter coefficients in SOS format.

validateattributes(w, {'double'}, {'vector', '>=', 0, '<=', 1})

validateattributes(g, {'double'}, {'vector'})

validateattributes(q, {'double'}, {'vector', '>', 0})

validateattributes(bqtype, {'double'}, {'vector'})

if ~isequal(size(w), size(g), size(q), size(bqtype))

    error('All input arguments should have same dimensions.')

end

n = numel(w);

sos = zeros(n, 6);

for i = 1 : n

    A = 10 .^ (g(i) / 40);

    sqrt_A = sqrt(A);

    sin_w = sin(pi * w(i));

    cos_w = cos(pi * w(i));

    alpha = sin_w / (2 * q(i));

    switch bqtype(i)

    case 0 % peak

        b0 =  1 + alpha*A;

        b1 = -2 * cos_w;

        b2 =  1 - alpha*A;

        a0 =  1 + alpha/A;

        a1 = b1;

        a2 =  1 - alpha/A;

    case 1 % lowshelf

        b0 =    A*((A+1) - (A-1)*cos_w + 2*sqrt_A*alpha);

        b1 =  2*A*((A-1) - (A+1)*cos_w);

        b2 =    A*((A+1) - (A-1)*cos_w - 2*sqrt_A*alpha);

        a0 =       (A+1) + (A-1)*cos_w + 2*sqrt_A*alpha;

        a1 =   -2*((A-1) + (A+1)*cos_w);

        a2 =       (A+1) + (A-1)*cos_w - 2*sqrt_A*alpha;

    case 2 % highshelf

        b0 =    A*((A+1) + (A-1)*cos_w + 2*sqrt_A*alpha);

        b1 = -2*A*((A-1) + (A+1)*cos_w);

        b2 =    A*((A+1) + (A-1)*cos_w - 2*sqrt_A*alpha);

        a0 =       (A+1) - (A-1)*cos_w + 2*sqrt_A*alpha;

        a1 =    2*((A-1) - (A+1)*cos_w);

        a2 =       (A+1) - (A-1)*cos_w - 2*sqrt_A*alpha;

    case 3 % lowpass

        b0 = (1 - cos_w) / 2;

        b1 =  1 - cos_w;

        b2 = b0;

        a0 =  1 + alpha;

        a1 = -2 * cos_w;

        a2 =  1 - alpha;

    case 4 % highpass

        b0 =  (1 + cos_w) / 2;

        b1 = -(1 + cos_w);

        b2 = b0;

        a0 =   1 + alpha;

        a1 =  -2 * cos_w;

        a2 =   1 - alpha;

    case 5 % bandpass

        b0 =  alpha;

        b1 =  0;

        b2 = -alpha;

        a0 =  1 + alpha;

        a1 = -2 * cos_w;

        a2 =  1 - alpha;

    case 6 % notch

        b0 =  1;

        b1 = -2 * cos_w;

        b2 =  1;

        a0 =  1 + alpha;

        a1 = -2 * cos_w;

        a2 =  1 - alpha;

    case 7 % allpass

        b0 =  1 - alpha;

        b1 = -2 * cos_w;

        b2 =  1 + alpha;

        a0 = b2;

        a1 = b1;

        a2 = b0;

    otherwise % bypass

        b0 = 1;

        b1 = 0;

        b2 = 0;

        a0 = 1;

        a1 = 0;

        a2 = 0;

    end

    sos(i, 1) = b0 / a0;

    sos(i, 2) = b1 / a0;

    sos(i, 3) = b2 / a0;

    sos(i, 4) = 1;

    sos(i, 5) = a1 / a0;

    sos(i, 6) = a2 / a0;

end

end

Java滤波器系数计算实现

public class BiquadDesign {
   
public static final int

TYPE_PEAK = 0;
   
public static final int TYPE_LOWSHELF = 1;
   
public static final int TYPE_HIGHSHELF = 2;
   
public static final int

 TYPE_LOWPASS = 3;
   
public static final int TYPE_HIGHPASS = 4;
   
public static final int TYPE_BANDPASS = 5;
   
public static final int

TYPE_NOTCH = 6;
   
public static final int

 TYPE_ALLPASS = 7;

   
/**
     * @param
gain   GaindB):范围:-15~15,精度:1
     * @param
fc     FcHz):范围:20~20000,精度:1
     * @param
bw     BWHz):范围:10~20000,精度:1
     * @param
type   Typepeaklowshelfhighshelflowpasshighpassbandpassnotchallpass0-7
     * @param bypass bypass :选中1,未选中0
     * @param fs     采样频率
     * @return 截面矩阵系数sos
     */
   
public static Coeff getSectionsMatrix(int gain, int fc, int bw, int type, boolean bypass, int fs) {

       
double w = (double) 2 * fc / fs;
       
double q = (double) fc / bw;
       
int bypassStatus = bypass?1:0;
       
int bqtype = type + (int)bypassStatus * 10;
       
double sA = Math.pow(10, (double) gain / 40);
       
double sqrt_sA = sqrt(sA);
       
double sin_w = Math.sin(PI * w);
       
double cos_w = Math.cos(PI * w);
       
double alpha = sin_w / (2 * q);
       
double b0;
       
double b1;
       
double b2;
       
double a0;
       
double a1;
       
double 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;
           
default:
               
b0 = 1;
               
b1 = 0;
               
b2 = 0;
               
a0 = 1;
               
a1 = 0;
               
a2 = 0;
               
break;
        }

       
Coeff 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;
    }
}

1.4 频率响应计算

频响是在电子学上用来描述一台仪器对于不同频率的信号的处理能力的差异。同失真一样,这也是一个非常重要的参数指标。频响也称频响曲线,是指增益随频率的变化曲线。任何音响设备或载体(记录声音信号的物体)都有其频响曲线。理想的频响曲线应当是平直的,声音信号通过后不产生失真。

计算数字滤波器的频率响应,根据滤波器系数(传递函数系数),角频率,可返回频率响应向量H。基本计算公式如下所示。

其中b(0),b(1)…b(m),a(0),a(1)…a(n)为滤波器系数,w为角频率。程序的核心就是对该公式的实现。

Matlab 实现

Matlab 通过freqz 函数进行频率响应的计算,主要也是根据上述公式进行计算。其调用方式包括

  [H,W] = freqz(SOS,N) returns the N-point complex frequency response

    given the second order sections matrix SOS. SOS is a Kx6 matrix, where

    the number of sections, K, must be greater than or equal to 2. Each row

    of SOS corresponds to the coefficients of a second order filter. From

    the transfer function displayed above, the ith row of the SOS matrix

    corresponds to [bi(1) bi(2) bi(3) ai(1) ai(2) ai(3)].

    [H,W] = freqz(D,N) returns the N-point complex frequency response given

    the digital filter, D. You design a digital filter, D, by calling the

    designfilt function.

    In all cases, the frequency response is evaluated at N points equally

    spaced around the upper half of the unit circle. If N isn't specified,

    it defaults to 512.

    [H,W] = freqz(...,N,'whole') uses N points around the whole unit

    circle.

    H = freqz(...,W) returns the frequency response at frequencies

    designated in vector W, in radians/sample (normally between 0 and pi).

    W must be a vector with at least two elements.

    [H,F] = freqz(...,N,Fs) and [H,F] = freqz(...,N,'whole',Fs) return

    frequency vector F (in Hz), where Fs is the sampling frequency (in Hz).

    H = freqz(...,F,Fs) returns the complex frequency response at the

    frequencies designated in vector F (in Hz), where Fs is the sampling

    frequency (in Hz).

    freqz(...) with no output arguments plots the magnitude and

    unwrapped phase of the filter in the current figure window.

在本算法中其调用公式如下

f = logspace(log10(20), log10(20e3), 200); //频率20Hz-20kHz 按对数划分为200个点

H = db(abs(freqz(sos, f, fs))); //sos表示2阶截面矩阵,对应滤波器系数[b0,b1,b2,a0,a1,a2],fs为采样频率

Java实现

(1) 根据系数计算某组滤波器下的频响

     /* 计算某组滤波器下的频响

*@param coeff 传递函数的系数 b0,b1,b2,a0,a1,a2

     * @param w 角频率

     * @return   频率响应 (复数类型)

     */

 public static Complex getFreqw(Coeff coeff,double w){
   
Complex complex = new Complex(cos(w),-sin(w));  //欧拉公式e^(-jw)=cos(w)-jsin(w)
   
Complex b2 = (complex.mul(complex)).mul(coeff.getB2());  //b(2)*e^(-j2w)
   
Complex b1 = complex.mul(coeff.getB1());          //b(1)*e^(-jw)
   
Complex hup =b2.add(b1).add(coeff.getB0());       //b(0)+b(1)*e^(-jw)+b(2)*e^(-j2w)
   
Complex a2 = (complex.mul(complex)).mul(coeff.getA2());
   
Complex a1 = complex.mul(coeff.getA1());
   
Complex hdown =a2.add(a1).add(coeff.getA0());
   
Complex res = hup.div(hdown);
  
// Log.d("tzw", "getFreqw: "+res.getReal()+"+"+res.getImage()+"i");
   
return res;
}

注: 欧拉公式e-jw=cos(w)-jsin(w)

(2)多组滤波器下的频响

多组滤波器作用下的频响为各个滤波器频响相乘

/**
 *
计算多组滤波器作用下的频响
 * @param coeffList 系数组
 * @param w 频率
 * @return 频响
 */
public static Complex getFreqw(List<Coeff> coeffList,double w){
   
Complex h = getFreqw(coeffList.get(0),w);
   
for(int i=1;i<coeffList.size();i++){
        h= h.mul(getFreqw(coeffList.get(i),w));
    }
   
return h;
}

 

(3)幅值、相位计算

之后可根据此计算对应的幅值和相位,如下

/**
 *
计算幅值
 * @param complex 频率响应
 * @return 幅值
 */
public static double getAmplitude(Complex complex){
   
return Math.sqrt(Math.pow(complex.getReal(),2)+Math.pow(complex.getImage(),2));
}


/**
 *
计算相位
 * @param complex  频率响应
 * @return 相位(-pi/2~pi/2
 */
public static double getPhase(Complex complex){
   
return Math.atan(complex.getImage()/complex.getReal());
}

(4)计算一组频率点下的频响幅值(单位:dB),最终调用

/**
 *
计算n 个点的频率响应
 * @param coeff 系数
 * @param fs 采样频率
 * @param 频率数组
 * @return n个点的频率响应 dB
 */
public static double[] getFreqzn(Coeff coeff,int fs,double[] f){
   
int n = f.length;
   
double[] h new double[n];
   
for(int i=0;i<n;i++){
       
double w = 2*Math.PI*(f[i])/fs;
       
//  h[i-1]= getFreqz(coeff,z);
       
Complex complex = getFreqw(coeff,w);
       
// h[i-1] = getAmplitude(complex); //幅值
        h[i] = 20*Math.log10(abs(getAmplitude(complex))); //分贝(dB
    }
   
return h;
}


/**
 *
计算多个滤波器作用下n个点的频率响应
 * @param coeffList 滤波器系数组
 * @param fs 采样频率
 * @param f 频率数组
 * @return n-1个点的频率响应 dB
 */
public static double[] getFreqzn(List<Coeff> coeffList,int fs,double[] f){
   
int n = f.length;
   
double[] h new double[n];
   
for(int i=0;i<n;i++){
       
double w = 2*Math.PI*(f[i])/fs;;
       
//  h[i-1]= getFreqz(coeff,z);
       
Complex complex = getFreqw(coeffList,w);
       
// h[i-1] = getAmplitude(complex); //幅值
        h[i] = 20*Math.log10(abs(getAmplitude(complex))); //分贝(dB
    }
   
return h;
}

 

1.5 曲线绘制

根据2.2界面输入的数据和上述计算,最终进行曲线绘制。Matlab 和Android绘制的曲线如下

Matlab 绘制

Android 绘制

其中

X轴:频率(Hz):20Hz-20kHz,按照对数划分。

Y轴:频响幅度(dB),彩色线band0-band4表示单个滤波器的频响曲线,黑色线Overall表示所有滤波器作用下的频响曲线。

Matlab 实现

X轴数据

f = logspace(log10(20), log10(20e3), 200); //频率20Hz-20kHz 按对数划分为200个点

Y轴数据

H = db(abs(freqz(sos, f, fs)));

绘制 (采用半对数绘制)

semilogx(f, H1, '--', 'Color', colors(i, :))

semilogx(X,Y)表示半对数绘制,即在 x 轴上使用以 10 为底的对数刻度、在 y 轴上使用线性刻度来绘制 x 和 y 坐标。

最终X轴显示数据:log10(f)

    Y轴显示数据: H

Android 实现

X轴数据

int n =200;

double startF = 20;

double endF = 20000;

double logStep = (Math.log10(endF)-Math.log10(startF))/n;

double[] f = new double[n];

double step = Math.pow(10,logStep);

for(int i=0;i<200;i++){

   f[i]= startF*Math.pow(step,i); //按对数划分为200个点

}
Y轴数据

double[] h = FrequencyResponse.getFreqzn(coeff,fs,f);

//具体实现见上文Java实现getFreqzn函数

绘制(采用半对数绘制)

double[] semilogf = new double[n];

for(int i=0;i<200;i++){

  semilogf[i]= Math.log10(f[i]);  //半对数绘制时,对f取以10为底的对数

 }

最终X轴显示数据:semilogf

    Y轴显示数据: h

2.DRC特性曲线绘制

DRC,全名Dynamic Range Control,主要用于调整输入语音的动态范围。应用场景可以有如下的几种形式

(1)类似于AGC的功能,对输入的忽大忽小语音进行动态拉伸,使语音听起来平稳。(2)作为小信号滤除器,滤除低于某一阈值的信号。一般用来滤除噪声,避免噪声在后续模块AGC中被放大。

DRC的原理就是通过设计一条曲线,将输入语音幅度x1通过曲线进行映射得到另一语音幅度值x2。然后计算两者之间的差值得到增益值g,然后根据设置的attacktime和releasetime进行增益平滑以及计算make-up增益,最后再应用到语音得到处理后的语音。

2.1 基本流程

2.2 参数输入

Matlab 和Android两个界面输入如下所示,Android 与Matlab保持一致。主要输入参数Threshold(dB),

Ratio,KneeWidth,Attack time(ms),Release time(ms),Makeup gain(dB)。

Matlab 界面输入           

 

Android界面输入

2.3 增益计算

增益的计算参考论文“Giannoulis, Dimitrios, Michael Massberg, and Joshua D. Reiss.  "Digital dynamic range compressor design - A tutorial and analysis."  Journal of the Audio Engineering Society 60.6 (2012): 399-408”

实现代码

Matlab 实现

function g = compute_gain(u, T, R, W)
%
% u - Input level
% T - threshold in dB
% R - ratio
% W - knee width
%
% References
%
% Giannoulis, Dimitrios, Michael Massberg, and Joshua D. Reiss.
%    "Digital dynamic range compressor design - A tutorial and analysis."
%    Journal of the Audio Engineering Society 60.6 (2012): 399-408.

if nargout > 0
    g = compute_gain_core(u, T, R, W);
else
    N = 60;
    u = -N : .1 : 0;
    y = u + compute_gain_core(u, T, R, W)
    Ty = T + compute_gain_core(T, T, R, W)

    plot(u, u, '--', 'Color', [.8 .8 .8])
    hold on
    grid on
    plot(u, y, 'black', 'LineWidth', 2)
    plot(T, Ty, 'ok', 'MarkerSize', 8, ...
        'MarkerFaceColor', 'white', ...
        'MarkerEdgeColor', 'black')
    axis([-N 0 -N 0])
    axis square
    xlabel('Input (dB)')
    ylabel('Output (dB)')
    title('Static Characteristic Curve')
    hold off
end
end

function g = compute_gain_core(u, T, R, W)

W2 = W / 2;
D = u - T;
S = 1/R - 1;
cond = abs(D) < W2;

g1 = S * (D + W2).^2 / (2*W);
g2 = min(D * S, 0);

if W
    g = g1 .* cond + g2 .* ~cond
else
    g = g2;
end
end

Java实现

/**
 * @param
u 数组,默认传入空数组
 * @param t ThresholddB):范围:-80~0,精度:1
 * @param
r Ratio0~100,精度:1
 * @param
w Knee WidthdB):0~80,精度:1
 * @return
 */

public static double[] computeGain(double[] u, int t, int r, int w) {
   
int ulength = u.length;
   
double[] d = new double[ulength];
   
int[] cond = new int[ulength];
   
double[] g1 = new double[ulength];
   
double[] g2 = new double[ulength];
   
double[] g = new double[ulength];
   
int w2 = w / 2;
   
int s = 1 / r - 1;
   
for (int i = 0; i < ulength; i++) {
       
d[i] = u[i] - t;
       
cond[i] = Math.abs(d[i]) < w2 ? 1 : 0;
       
g1[i] = s * Math.pow(d[i] + w2, 2) / (2 * w);
       
g2[i] = Math.min(d[i] * s, 0);
       
if (w != 0) {
           
if(cond[i]==1){
               
g[i] = g1[i];
            }
else{
               
g[i] = g2[i];
            }
          
// g[i] = g1[i] * cond[i] + g2[i] * (~cond[i]);
       
} else {
           
g[i] = g2[i];
        }
    }

     
return g;
}

增益计算调用

Matlab调用

%输入增益

N = 60;

u = -N : .1 : 0;

%计算y

y = u + compute_gain_core(u, T, R, W)

%计算Ty

    Ty = T + compute_gain_core(T, T, R, W)

Java调用

//输入增益

double[] u = new double[601];
for (int i = 0; i < 601; i++) {
   
u[i] = -60 + 0.1 * i;
}

//计算y

double[] g = CompressorUtil.computeGain(u, t, r, w);
double[] y = new double[u.length];
for (int i = 0; i < g.length; i++) {
   
y[i] = u[i] + g[i];
}

//计算Ty

double[] tArray = {t};
double[] tgArray = CompressorUtil.computeGain(tArray, t, r, w);
double ty = t + tgArray[0];

2.4 静态特性曲线绘制

根据上述计算的增益数据u,y,Ty可进行静态特性曲线的绘制,Matlab 和Android绘制的曲线如下

下图中输入数据Threshold(dB):-20,Ratio:100,KneeWidth(dB):30;通过增益计算求得u,y,ty。

Matlab 绘制

虚线数据:(u,u)

黑色线(特性曲线),数据(u,y),

白色空心拐点,数据(t,ty),t为Threshold

Android 绘制

黄线数据:(u,u)

黑色线(特性曲线),数据(u,y),

红色拐点,数据(t,ty),t为Threshold

3 Android 工程实现

具体Android工程实现参考:​​​​​​​​​​GitHub - tongziwei/EQ: An EQ demo for computing coeffs of transfer function and drawing frequency response characteristic curve.https://github.com/tongziwei/EQ.git

工程主界面

EQ1 频响曲线绘制

 可通过直接输入f,Q,Gain,fs,选择滤波器类型(三种滤波器LowShelf,PeakShelf,HighShelf)计算对应的滤波器系数,并绘制频响曲线图。

EQ2 频响曲线绘制

  可通过直接输入Gain,fc,Bw, 采样率fs,选择滤波器类型(8种滤波器LowShelf,PeakShelf,HighShelf)计算对应的滤波器系数,并绘制频响曲线图。具体实现参考上文EQ系数计算和频响曲线绘制。

DRC特性曲线绘制

  通过输入Threshold,Ratio,KneeWidth,计算增益,绘制特性曲线图,具体实现参考上文DRC特性曲线绘制。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

EQ频响曲线绘制和DRC特性曲线绘制 的相关文章

  • 在 Jetpack Compose 中启动动画矢量 Drawable

    我有一个动画矢量可绘制R drawable my anim 我想在 Jetpack Compose 中展示并开始 可绘制对象显示 渲染正确 但动画未启动 这是撰写视图 Composable fun SplashView Surface mo
  • 带有自定义阵列适配器的微调器不允许选择项目

    我使用自定义阵列适配器作为微调器 但是 当在下拉列表中选择一个项目时 下拉列表保留在那里 并且微调器不会更新 这是错误行为 与使用带有字符串的通用数组适配器相比 这是自定义类 我错过了什么吗 谢谢 public class Calendar
  • 无法理解 Java 地图条目集

    我正在看一个 java 刽子手游戏 https github com leleah EvilHangman blob master EvilHangman java https github com leleah EvilHangman b
  • ROOM迁移过程中如何处理索引信息

    CODE Entity tableName UserRepo indices Index value id unique true public class GitHubRepo PrimaryKey autoGenerate true p
  • 检查 Android 手机上的方向

    如何查看Android手机是横屏还是竖屏 当前配置用于确定要检索的资源 可从资源中获取Configuration object getResources getConfiguration orientation 您可以通过查看其值来检查方向
  • 反思 Groovy 脚本中声明的函数

    有没有一种方法可以获取 Groovy 脚本中声明的函数的反射数据 该脚本已通过GroovyShell目的 具体来说 我想枚举脚本中的函数并访问附加到它们的注释 Put this到 Groovy 脚本的最后一行 它将作为脚本的返回值 a la
  • 如何在 JFreeChart TimeSeries 图表上显示降雨指数和温度?

    目前 我的 TimeSeries 图表每 2 秒显示一个位置的温度 现在 如果我想每2秒显示一次降雨指数和温度 我该如何实现呢 这是我的代码 import testWeatherService TestWeatherTimeLapseSer
  • 调节麦克风录音音量

    我们正在尝试调整录音时的音量级别 麦克风似乎非常敏感 会接收到很多静电 我们查看了 setVolumeControlStream 但找不到传入其中来控制麦克风的流 将您的音频源设置为 MIC using MediaRecorder Audi
  • 在 Matlab 中保存 Kinect 深度图像?

    通过使用 Kinect 我可以获得深度图像 其中每个深度图像像素存储相机和物体之间的距离 以毫米为单位 现在我想保存它们以便以后使用 最好的推荐是什么 我正在考虑将深度图像保存为图像 jpg png等 然而 该值通常是从50毫米到10000
  • 将 Long 转换为 DateTime 从 C# 日期到 Java 日期

    我一直尝试用Java读取二进制文件 而二进制文件是用C 编写的 其中一些数据包含日期时间数据 当 DateTime 数据写入文件 以二进制形式 时 它使用DateTime ToBinary on C 为了读取 DateTime 数据 它将首
  • 下载后从谷歌照片库检索图像

    我正在发起从图库中获取照片的意图 当我在图库中使用 Nexus 谷歌照片应用程序时 一切正常 但如果图像不在手机上 在 Google Photos 在线服务上 它会为我下载 选择图像后 我将图像发送到另一个活动进行裁剪 但在下载的情况下 发
  • Android中webview的截图方法

    我在 webview 中的 html5 canvas 上画了一些线 并尝试使用下面的代码截取 webview 的屏幕截图 WebView webView WebView findViewById R id webview webView s
  • 运行 Jar 文件时出现问题

    我已将 java 项目编译成 Jar 文件 但运行它时遇到问题 当我跑步时 java jar myJar jar 我收到以下错误 Could not find the main class myClass 类文件不在 jar 的根目录中 因
  • Keycloak - 自定义 SPI 未出现在列表中

    我为我的 keycloak 服务器制作了一个自定义 SPI 现在我必须在管理控制台上配置它 我将 SPI 添加为模块 并手动安装 因此我将其放在 module package name main 中 并包含 module xml 我还将其放
  • java迭代器内部是如何工作的? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我有一个员工列表 List
  • 为什么Android的ImageReader类这么慢?

    我尝试了适用于 Android 3 4 1 的全新 OpenCVJavaCamera2View但它太慢了 仅显示相机视图约 15 fps 当我尝试较旧的JavaCameraView相反 它给了我很好的结果 30fps 这是我相机的极限 我想
  • 无法运行我的应用程序,要求选择 Android SDK

    今天我已经安装了Android Studio 金丝雀 1 现在我无法运行我的应用程序 将出现以下对话框 我已经通过 文件 gt 项目结构 gt Android SDK 位置 设置了正确的 SDK 位置 期待您的帮助来解决这个问题 警告对话框
  • 无法将 admob 与 firebase iOS/Android 项目链接

    我有两个帐户 A 和 B A 是在 Firebase 上托管 iOS Android unity 手机游戏的主帐户 B 用于将 admob 集成到 iOS Android 手机游戏中 我在尝试将 admob 分析链接到 Firebase 项
  • java8 Collectors.toMap() 限制?

    我正在尝试使用java8Collectors toMap on a Stream of ZipEntry 这可能不是最好的想法 因为在处理过程中可能会发生异常 但我想这应该是可能的 我现在收到一个我不明白的编译错误 我猜是类型推理引擎 这是
  • Jackson 将单个项目反序列化到列表中

    我正在尝试使用一项服务 该服务为我提供了一个带有数组字段的实体 id 23233 items name item 1 name item 2 但是 当数组包含单个项目时 将返回该项目本身 而不是包含一个元素的数组 id 43567 item

随机推荐

  • 将文件间的编译依存关系降至最低——条款31

    假设你对C 程序的某个class实现文件做了些轻微修改 注意 修改的不是class接口 而是实现 而且只改private成分 然后重新建置这个程序 并预计只花数秒就好 毕竟只有一个class被修改 你按下 Build 按钮或键入make 或
  • 西门子200SMART(六)数据块

    数据块中的数据页可以插入 编辑 删除 查询 和之前讨论的程序块 符号快以及状态图标基本具备一样的功能 数据块最主要点作用就是对地址和数据赋值 如下图 这里需要注意点是 这里的赋值和之前我们说过的状态图表中的强制是有区别的 强制顾名思义不管你
  • 【Pandas学习】读、存excel数据

    目录 一 读数据 二 将df存为excel 1 pandas DataFrame to csv 函数语法 2 利用 import os 获取保存路径 3 产生新的数据 添加至上述csv文件中已有数据的后面 4 多sheet 指定存入的she
  • Leecode 每日一题 problem2 (03-23)

    给你两个 非空 的链表 表示两个非负的整数 它们每位数字都是按照 逆序 的方式存储的 并且每个节点只能存储 一位 数字 请你将两个数相加 并以相同形式返回一个表示和的链表 你可以假设除了数字 0 之外 这两个数都不会以 0 开头 来源 力扣
  • 2021-10-24

    Python 简介 Python 是一个高层次的结合了解释性 编译性 互动性和面向对象的脚本语言 Python 的设计具有很强的可读性 相比其他语言经常使用英文关键字 其他语言的一些标点符号 它具有比其他语言更有特色语法结构 Python
  • ERR_PNPM_NO_GLOBAL_BIN_DIR Unable to find the global bin directory

    错误提示 ERROR Unable to find the global bin directory Run pnpm setup to create it automatically or set the global bin dir s
  • (1)minikube玩转k8s集群之虚拟机支持嵌套虚拟化

    配套视频教程 1 Minikube介绍 简单说 创建k8s集群很麻烦 minikube可以让我们快速搭建一个k8s集群用于学习 Minikube 是一种可以让您在本地轻松运行 Kubernetes 的工具 Minikube 在笔记本电脑上的
  • openId和unionId的区别

    网友的解释 微信的用户隐私策略 每个接入微信的应用 公众号 APP 就像一个独立的商场 用户使用这些应用就像逛商场 商场用会员卡识别用户 类似的 我们根据商场名字为每个用户生成了一张专属会员卡 openid 每张会员卡只能在对应的商场才能够
  • Navicat for MySQL安装教程

    Navicat for MySQL是一款强大的 MySQL 数据库管理和开发工具 它为专业开发者提供了一套强大的足够尖端的工具 但对于新用户仍然易于学习 Navicat for MySQL 基于Windows平台 为 MySQL 量身订作
  • R语言logistic回归的细节解读

    本文首发于公众号 医学和生信笔记 完美观看体验请至公众号查看本文 医学和生信笔记 专注R语言在临床医学中的使用 R语言数据分析和可视化 文章目录 二项logistic回归 R语言中的 factor 函数可以把变量变为因子类型 默认是没有等级
  • Redis缓存击穿问题及解决思路

    一 什么是缓存击穿 缓存击穿问题也叫热点Key问题 就是一个被高并发访问并且缓存重建业务较复杂的key突然失效了 无数的请求访问会在瞬间给数据库带来巨大的冲击 逻辑分析 假设线程1在查询缓存之后 本来应该去查询数据库 然后把这个数据重新加载
  • 【Java】对象的序列化与反序列化

    对象序列化的含义 对象序列化 Serialize 指将一个Java对象写入IO流中 对象的反序列化 Deserialize 则是指从IO流中恢复该Java对象 如果想让某个Java对象能够序列化 则必须让它的类实现java io Seria
  • 使用docker需要知道的基础知识

    一 docker概念 1 1 docker仓库 镜像 容器的作用和三者之间的关系是什么 答 Docker 仓库 用来保存镜像 可以理解为代码控制中的代码仓库 Docker 镜像 是用于创建 Docker 容器的模板 Docker 容器 是独
  • 前端工程化详解——理解与实践前端工程化

    前言 前端工程化一直是一个老生常谈的问题 不管是面试还是我们在公司做基建都会经常提到前端工程化 那么为什么经常会说到前端工程化 并没有听过后端工程化 Java工程化或者Python工程化呢 我们理解的前端工程化是不是一直都是Webpack的
  • 回望2001年的雪鸟城:引发全球软件革命的“敏捷宣言”是如何诞生的?

    将人们置于流程之上 专注于开发可以工作的软件 而不是软件的文档 和你的客户一起工作 而不是为一份合同而争吵 在此过程中 要对改变持开放态度 编者按 敏捷 Agile 这个对于开发真来说不在陌生的概念 已经提出了近17年了 其背后的哲学理念也
  • [CSDN竞赛]第五期参赛回顾

    CSDN竞赛 第五期参赛回顾 体验感想 第一次参加 本来有点小期待 那天还起晚了 结果登录不上去 发现大家都有问题 对我来说反而是好事 本来早上没有下午晚上更加精神 下面是提的建议 上次的登录问题 希望官方下次不要再出现 一定要准备充足 为
  • Unity Shader:用几何着色器实现复联3灭霸的终极大招灰飞烟灭

    图1 正常渲染 图2 几何着色器粒子化特效进行中 图3 几何着色器粒子化特效进行中 1 用几何着色器进行图元转换 在OpenGL渲染管线中 几何着色器Geometry Shader有一个独一无二的功能 既是图元转换 可简单理解为对基本图元点
  • 微信小程序默认下拉刷新和自定义下拉刷新的方式

    1 默认下拉刷新 在指定页面对应的 json配置文件中加入 enablePullDownRefresh true backgroundTextStyle dark 在对应的 js文件中 写入onPullDownRefresh 如果存在则替换
  • 手把手教你做一套“能源管理系统” A

    hello 大家好 我是CC 今天让CC来手把手教大家设计一套 能源管理系统 上个视频咱们有说到 能源管理系统 的范围很广 可以粗分为面向供给侧和面向消费侧 其中面向消费侧又可以分为 家庭能源管理系统HEMS 社区 园区能源管理系统CEMS
  • EQ频响曲线绘制和DRC特性曲线绘制

    目录 1 EQ 系数计算和频响曲线绘制 1 1 基本流程 1 2 EQ参数输入 1 3 滤波器系数计算 1 4 频率响应计算 1 5 曲线绘制 2 DRC特性曲线绘制 2 1 基本流程 2 2 参数输入 2 3 增益计算 2 4 静态特性曲