我想從MATLAB中的採樣信號中產生一系列「聽覺尖峯」,並且迄今爲止我實施的方法很慢。太慢了。Matlab:高效地產生聽覺尖峯
尖峯產生於第二部分B的http://patrec.cs.tu-dortmund.de/pubs/papers/Plinge2010-RNF.pdf:檢測過零點並對每對之間信號的(平方根壓縮的)正部分進行求和。這給每個釘的高度。他們的位置是通過識別每對過零點之間的最大值來確定樣本的。
我想爲此使用accumarray(...),這讓我產生了一個矩陣,其中每列表示一對過零點(尖峯)並且每行都是樣本。然後用相應的一對過零點之間的列填充每列。
當前的實現從實際的數據向量中填充這些列,以便我們不必在之後使用準確數據。
當前實現:
function out = audspike(data)
% Find the indices of the zero crossings. Two types of zero crossing:
% * Exact, samples where data == 0
% * Change, where data(i) .* data(i+1) < 0; that is, data changes sign
% between two samples. In this implementation i+1 is returned as the
% index of the zero crossing.
zExact = (data == 0);
zChange = logical([0; data(1:end-1) .* data(2:end) < 0]);
zeroInds = find(zExact | zChange);
% Vector of the difference between each zero crossing index
z=[zeroInds(1)-1; diff(zeroInds)];
% Find the "number of zeros" it takes to move from the first sample to the
% a given zero crossing
nzeros=cumsum(z);
% If the first sample is positive, we cannot generate a spike for the first
% pair of zero crossings as this represents part of the signal that is
% negative; therefore, skip the first zero crossing and begin pairing from
% the second
if data(1) > 0
nzeros = nzeros(2:2:end);
nones = z(3:2:end)+1;
else
nzeros = nzeros(1:2:end);
nones = z(2:2:end)+1;
end
% Allocate sparse array for result
G = spalloc(length(data), length(nzeros), sum(nones));
% Loop through pairs of zero crossings. Each pair gets a column in the
% resultant matrix. The number of rows of the matrix is the number of
% samples. G(n, ii) ~= 0 indicates that sample n belongs to pair ii
for ii = 1:min(length(nzeros), length(nones))
sampleInd = nzeros(ii)+1:nzeros(ii)+nones(ii)-1;
G(sampleInd, ii) = data(sampleInd);
end
% Sum the square root-compressed positive parts of signal between each zero
% crossing
height = sum(sqrt(G), 2);
% Find the peak over average position
[~, pos] = max(G, [], 2);
out = zeros(size(data));
out(pos) = height;
end
正如我所說的,這是緩慢的,而且每次只適用於一個通道。緩慢的部分是(不出所料)的循環。如果我將矩陣G的分配更改爲標準零(...)而不是稀疏數組,則慢速部分將成爲總和(...)和最大(...)計算,原因很明顯。
我該如何更有效地做到這一點?我不反對寫一個MEX函數,如果這就是它要做的。
你正在做處理看起來適合信號的串行處理。我想這種串行處理在C/C++中比在Matlab中更好。你有沒有考慮過這個功能? – Shai
如果我理解正確,sampleInd是循環中每個點的向量。在這種情況下,如果使用索引矩陣而不是許多向量,則可能會消除循環。 –