% [freq,fase,amp] = freqmat2(allpeaks,allfase,allamps, delta)
% allpeaks = matrix of peaks returned from stft and normalized to freq
% INPUT - allpeaks is the matrix of all the frequencies, with each column
% corresponding to a frame (or stft computation) allfase and allamps are
% corresponding matrics of all the phases and amplitudes
% OUTPUT - freq, fase, and amp are matrices with each column holding tracks.
% A 0 in amps after data means a track going has died, and a track is born at
% the point data begins following a zero. Note: there is still a one-to-one
% correspondence between the frame number and the row index.
function [freq, fase, amp] = freqmat2(allpeaks, allfase, allamps, delta)
[numPeaks, numFrames] = size (allpeaks);
% pre-allocate space
freq = zeros(numFrames, numPeaks);
fase = zeros(numFrames, numPeaks);
amp = zeros(numFrames, numPeaks);
%set first row to first frame's peaks
freq(1,:) = allpeaks(:, 1)';
fase(1,:) = allpeaks(:, 1)';
amp(1,:) = allpeaks(:, 1)';
oldCrib = find(amp(1,:) == 0);
oldBirth = length(oldCrib);
extras = 0; % keeps track of how many columns past numPeaks exist
for k = 1:(numFrames-1)
%reset flag vector
flag = zeros(numPeaks, 1);
index = 0; % in case nothing picked up
% grab all the next frame's peak that fall in delta fan for the first peak
if (freq(k,1) ~= 0)
compare = (allpeaks(:, k+1) > (freq(k,1) - delta)) & (allpeaks(:, k+1) <= freq(k,1) + delta);
possibles = find(compare);
if possibles == []
% nothing matches, this track DIES
%freq(k+1, 1) = freq(k, 1); % for interpolating
%fase(k+1, 1) = fase(k, 1); %for interpolating
else % find which is closest
[value, index] = min(abs(allpeaks(possibles, k+1) - freq(k, 1)));
index = possibles(index);
end % end if
end % end if
for i = 1:(numPeaks - 1 + extras)
oldCompare = compare;
oldIndex = index; index = 0;
oldValue = value;
if (amp(k,i+1) ~= 0) % changed from freq
% check if next guy doesn't want that point
% Side note to users- we are only checking if the next track does not want
% that point, this does not provide total coverage/correctness, but
% there is no way to produce exactitude in this, and the marginal value
% of checking other guys goes down quickly, so this should prove good
% To improve: try using a small delta, and then a bigger delta. For our tests
% a delta from .03 to .05 seemed to provide the best results.
%calculate for next guy
compare = ((allpeaks(:, k+1) > (freq(k,i+1) - delta)) & (allpeaks(:, k+1) <= freq(k,i+1) + delta));
% check if someone else has grabbed those points
possibles = find(compare);
for q = 1:length(possibles)
if (flag(possibles(q))==1) % flag is set, that peak is taken
compare(possibles(q)) = 0; % erase from compare
end % end if
end % end for
possibles = find(compare); %may have changed
if possibles == []
% nothing matches, this track DIES
%freq(k+1, i) = freq(k, i); % for interpolating
%fase(k+1, i) = fase(k, i); %for interpolating
else % find which is closest
[value, index] = min(abs(allpeaks(possibles, k+1) - freq(k, i+1)));
index = possibles(index);
end % end
end % end if next freq != 0
if(amp(k, i) ~=0)% used to be freq
if (index==oldIndex & oldIndex~=0 & oldValue>value) % oldguy takes second choice
% only if new guy is closer.
oldCompare(oldIndex) = 0;
% check flag again
oldPos = find (oldCompare);
for q = 1:length(oldPos)
if (flag(oldPos(q))==1) % flag is set, that peak is taken
oldCompare(oldPos(q)) = 0; % erase from compare
end
end
oldPos = find(oldCompare);
if (oldPos == []) % nothing matches, this track DIES
%freq(k+1, i) = freq(k, i); % for interpolating
%fase(k+1, i) = fase(k, i); %for interpolating
oldIndex = 0;
else % find which is closest
[oldValue, oldIndex] = min(abs(allpeaks(oldPos, k+1) - freq(k, i)));
oldIndex = oldPos(oldIndex);
end % end if
end % end if
if (oldIndex ~= 0)
freq(k+1, i) = allpeaks(oldIndex, k+1);
fase(k+1, i) = allfase(oldIndex, k+1);
amp(k+1, i) = allamps(oldIndex, k+1);
flag(oldIndex) = 1;
end
end %end if
end % end for(i) loop
% last guy auto gets whatever one he wants:
if(index ~= 0)
freq(k+1, numPeaks + extras) = allpeaks(index, k+1);
fase(k+1, numPeaks + extras) = allfase(index, k+1);
amp(k+1, numPeaks + extras) = allamps(index, k+1);
flag(index) = 1;
end
% Now, all the existing tracks have gotten to pick successors from the frame
% but there may be values in frame k+1 not matched into k, they need to be born
% and added to open space somewhere at the correct row index to start a track.
% Check the flag vector for values not matched, and birth them.
for y=1:numPeaks
if (flag(y) == 0 & oldBirth ~= 0) %
newBorn = oldCrib(oldBirth);
if(allpeaks(y, k+1) ~= 0) % don't birth zeros
freq(k+1, newBorn) = allpeaks(y, k+1); % A track is born!
%freq(k, newBorn) = allpeaks(y, k+1); % for interpolating
amp(k+1, newBorn) = allamps(y, k+1);
fase(k+1, newBorn) = allfase(y, k+1);
%fase(k, newBorn) = allfase(y, k+1); % for interpolating
oldBirth = oldBirth - 1;
end
elseif (flag(y) == 0) % need to add new track column
extras = extras + 1; newC = numPeaks + extras;
freq(k+1, newC) = allpeaks(y, k+1);
%freq(k, newC) = allpeaks(y, k+1); % for interpolating
amp(k+1, newC) = allamps(y, k+1);
fase(k+1, newC) = allfase(y, k+1);
%fase(k, newC) = allfase(y, k+1); % for interpolating
end % end if
end % end local for
oldCrib = find (amp(k+1,:) == 0); % prepare for next cycle
oldBirth = length(oldCrib); % OldCrib holds indices of zeros
% % from k+1 track and oldBirth is how many
end % end frame (k) loop for