我正在编写一个实现噪声门算法的Matlab脚本。它迭代输入信号的长度(我在同一个脚本中创建)并逐个样本处理。算法本身不需要太多内存(它会在下一次迭代中携带两个值,即x_peak_old
和g_old
)。但是,为了监视算法的内部过程,我创建了一些额外的调试向量,这些向量与输入信号的长度相同,并且每个循环都会更新。我会根据需要对它们进行评论。
然而,我的问题是其中一个向量行为奇怪。如果我禁用此向量并点击“运行”,脚本将立即执行并完成。但是,当我为每个循环的特定向量赋值并运行脚本时,计算需要几秒钟,并且在此期间我的CPU的一个核心处于100%负载。
以下是代码:
clear all; close all;
% ***** Parameter *****
Fs = 44100; % Samplerate
ta = 5; % Attack time in ms
tr = 300; % Release time in ms
th = -8; % Threshold in dB
R = 0.05; % Ratio in dB/dB
% ***** Test signal *****
f0 = 20000; % Frequency in Hz
a = (0:Fs) ./ Fs;
aflip = fliplr(a);
sine = sin((2 * pi * f0 / Fs) .* (0:Fs));
sinedecay = zeros(1, Fs);
for k = 1:(Fs+1)
sinedecay(k) = sine(k)*aflip(k);
end
zeropad = zeros(1, Fs);
% Sine only
% x = [zeropad sine sinedecay zeropad];
% Triangle Rectangle Sine
x = [zeropad a (1-a) -a a-1 zeropad ones(1, Fs) (-1).*ones(1,Fs) zeropad sine sine sinedecay zeropad];
% Dirac
%x = [zeropad 1 zeropad];
siglen = length(x);
x_axis = (1:siglen) ./ Fs;
% ***** Output signal *****
y = zeros(1, siglen);
% ***** Debug signals *****
%threshold = 10^(th/20) .* ones(1, siglen);
%xpeakt = zeros(1, siglen);
%peaklogt = zeros(1, siglen);
%ctrl_logt = zeros(1, siglen);
f_t = zeros(1, siglen);
gt = zeros(1, siglen);
% ***** Derived parameters *****
AT = 1/(1+ta*Fs/1000);
RT = 1-1/(1+tr*Fs/1000);
TH_log = log2( 10^(th/20));
S = 1 - 1/R;
% ***** Initial parameters *****
x_peak_old = 0;
g_old = 0;
% ***** Lets go! *****
for i = 1:siglen
% Peak measurement
p0 = abs(x(i));
x_peak = x_peak_old * RT;
if (p0 > x_peak)
x_peak = p0 * AT + x_peak_old *(1-AT);
end
x_peak_old = x_peak;
% xpeakt(i) = x_peak; % DEBUG
x_peak_log = log2(x_peak);
% peaklogt(i) = x_peak_log; % DEBUG
% Compare with threshold
ctrl_log = TH_log - x_peak_log;
if (ctrl_log < 0)
ctrl_log = 0;
end
% ctrl_logt(i) = ctrl_log; %DEBUG
% Calculation of weight factor
f = S * ctrl_log;
f_t(i) = f; %DEBUG
g = 2^f;
% Smoothing filter for weight factor
if (g > g_old)
coeff = 1-AT;
else
coeff = 1-RT;
end
temp = g;
g = coeff * g + (1-coeff) * g_old;
g_old = temp;
% THE FOLLOWING LINE CAUSES PROBLEMS
gt(i) = g; % DEBUG
% Calculation output signal
y(i) = x(i) * g;
end
% ***** Plot input, output and debug signals *****
figure;
subplot(211);
plot(x_axis, x);
hold on; grid on;
%plot(x_axis, threshold);
%plot(x_axis, xpeakt); %DEBUG
%plot(x_axis, peaklogt); %DEBUG
%plot(x_axis, ctrl_logt); %DEBUG
plot(x_axis, f_t); %DEBUG
%plot(x_axis, gt); %DEBUG
subplot(212);
plot(x_axis, y);
导致问题的一条线接近结束:
gt(i) = g; % DEBUG
然而,在同一个循环之前,我只是几行,我以同样的方式为一个向量赋值:
f_t(i) = f; %DEBUG
两个向量都以相同的方式初始化。此循环中有更多向量以完全相同的方式处理,但只有gt(i)
向量表现为奇数。
我在运行Matlab R2014b的两台不同机器上测试了这个脚本。是什么导致了这个问题?
答案 0 :(得分:4)
只需将变量gt
的名称更改为其他内容(除了内置函数的名称)。
我认为情况确实如此.Mathworks警告您何时告诉您不建议重载内置函数。
gt
函数是速记运算符>
的完整形式。
在运行脚本之前:
>> which gt
built-in (C:\TLAB13a\toolbox\matlab\ops\@double\gt) % double method
运行脚本后:
>> which gt
gt is a variable.
我可以在Matlab R2013a中重现所描述的行为(使用调试变量约为7.5s,不带0.1s)。
请注意,在R2016a上,此行为是不存在的(两个版本都为~0.12s)。较新的Matlab引擎不会因重载的内置函数而容易混淆。
在您的情况下,对于使用较旧Matlab版本的人,只需将变量名称从gt
更改为其他任何内容(除了另一个内置函数的名称),例如gtx
,即使使用调试变量,脚本也能正常运行。
答案 1 :(得分:3)
找到了恶作剧。显然这个问题是由矢量名gt
引起的,它也是一个等同于'&gt;'的内置函数。运营商。压倒一切对速度有很大影响。简单地重命名向量就解决了这个问题。