To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

Statistics Download as Zip
| Branch: | Revision:

root / _segmentation / segmentation_auto.m

History | View | Annotate | Download (6.58 KB)

1
function song = segmentation_auto(song, param, varargin)
2

    
3

    
4
%% calculating similarity matrix
5
% exp of minus the cosine distance
6

    
7
if any(strcmp(fieldnames(song.syncchroma),'wide'))
8
	v = song.syncchroma.wide;
9
else
10
	v = song.syncchroma.treble + song.syncchroma.bass(:,1:12) * 0.8;
11
end
12
nBeat = song.nBeat;
13
flatPCP = std(v')<.000001;
14
v(flatPCP,1) = 1000; % arbitrary
15
simmat0 = squareform(pdist(v,'correlation'));
16
% simmat0(flatPCP,:) = 2;
17
% simmat0(:,flatPCP) = 2;
18
% simmat = qnormalise(exp(-simmat0),inf,1);
19
% simmat(flatPCP,:) = 0;
20
% simmat(:,flatPCP) = 0;
21

    
22
simmat0(flatPCP,:) = 1;
23
simmat0(:,flatPCP) = 1;
24
simmat = 1-simmat0/2;
25
simmat(flatPCP,:) = 0;
26
simmat(:,flatPCP) = 0;
27

    
28
%%
29
median_simmat = zeros(size(simmat));
30
for  i = 1:nBeat
31
    temp1 = diag(medfilt1(diag(simmat,i-1),param.seg.medfilt_length,[],1),i-1);
32
    median_simmat = median_simmat + temp1;
33
end
34
median_simmat = median_simmat + median_simmat' - diag(diag(median_simmat));
35
median_simmat(isnan(median_simmat)) = 0;
36
%%median_simmat = (median_simmat - mean(median_simmat(:)))/std(median_simmat(:));
37
%%%%%%%% ATTENTION!!!!!!!! using MEDIAN %%%%%%%%%%%%%
38
% median_simmat = (median_simmat - median(median_simmat(:)))/std(median_simmat(:));
39
if param.seg.standardise
40
    med_median_simmat = repmat(median(median_simmat),nBeat,1);
41
    std_median_simmat = repmat(std(median_simmat),nBeat,1);
42
    median_simmat = (median_simmat - med_median_simmat) ./ std_median_simmat;
43
end
44
%% get bar boundaries!!!
45

    
46
potential_duplicates = triu(median_simmat > param.seg.thresh_beat);
47

    
48
%%
49
partlengths = param.seg.minlength:4:param.seg.maxlength;
50
nPartlengths = length(partlengths);
51

    
52
% initialise arrays
53
simArray = zeros(nBeat,nBeat,nPartlengths);
54
decisionArray2 = zeros(nBeat,nBeat,nPartlengths);
55

    
56

    
57

    
58
fprintf(1,'\n');
59
fprintf(2,'    ');
60
for iLength = 1:nPartlengths
61
    len = partlengths(iLength);
62
    nUsedBeat = nBeat - len + 1; % number of potential rep beginnings: they can't overlap at the end of the song
63
    fprintf(1,'\rLength: %1.0d',len)
64
    fprintf(2,'\b\b\b\b%3.0f%%',iLength/nPartlengths*100);
65
    for iBeat = 1:nUsedBeat % looping over all columns (arbitrarily chosen columns)
66
        help2 = find(potential_duplicates(1:nUsedBeat,iBeat));
67
        for kBeat = help2' % check only potential duplicates
68
            % measure how well two length len segments go together
69
            simArray(iBeat,kBeat,iLength) = ...
70
                quantile(diag(median_simmat(iBeat+(0:len-1),kBeat+(0:len-1))),param.seg.quantile);
71
        end
72
    end
73
    simArray(1:nUsedBeat,1:nUsedBeat,iLength) = simArray(1:nUsedBeat,1:nUsedBeat,iLength) ...
74
        + simArray(1:nUsedBeat,1:nUsedBeat,iLength)' ...
75
        - eye(nUsedBeat) .* simArray(1:nUsedBeat,1:nUsedBeat,iLength);
76

    
77
    simArray(:,:,iLength) = conv2(simArray(:,:,iLength),[.01 .98 .01], 'same');
78
    % take only over-average bars that do not overlap
79
    for iBeat = 1:nUsedBeat
80
        temp = simArray(:,iBeat,iLength) > param.seg.thresh_seg;
81
        decisionArray2(temp,iBeat,iLength) = ...
82
            simArray(temp,iBeat,iLength);
83
    end
84
    decisionArray2(:,:,iLength) = decisionArray2(:,:,iLength) .* (decisionArray2(:,:,iLength) >= maxfilt1(decisionArray2(:,:,iLength),len-1));
85
    decisionArray2(:,:,iLength) = decisionArray2(:,:,iLength) .* decisionArray2(:,:,iLength)';
86
%     potential_duplicates = triu(simArray(:,:,iLength) > param.seg.thresh_seg * 0.7);
87
    potential_duplicates = potential_duplicates .* (simArray(:,:,iLength) > param.seg.thresh_seg);
88
end
89
%% milk the data
90

    
91
bestvals = [];
92
for iLength = 1:nPartlengths
93
    currLogicSum = sum(decisionArray2(:,:,iLength)>0,2);
94
    for iBeat = 1:nBeat
95
        if currLogicSum(iBeat) > 1.0
96
            currSum = (mean(decisionArray2(decisionArray2(:,iBeat,iLength)>0,iBeat,iLength)))/2;
97
            bestvals = [bestvals; (currLogicSum(iBeat)-1) * partlengths(iLength), currSum, iLength, iBeat, currLogicSum(iBeat)];
98
        end
99
    end
100
end
101
%%
102
%%
103
% make a table of all valid sets of parts
104
partletters = {'A','B','C','D','E','F','G', 'H','I','J','K','L','M','N','O','P','Q','R','S'};
105
valid_sets = ones(1,size(bestvals,1));
106
parts = [];
107
if ~isempty(bestvals)
108
    bestvals(:,2) = bestvals(:,2) / max(bestvals(:,2)*2);
109
    bestvals(:,1) = bestvals(:,1) + bestvals(:,2);
110
    bestvals(:,2) = [];
111

    
112
    for kSeg = 1:7
113
        currbestvals = bestvals(logical(valid_sets),:);
114
        [m,i] = max(currbestvals(:,1));
115
        if isempty(m)
116
            break
117
        end
118

    
119
        bestLength = partlengths(currbestvals(i,2));
120
        bestIndices = decisionArray2(currbestvals(i,3),:,currbestvals(i,2));
121
        islands = conv2(1*(bestIndices > 0), [zeros(1,bestLength-1) ones(1,bestLength)], 'same');
122
        %%
123
        if param.seg.newcheck
124
            iBetter = i;
125
            bestSubval = 0;
126
            subm1 = find(currbestvals(:,4) > currbestvals(i,4)); % has to have more part instances
127
            for kSub = 1:length(subm1)
128
                iSub = subm1(kSub);
129
                subIndices = decisionArray2(currbestvals(iSub,3),:,currbestvals(iSub,2));
130
                subLength = partlengths(currbestvals(iSub,2));
131
                subIslands = conv2(1*(subIndices > 0), [zeros(1,subLength-1) ones(1,subLength)], 'same');
132
                if sum(islands.*subIslands) == currbestvals(i,4) * subLength ...
133
                        && currbestvals(iSub,1) > bestSubval
134
                    iBetter = iSub;
135
                    bestSubval = currbestvals(iSub,1);
136
                end
137
            end
138
            i = iBetter;
139
            bestLength = partlengths(currbestvals(i,2));
140
            bestIndices = decisionArray2(currbestvals(i,3),:,currbestvals(i,2));
141
            islands = conv2(1*(bestIndices > 0), [zeros(1,bestLength-1) ones(1,bestLength)], 'same');
142
        end
143
        %%
144
        part.n = bestLength;
145
        part.indices = find(bestIndices);
146
        part.letter = partletters{kSeg};
147
        part.level = kSeg;
148
        parts = [parts part];
149

    
150
        for iSet = find(valid_sets)
151
            currislands = conv2(2*(decisionArray2(bestvals(iSet,3),:,bestvals(iSet,2)) > 0), ...
152
                [zeros(1,partlengths(bestvals(iSet,2))-1) ones(1,partlengths(bestvals(iSet,2)))], 'same');
153
            if any(islands .* currislands > 0)
154
                valid_sets(iSet) = false;
155
            else
156
                %             stem(islands+currislands*.5)
157
                %             aaa = 1;
158
            end
159
        end
160
    end
161
else
162
    part.n = nBeat;
163
    part.indices = 1;
164
    part.letter = 'A';
165
    part.level = 1;
166
    parts = [parts part];
167
end
168

    
169
parts = [parts, nullpart(parts,1:nBeat)];
170
if param.seg.editor
171
    [pa, ta] = partarray(parts);
172
    parts = editorssearch(pa, ta, parts);
173
    parts = [parts, nullpart(parts,1:nBeat)];
174
end
175
parts = mergenulls(parts);
176

    
177
song.parts = parts;
178
% song.parts
179

    
180