annotate nonExposed/generateScene.m @ 14:b1901e8d8f5f

initial commit
author Mathieu Lagrange <mathieu.lagrange@cnrs.fr>
date Tue, 17 Mar 2015 09:34:13 +0100
parents
children 69410ac2a50d
rev   line source
mathieu@14 1 function [w,sceneSchedule] = generateScene (sceneSchedule,sceneObjects,score,inputPath,outputPath,outputFileName,displayFigures,timeMode,endCut)
mathieu@14 2 % function [w,sceneSchedule] = generateScene (sceneSchedule,sceneObjects,score,inputPath,outputPath,outputFileName,displayFigures,timeMode,endCut)
mathieu@14 3 % This function does the actual job of loading, scaling, positioning and
mathieu@14 4 % mixing the various samples to generate a scene, based on the
mathieu@14 5 % specifications given by its parameters.
mathieu@14 6
mathieu@14 7 % This program was written by Mathias Rossignol & Grégoire Lafay
mathieu@14 8 % is Copyright (C) 2015 IRCAM <http://www.ircam.fr>
mathieu@14 9 %
mathieu@14 10 % This program is free software: you can redistribute it and/or modify it
mathieu@14 11 % under the terms of the GNU General Public License as published by the Free
mathieu@14 12 % Software Foundation, either version 3 of the License, or (at your option)
mathieu@14 13 % any later version.
mathieu@14 14 %
mathieu@14 15 % This program is distributed in the hope that it will be useful, but
mathieu@14 16 % WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
mathieu@14 17 % or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
mathieu@14 18 % for more details.
mathieu@14 19 %
mathieu@14 20 % You should have received a copy of the GNU General Public License along
mathieu@14 21 % with this program. If not, see <http://www.gnu.org/licenses/>.
mathieu@14 22
mathieu@14 23 sr = 44100;
mathieu@14 24 trackLength = sr*score.sceneDuration;
mathieu@14 25 nbTracks = length(sceneObjects);
mathieu@14 26
mathieu@14 27 % All instances of one sample will appear on a given track, before
mathieu@14 28 % everything is mixed together, making it possible to apply track-specific
mathieu@14 29 % effects or generate nice colorful representations
mathieu@14 30 tracks = zeros(length(sceneObjects), trackLength);
mathieu@14 31
mathieu@14 32 % We also generate a "bg" track with all background samples, against which
mathieu@14 33 % the snr of fg sounds will be evaluated
mathieu@14 34 bg = zeros(trackLength, 1);
mathieu@14 35
mathieu@14 36 %% Preloading all wav samples into memory
mathieu@14 37 waves = {};
mathieu@14 38 for i=1:nbTracks
mathieu@14 39 if(sceneObjects(i).isBackground)
mathieu@14 40 path = [inputPath,'background/'];
mathieu@14 41 else
mathieu@14 42 path = [inputPath,'event/'];
mathieu@14 43 end
mathieu@14 44 sample = dir([path '*wav']);
mathieu@14 45 sampleId = find(cellfun('isempty',regexpi({sample.name},sceneObjects(i).query,'match'))==0);
mathieu@14 46 for j=1:length(sampleId)
mathieu@14 47 % this test is necessary because mp3 conversion does not
mathieu@14 48 % always maintain exact length, and wavread will crash if asked to
mathieu@14 49 % read too many samples.
mathieu@14 50 waves{i}{j}= wavread([path sample(sampleId(j)).name]);
mathieu@14 51 if(size(waves{i}{j},2)==2)
mathieu@14 52 waves{i}{j}= mean(waves{i}{j},2);
mathieu@14 53 end
mathieu@14 54 waves{i}{j} = waves{i}{j}(:);
mathieu@14 55 end
mathieu@14 56 end
mathieu@14 57
mathieu@14 58 dominantTrack = zeros(1,trackLength) + 1;
mathieu@14 59 dominantObject = zeros(1,trackLength) + 1;
mathieu@14 60 dominantEnergy = zeros(1,trackLength);
mathieu@14 61 simulatedEBR = zeros(length(sceneSchedule),2);
mathieu@14 62 objNum = 1;
mathieu@14 63
mathieu@14 64 %% Create sceneSchedule
mathieu@14 65 id2remove=[];
mathieu@14 66 for i=1:length(sceneSchedule)
mathieu@14 67 id = sceneSchedule(i).classId;
mathieu@14 68 if (sceneSchedule(i).isBackground)
mathieu@14 69 scale = 1;
mathieu@14 70 if (i>1)
mathieu@14 71 scale = adjustScaleForEBR(waves{id}{1}, bg, 1, sceneSchedule(i).ebr, 1, 0.01);
mathieu@14 72 end
mathieu@14 73 if (length(waves{id}{1}) < trackLength)
mathieu@14 74 % need to loop the sample to fill the bg. Linear crossfade
mathieu@14 75 loop = waves{id}{1};
mathieu@14 76 fadeLen = 20000;
mathieu@14 77 fadeIn = transpose(0:1/fadeLen:1);
mathieu@14 78 fadeOut = transpose(1:-1/fadeLen:0);
mathieu@14 79 loop(1:fadeLen) = loop(1:fadeLen) .* fadeIn(1:fadeLen);
mathieu@14 80 loop(length(loop)-fadeLen+1:length(loop)) = loop(length(loop)+1-fadeLen:length(loop)) .* fadeOut(1:fadeLen);
mathieu@14 81 loop = scale * loop.';
mathieu@14 82 for l=0:floor(trackLength/(length(loop)-fadeLen))
mathieu@14 83 t1 = 1+l*(length(loop)-fadeLen);
mathieu@14 84 t2 = min(length(bg), t1+length(loop)-1);
mathieu@14 85 tracks(id,t1:t2) = tracks(id,t1:t2) + loop(1:t2-t1+1);
mathieu@14 86 end
mathieu@14 87 else
mathieu@14 88 dim = min(trackLength, length(waves{id}{1}));
mathieu@14 89 tracks(id,1:dim) = tracks(id,1:dim) + scale*(waves{id}{1}(1:dim).');
mathieu@14 90 end
mathieu@14 91 if (i==1)
mathieu@14 92 bg = tracks(id,:);
mathieu@14 93 else
mathieu@14 94 bg = bg+tracks(id,:);
mathieu@14 95 end
mathieu@14 96 else
mathieu@14 97 objNum = objNum+1;
mathieu@14 98 inst = sceneSchedule(i).instance;
mathieu@14 99 pos = max(1,floor(sr*sceneSchedule(i).position));
mathieu@14 100
mathieu@14 101 switch timeMode
mathieu@14 102 case {'replicate'}
mathieu@14 103 if(length(waves{id}{inst})/sr - sceneSchedule(i).duration > 0.5)
mathieu@14 104 endTime = round(sceneSchedule(i).duration*sr);
mathieu@14 105 else
mathieu@14 106 endTime = length(waves{id}{inst});
mathieu@14 107 end
mathieu@14 108 case {'abstract'}
mathieu@14 109 endTime = round(sceneSchedule(i).duration*sr);
mathieu@14 110 otherwise
mathieu@14 111 endTime = length(waves{id}{inst});
mathieu@14 112 end
mathieu@14 113
mathieu@14 114 if endCut
mathieu@14 115 pos2Test=pos;
mathieu@14 116 else
mathieu@14 117
mathieu@14 118 pos2Test=pos+endTime-1;
mathieu@14 119 end
mathieu@14 120
mathieu@14 121 if(pos2Test<round(sceneObjects(sceneSchedule(i).classId).trackLength*sr))
mathieu@14 122 t2 = min(pos+endTime-1, round(sceneObjects(sceneSchedule(i).classId).trackLength*sr));
mathieu@14 123 wav2use=waves{id}{inst}(1:t2-pos+1);
mathieu@14 124 sceneSchedule(i).duration=length(wav2use)/sr;
mathieu@14 125 scale = adjustScaleForEBR(wav2use, bg, pos, sceneSchedule(i).ebr, 1, 0.01);
mathieu@14 126
mathieu@14 127 [~,bgEnergy] = powspec(bg(pos:t2));
mathieu@14 128 [~,evEnergy] = powspec(scale*wav2use.');
mathieu@14 129 labelStart = min(find(bgEnergy<evEnergy));
mathieu@14 130 labelEnd = max(find(bgEnergy<evEnergy));
mathieu@14 131 for t=labelStart:labelEnd
mathieu@14 132 if evEnergy(t)>dominantEnergy(pos+t)
mathieu@14 133 dominantObject(pos+round(t*(t2-pos)/length(bgEnergy))) = objNum;
mathieu@14 134 dominantEnergy(pos+round(t*(t2-pos)/length(bgEnergy))) = evEnergy(t);
mathieu@14 135 end
mathieu@14 136 end
mathieu@14 137 dominantObject(min(find(dominantObject==objNum)):max(find(dominantObject==objNum))) = objNum;
mathieu@14 138 dominantTrack(dominantObject==objNum) = id;
mathieu@14 139
mathieu@14 140 tracks(id, pos:t2) = tracks(id, pos:t2) + scale*wav2use.';
mathieu@14 141 %% Store EBR and event locations
mathieu@14 142 simulatedEBR(i,1) = ebr(tracks(id, pos:t2),tracks(1, pos:t2));
mathieu@14 143 simulatedEBR(i,2)=pos;
mathieu@14 144 else
mathieu@14 145 id2remove=[id2remove i];
mathieu@14 146 end
mathieu@14 147 end
mathieu@14 148 end
mathieu@14 149
mathieu@14 150 sceneSchedule(id2remove)=[];
mathieu@14 151 % checkClassPresence(sceneSchedule,sceneObjects);
mathieu@14 152
mathieu@14 153 save ([outputPath 'annotation/' outputFileName '.mat'],'score', 'sceneObjects', 'sceneSchedule','dominantTrack', 'dominantObject','simulatedEBR');
mathieu@14 154 saveAnnotationTxt(sceneSchedule,outputPath,outputFileName);
mathieu@14 155
mathieu@14 156 w = sum(tracks);
mathieu@14 157 w = w/(max(abs(w))+0.001); %Normalize to [-1,1]
mathieu@14 158
mathieu@14 159 if displayFigures
mathieu@14 160 cmap = generateColormap(sceneObjects);
mathieu@14 161
mathieu@14 162 timeDomainVisualization(tracks, cmap, 1, 10000, 1, [outputPath 'annotation/' outputFileName,'-timeDomain.png']);
mathieu@14 163
mathieu@14 164 % Producing a colored spectrum visualization
mathieu@14 165 for i=1:nbTracks
mathieu@14 166 spec = log(1+abs(spectrogram(tracks(i,:), hanning(2048), 1024, 2048)));
mathieu@14 167 spec = min(1, spec ./ max(spec(:)));
mathieu@14 168 spec = spec(1:400,:);
mathieu@14 169 spec = flipud(spec);
mathieu@14 170 for colorComp=1:3
mathieu@14 171 if (i==1)
mathieu@14 172 img(:,:,colorComp) = cmap(i,colorComp)*spec;
mathieu@14 173 else
mathieu@14 174 img(:,:,colorComp) = img(:,:,colorComp)+cmap(i,colorComp)*spec;
mathieu@14 175 end
mathieu@14 176 end
mathieu@14 177 end
mathieu@14 178 img = img/max(img(:));
mathieu@14 179 f = figure(2);
mathieu@14 180 clf;
mathieu@14 181 set(gca,'YTick', []);
mathieu@14 182 set(f, 'Position', [0, 0, 2*size(img,1), 600]);
mathieu@14 183 imagesc(img);
mathieu@14 184 imwrite(img, [outputPath 'annotation/' outputFileName,'-spectrum.png'], 'png');
mathieu@14 185
mathieu@14 186
mathieu@14 187 %% Producing a "piano roll" visualization
mathieu@14 188 f = figure(3);
mathieu@14 189 clf;
mathieu@14 190 set(gca,'YTick', []);
mathieu@14 191 grid on;
mathieu@14 192 set(f, 'Position', [0, 0, trackLength/512, 300]);
mathieu@14 193 for i=1:length(sceneObjects)
mathieu@14 194 text(0, i+.4, [num2str(sceneObjects(i).classLabel), ' '], 'HorizontalAlignment', 'right');
mathieu@14 195 end
mathieu@14 196
mathieu@14 197 for i=1:length(sceneSchedule)
mathieu@14 198 id = sceneSchedule(i).classId;
mathieu@14 199 if (sceneSchedule(i).isBackground)
mathieu@14 200 rectangle('Position', [0, id+.2, score.sceneDuration, .6], 'FaceColor', cmap(id,:));
mathieu@14 201 else
mathieu@14 202 t1 = sceneSchedule(i).position;
mathieu@14 203 rectangle('Position', [t1, id+.1, sceneSchedule(i).duration, .8], 'FaceColor', cmap(id,:));
mathieu@14 204 end
mathieu@14 205 end
mathieu@14 206 set(f, 'PaperPositionMode', 'auto');
mathieu@14 207 print ('-dpng', '-r150', [outputPath 'annotation/' outputFileName,'-piano_roll.png']);
mathieu@14 208 end
mathieu@14 209 end