我认为没有现成的解决方案可以找到干扰,但这是解决问题的一种(非标准)方法。使用它,我可以找到大多数间隔,并且只得到少量误报,但该算法当然可以使用一些微调。
我的想法是找到偏离样本的起点和终点。第一步应该是让这些观点更加清晰。这可以通过取数据的对数并取连续值之间的差异来完成。
在 MATLAB 中我加载数据(在这个例子中我使用了dirty-sample-other.wav)
y1 = wavread('dirty-sample-pictured.wav');
y2 = wavread('dirty-sample-other.wav');
y3 = wavread('clean-highfreq.wav');
data = y2;
并使用以下代码:
logdata = log(1+data);
difflogdata = diff(logdata);
因此,而不是原始数据的这个图:

我们得到:

我们正在寻找的间隔突出为正负峰值。例如放大对数差异图中的最大正值,我们得到以下两个数字。一个用于原始数据:

一个用于对数的差异:

该图可以帮助手动查找区域,但理想情况下,我们希望使用算法找到它们。我这样做的方法是取一个大小为 6 的移动窗口,计算窗口的平均值(除最小值之外的所有点),并将其与最大值进行比较。如果最大值点是唯一高于平均值且至少是平均值两倍的点,则将其计为正极值。
然后我使用了计数阈值,至少有一半的窗口在该值上移动应该将其检测为极值,以便它被接受。
然后将所有点与 (-1) 相乘,然后再次运行该算法以检测最小值。
用“o”标记正极端,用“*”标记负极端,我们得到以下两个图。一种是对数的差异:

一个用于原始数据:

放大显示对数差异的图的左侧部分,我们可以看到找到了大多数极值:

似乎找到了大多数间隔,并且只有少量误报。例如,在我运行算法时,'clean-highfreq.wav'
我只找到一个正极值和一个负极值。
被错误归类为极值的单个值可能会通过匹配起点和终点而被淘汰。如果你想替换丢失的数据,你可以使用周围数据点的某种插值,甚至线性插值就足够了。
这是我使用的 MATLAB 代码:
function test20()
clc
clear all
y1 = wavread('dirty-sample-pictured.wav');
y2 = wavread('dirty-sample-other.wav');
y3 = wavread('clean-highfreq.wav');
data = y2;
logdata = log(1+data);
difflogdata = diff(logdata);
figure,plot(data),hold on,plot(data,'.')
figure,plot(difflogdata),hold on,plot(difflogdata,'.')
figure,plot(data),hold on,plot(data,'.'),xlim([68000,68200])
figure,plot(difflogdata),hold on,plot(difflogdata,'.'),xlim([68000,68200])
k = 6;
myData = difflogdata;
myPoints = findPoints(myData,k);
myData2 = -difflogdata;
myPoints2 = findPoints(myData2,k);
figure
plotterFunction(difflogdata,myPoints>=k,'or')
hold on
plotterFunction(difflogdata,myPoints2>=k,'*r')
figure
plotterFunction(data,myPoints>=k,'or')
hold on
plotterFunction(data,myPoints2>=k,'*r')
end
function myPoints = findPoints(myData,k)
iterationVector = k+1:length(myData);
myPoints = zeros(size(myData));
for i = iterationVector
subVector = myData(i-k:i);
meanSubVector = mean(subVector(subVector>min(subVector)));
[maxSubVector, maxIndex] = max(subVector);
if (sum(subVector>meanSubVector) == 1 && maxSubVector>2*meanSubVector)
myPoints(i-k-1+maxIndex) = myPoints(i-k-1+maxIndex) +1;
end
end
end
function plotterFunction(allPoints,extremeIndices,markerType)
extremePoints = NaN(size(allPoints));
extremePoints(extremeIndices) = allPoints(extremeIndices);
plot(extremePoints,markerType,'MarkerSize',15),
hold on
plot(allPoints,'.')
plot(allPoints)
end
编辑 - 关于恢复原始数据的评论
这是上图三的稍微放大的视图:(扰动在 6.8 和 6.82 之间)

当我检查这些值时,您关于将数据镜像为负值的理论似乎并不完全符合该模式。但无论如何,我认为只是消除差异的想法肯定是不正确的。由于周围的点似乎没有被干扰改变,我可能会回到最初的想法,即不信任受影响区域内的点,而是使用周围数据进行某种插值。在大多数情况下,简单的线性插值似乎是一个很好的近似值。