mathieu@14: function [w,sceneSchedule] = generateScene (sceneSchedule,sceneObjects,score,inputPath,outputPath,outputFileName,displayFigures,timeMode,endCut) mathieu@14: % function [w,sceneSchedule] = generateScene (sceneSchedule,sceneObjects,score,inputPath,outputPath,outputFileName,displayFigures,timeMode,endCut) mathieu@14: % This function does the actual job of loading, scaling, positioning and mathieu@14: % mixing the various samples to generate a scene, based on the mathieu@14: % specifications given by its parameters. mathieu@14: mathieu@14: % This program was written by Mathias Rossignol & Grégoire Lafay mathieu@14: % is Copyright (C) 2015 IRCAM mathieu@14: % mathieu@14: % This program is free software: you can redistribute it and/or modify it mathieu@14: % under the terms of the GNU General Public License as published by the Free mathieu@14: % Software Foundation, either version 3 of the License, or (at your option) mathieu@14: % any later version. mathieu@14: % mathieu@14: % This program is distributed in the hope that it will be useful, but mathieu@14: % WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY mathieu@14: % or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License mathieu@14: % for more details. mathieu@14: % mathieu@14: % You should have received a copy of the GNU General Public License along mathieu@14: % with this program. If not, see . mathieu@14: mathieu@14: sr = 44100; mathieu@14: trackLength = sr*score.sceneDuration; mathieu@14: nbTracks = length(sceneObjects); mathieu@14: mathieu@14: % All instances of one sample will appear on a given track, before mathieu@14: % everything is mixed together, making it possible to apply track-specific mathieu@14: % effects or generate nice colorful representations mathieu@14: tracks = zeros(length(sceneObjects), trackLength); mathieu@14: mathieu@14: % We also generate a "bg" track with all background samples, against which mathieu@14: % the snr of fg sounds will be evaluated mathieu@14: bg = zeros(trackLength, 1); mathieu@14: mathieu@14: %% Preloading all wav samples into memory mathieu@14: waves = {}; mathieu@14: for i=1:nbTracks mathieu@14: if(sceneObjects(i).isBackground) mathieu@14: path = [inputPath,'background/']; mathieu@14: else mathieu@14: path = [inputPath,'event/']; mathieu@14: end mathieu@14: sample = dir([path '*wav']); mathieu@14: sampleId = find(cellfun('isempty',regexpi({sample.name},sceneObjects(i).query,'match'))==0); mathieu@14: for j=1:length(sampleId) mathieu@14: % this test is necessary because mp3 conversion does not mathieu@14: % always maintain exact length, and wavread will crash if asked to mathieu@14: % read too many samples. mathieu@14: waves{i}{j}= wavread([path sample(sampleId(j)).name]); mathieu@14: if(size(waves{i}{j},2)==2) mathieu@14: waves{i}{j}= mean(waves{i}{j},2); mathieu@14: end mathieu@14: waves{i}{j} = waves{i}{j}(:); mathieu@14: end mathieu@14: end mathieu@14: mathieu@14: dominantTrack = zeros(1,trackLength) + 1; mathieu@14: dominantObject = zeros(1,trackLength) + 1; mathieu@14: dominantEnergy = zeros(1,trackLength); mathieu@14: simulatedEBR = zeros(length(sceneSchedule),2); mathieu@14: objNum = 1; mathieu@14: mathieu@14: %% Create sceneSchedule mathieu@14: id2remove=[]; mathieu@14: for i=1:length(sceneSchedule) mathieu@14: id = sceneSchedule(i).classId; mathieu@14: if (sceneSchedule(i).isBackground) mathieu@14: scale = 1; mathieu@14: if (i>1) mathieu@14: scale = adjustScaleForEBR(waves{id}{1}, bg, 1, sceneSchedule(i).ebr, 1, 0.01); mathieu@14: end mathieu@14: if (length(waves{id}{1}) < trackLength) mathieu@14: % need to loop the sample to fill the bg. Linear crossfade mathieu@14: loop = waves{id}{1}; mathieu@14: fadeLen = 20000; mathieu@14: fadeIn = transpose(0:1/fadeLen:1); mathieu@14: fadeOut = transpose(1:-1/fadeLen:0); mathieu@14: loop(1:fadeLen) = loop(1:fadeLen) .* fadeIn(1:fadeLen); mathieu@14: loop(length(loop)-fadeLen+1:length(loop)) = loop(length(loop)+1-fadeLen:length(loop)) .* fadeOut(1:fadeLen); mathieu@14: loop = scale * loop.'; mathieu@14: for l=0:floor(trackLength/(length(loop)-fadeLen)) mathieu@14: t1 = 1+l*(length(loop)-fadeLen); mathieu@14: t2 = min(length(bg), t1+length(loop)-1); mathieu@14: tracks(id,t1:t2) = tracks(id,t1:t2) + loop(1:t2-t1+1); mathieu@14: end mathieu@14: else mathieu@14: dim = min(trackLength, length(waves{id}{1})); mathieu@14: tracks(id,1:dim) = tracks(id,1:dim) + scale*(waves{id}{1}(1:dim).'); mathieu@14: end mathieu@14: if (i==1) mathieu@14: bg = tracks(id,:); mathieu@14: else mathieu@14: bg = bg+tracks(id,:); mathieu@14: end mathieu@14: else mathieu@14: objNum = objNum+1; mathieu@14: inst = sceneSchedule(i).instance; mathieu@14: pos = max(1,floor(sr*sceneSchedule(i).position)); mathieu@14: mathieu@14: switch timeMode mathieu@14: case {'replicate'} mathieu@14: if(length(waves{id}{inst})/sr - sceneSchedule(i).duration > 0.5) mathieu@14: endTime = round(sceneSchedule(i).duration*sr); mathieu@14: else mathieu@14: endTime = length(waves{id}{inst}); mathieu@14: end mathieu@14: case {'abstract'} mathieu@14: endTime = round(sceneSchedule(i).duration*sr); mathieu@14: otherwise mathieu@14: endTime = length(waves{id}{inst}); mathieu@14: end mathieu@14: mathieu@14: if endCut mathieu@14: pos2Test=pos; mathieu@14: else mathieu@14: mathieu@14: pos2Test=pos+endTime-1; mathieu@14: end mathieu@14: mathieu@14: if(pos2TestdominantEnergy(pos+t) mathieu@14: dominantObject(pos+round(t*(t2-pos)/length(bgEnergy))) = objNum; mathieu@14: dominantEnergy(pos+round(t*(t2-pos)/length(bgEnergy))) = evEnergy(t); mathieu@14: end mathieu@14: end mathieu@14: dominantObject(min(find(dominantObject==objNum)):max(find(dominantObject==objNum))) = objNum; mathieu@14: dominantTrack(dominantObject==objNum) = id; mathieu@14: mathieu@14: tracks(id, pos:t2) = tracks(id, pos:t2) + scale*wav2use.'; mathieu@14: %% Store EBR and event locations mathieu@14: simulatedEBR(i,1) = ebr(tracks(id, pos:t2),tracks(1, pos:t2)); mathieu@14: simulatedEBR(i,2)=pos; mathieu@14: else mathieu@14: id2remove=[id2remove i]; mathieu@14: end mathieu@14: end mathieu@14: end mathieu@14: mathieu@14: sceneSchedule(id2remove)=[]; mathieu@14: % checkClassPresence(sceneSchedule,sceneObjects); mathieu@14: mathieu@14: save ([outputPath 'annotation/' outputFileName '.mat'],'score', 'sceneObjects', 'sceneSchedule','dominantTrack', 'dominantObject','simulatedEBR'); mathieu@14: saveAnnotationTxt(sceneSchedule,outputPath,outputFileName); mathieu@14: mathieu@14: w = sum(tracks); mathieu@14: w = w/(max(abs(w))+0.001); %Normalize to [-1,1] mathieu@14: mathieu@14: if displayFigures mathieu@14: cmap = generateColormap(sceneObjects); mathieu@14: mathieu@14: timeDomainVisualization(tracks, cmap, 1, 10000, 1, [outputPath 'annotation/' outputFileName,'-timeDomain.png']); mathieu@14: mathieu@14: % Producing a colored spectrum visualization mathieu@14: for i=1:nbTracks mathieu@14: spec = log(1+abs(spectrogram(tracks(i,:), hanning(2048), 1024, 2048))); mathieu@14: spec = min(1, spec ./ max(spec(:))); mathieu@14: spec = spec(1:400,:); mathieu@14: spec = flipud(spec); mathieu@14: for colorComp=1:3 mathieu@14: if (i==1) mathieu@14: img(:,:,colorComp) = cmap(i,colorComp)*spec; mathieu@14: else mathieu@14: img(:,:,colorComp) = img(:,:,colorComp)+cmap(i,colorComp)*spec; mathieu@14: end mathieu@14: end mathieu@14: end mathieu@14: img = img/max(img(:)); mathieu@14: f = figure(2); mathieu@14: clf; mathieu@14: set(gca,'YTick', []); mathieu@14: set(f, 'Position', [0, 0, 2*size(img,1), 600]); mathieu@14: imagesc(img); mathieu@14: imwrite(img, [outputPath 'annotation/' outputFileName,'-spectrum.png'], 'png'); mathieu@14: mathieu@14: mathieu@14: %% Producing a "piano roll" visualization mathieu@14: f = figure(3); mathieu@14: clf; mathieu@14: set(gca,'YTick', []); mathieu@14: grid on; mathieu@14: set(f, 'Position', [0, 0, trackLength/512, 300]); mathieu@14: for i=1:length(sceneObjects) mathieu@14: text(0, i+.4, [num2str(sceneObjects(i).classLabel), ' '], 'HorizontalAlignment', 'right'); mathieu@14: end mathieu@14: mathieu@14: for i=1:length(sceneSchedule) mathieu@14: id = sceneSchedule(i).classId; mathieu@14: if (sceneSchedule(i).isBackground) mathieu@14: rectangle('Position', [0, id+.2, score.sceneDuration, .6], 'FaceColor', cmap(id,:)); mathieu@14: else mathieu@14: t1 = sceneSchedule(i).position; mathieu@14: rectangle('Position', [t1, id+.1, sceneSchedule(i).duration, .8], 'FaceColor', cmap(id,:)); mathieu@14: end mathieu@14: end mathieu@14: set(f, 'PaperPositionMode', 'auto'); mathieu@14: print ('-dpng', '-r150', [outputPath 'annotation/' outputFileName,'-piano_roll.png']); mathieu@14: end mathieu@14: end