changeset 16:92f73423eb37

update figure generation
author GregoireLafay <gregoire.lafay@irccyn.ec-nantes.fr>
date Wed, 06 Jan 2016 18:04:24 +0100
parents 69410ac2a50d
children fc99c676c280
files nonExposed/generateScene.m nonExposed/getBackground.m nonExposed/getEvent.m nonExposed/getSampleInfo.m nonExposed/getSceneSchedule.m nonExposed/timeDomainVisualization.m simScene.m
diffstat 7 files changed, 128 insertions(+), 153 deletions(-) [+]
line wrap: on
line diff
--- a/nonExposed/generateScene.m	Tue Dec 08 10:45:15 2015 +0100
+++ b/nonExposed/generateScene.m	Wed Jan 06 18:04:24 2016 +0100
@@ -1,8 +1,8 @@
-function [w,sceneSchedule] = generateScene (sceneSchedule,sceneObjects,score,inputPath,outputPath,outputFileName,displayFigures,timeMode,endCut)
+function [w,sceneSchedule] = generateScene (sceneSchedule,sceneObjects,score,inputPath,outputPath,outputFileName,figuresOption,timeMode,endCut,norm,sr)
 % function [w,sceneSchedule] = generateScene (sceneSchedule,sceneObjects,score,inputPath,outputPath,outputFileName,displayFigures,timeMode,endCut)
 % This function does the actual job of loading, scaling, positioning and
 % mixing the various samples to generate a scene, based on the
-% specifications given by its parameters. 
+% specifications given by its parameters.
 
 % This program was written by Mathias Rossignol & Grégoire Lafay
 % is Copyright (C) 2015 IRCAM <http://www.ircam.fr>
@@ -20,42 +20,22 @@
 % You should have received a copy of the GNU General Public License along
 % with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-sr = 44100;
-trackLength = sr*score.sceneDuration;
-nbTracks = length(sceneObjects);
 
 % All instances of one sample will appear on a given track, before
 % everything is mixed together, making it possible to apply track-specific
 % effects or generate nice colorful representations
-tracks = zeros(length(sceneObjects), trackLength);
+
 
 % We also generate a "bg" track with all background samples, against which
 % the snr of fg sounds will be evaluated
+
+%% Init tab
+
+trackLength = sr*score.sceneDuration;
+
+tracks = zeros(length(sceneObjects), trackLength);
 bg = zeros(trackLength, 1);
 
-%% Preloading all wav samples into memory
-waves = {};
-for i=1:nbTracks
-    if(sceneObjects(i).isBackground)
-        path = [inputPath,'background/'];
-    else
-        path = [inputPath,'event/'];
-    end
-    sample = dir([path '*wav']);
-    sampleId = find(cellfun('isempty',regexpi({sample.name},sceneObjects(i).query,'match'))==0);
-    for j=1:length(sampleId)
-        % this test is necessary because mp3 conversion does not
-        % always maintain exact length, and wavread will crash if asked to
-        % read too many samples.
-%         waves{i}{j}= wavread([path sample(sampleId(j)).name]);
-        waves{i}{j}= audioread([path sample(sampleId(j)).name]);
-        if(size(waves{i}{j},2)==2)
-            waves{i}{j}= mean(waves{i}{j},2);
-        end
-        waves{i}{j} = waves{i}{j}(:);
-    end
-end
-
 dominantTrack = zeros(1,trackLength) + 1;
 dominantObject = zeros(1,trackLength) + 1;
 dominantEnergy = zeros(1,trackLength);
@@ -67,13 +47,14 @@
 for i=1:length(sceneSchedule)
     id = sceneSchedule(i).classId;
     if (sceneSchedule(i).isBackground)
+        waves = audioread([inputPath 'background/' sceneObjects(id).names{1}]);
         scale = 1;
         if (i>1)
-            scale = adjustScaleForEBR(waves{id}{1}, bg, 1, sceneSchedule(i).ebr, 1, 0.01);
+            scale = adjustScaleForEBR(waves, bg, 1, sceneSchedule(i).ebr, 1, 0.01);
         end
-        if (length(waves{id}{1}) < trackLength)
+        if (length(waves) < trackLength)
             % need to loop the sample to fill the bg. Linear crossfade
-            loop = waves{id}{1};
+            loop = waves;
             fadeLen = 20000;
             fadeIn = transpose(0:1/fadeLen:1);
             fadeOut = transpose(1:-1/fadeLen:0);
@@ -86,8 +67,8 @@
                 tracks(id,t1:t2) = tracks(id,t1:t2) + loop(1:t2-t1+1);
             end
         else
-            dim = min(trackLength, length(waves{id}{1}));
-            tracks(id,1:dim) = tracks(id,1:dim) + scale*(waves{id}{1}(1:dim).');
+            dim = min(trackLength, length(waves));
+            tracks(id,1:dim) = tracks(id,1:dim) + scale*(waves(1:dim).');
         end
         if (i==1)
             bg = tracks(id,:);
@@ -97,31 +78,32 @@
     else
         objNum = objNum+1;
         inst = sceneSchedule(i).instance;
+        waves = audioread([inputPath 'event/' sceneObjects(id).names{inst}]);
         pos = max(1,floor(sr*sceneSchedule(i).position));
         
         switch timeMode
             case {'replicate'}
-                if(length(waves{id}{inst})/sr - sceneSchedule(i).duration > 0.5)
+                if(length(waves)/sr - sceneSchedule(i).duration > 0.5)
                     endTime = round(sceneSchedule(i).duration*sr);
                 else
-                    endTime = length(waves{id}{inst});
+                    endTime = length(waves);
                 end
             case {'abstract'}
                 endTime = round(sceneSchedule(i).duration*sr);
             otherwise
-                endTime = length(waves{id}{inst});
+                endTime = length(waves);
         end
-  
+        
         if endCut
-                pos2Test=pos;
+            pos2Test=pos;
         else
             
-                pos2Test=pos+endTime-1;
+            pos2Test=pos+endTime-1;
         end
         
         if(pos2Test<round(sceneObjects(sceneSchedule(i).classId).trackLength*sr))
             t2 = min(pos+endTime-1, round(sceneObjects(sceneSchedule(i).classId).trackLength*sr));
-            wav2use=waves{id}{inst}(1:t2-pos+1);
+            wav2use=waves(1:t2-pos+1);
             sceneSchedule(i).duration=length(wav2use)/sr;
             scale = adjustScaleForEBR(wav2use, bg, pos, sceneSchedule(i).ebr, 1, 0.01);
             
@@ -154,57 +136,22 @@
 save ([outputPath 'annotation/' outputFileName '.mat'],'score', 'sceneObjects', 'sceneSchedule','dominantTrack', 'dominantObject','simulatedEBR');
 saveAnnotationTxt(sceneSchedule,outputPath,outputFileName);
 
-w = sum(tracks);
-w = w/(max(abs(w))+0.001); %Normalize to [-1,1]
+w = sum(tracks,1);
 
-if displayFigures
-    cmap = generateColormap(sceneObjects);
+if norm
+    w = w/(max(abs(w)))*norm; %Normalize to [-norm,norm]
+end
+
+if figuresOption
+    settingFigure.cmap = generateColormap(sceneObjects);
+    settingFigure.width=29.7; % cm
+    settingFigure.height=21; % cm
+    settingFigure.FontSize=16;
+    settingFigure.sr=sr;
+    settingFigure.sceneDuration=score.sceneDuration;
     
-    timeDomainVisualization(tracks, cmap, 1, 10000, 1, [outputPath 'annotation/' outputFileName,'-timeDomain.png']);
-    
-    % Producing a colored spectrum visualization
-    for i=1:nbTracks
-        spec = log(1+abs(spectrogram(tracks(i,:), hanning(2048), 1024, 2048)));
-        spec = min(1, spec ./ max(spec(:)));
-        spec = spec(1:400,:);
-        spec = flipud(spec);
-        for colorComp=1:3
-            if (i==1)
-                img(:,:,colorComp) = cmap(i,colorComp)*spec;
-            else
-                img(:,:,colorComp) = img(:,:,colorComp)+cmap(i,colorComp)*spec;
-            end
-        end
-    end
-    img = img/max(img(:));
-    f = figure(2);
-    clf;
-    set(gca,'YTick', []);
-    set(f, 'Position', [0, 0, 2*size(img,1), 600]);
-    imagesc(img);
-    imwrite(img, [outputPath 'annotation/' outputFileName,'-spectrum.png'], 'png');
-    
-    
-    %% Producing a "piano roll" visualization
-    f = figure(3);
-    clf;
-    set(gca,'YTick', []);
-    grid on;
-    set(f, 'Position', [0, 0, trackLength/512, 300]);
-    for i=1:length(sceneObjects)
-        text(0, i+.4, [num2str(sceneObjects(i).classLabel), '  '], 'HorizontalAlignment', 'right');
-    end
-    
-    for i=1:length(sceneSchedule)
-        id = sceneSchedule(i).classId;
-        if (sceneSchedule(i).isBackground)
-            rectangle('Position', [0, id+.2, score.sceneDuration, .6], 'FaceColor', cmap(id,:));
-        else
-            t1 = sceneSchedule(i).position;
-            rectangle('Position', [t1, id+.1, sceneSchedule(i).duration, .8], 'FaceColor', cmap(id,:));
-        end
-    end
-    set(f, 'PaperPositionMode', 'auto');
-    print ('-dpng', '-r150', [outputPath 'annotation/' outputFileName,'-piano_roll.png']);
+    coloredSpectrumVisualization(tracks,1,settingFigure,figuresOption,[outputPath 'annotation/' outputFileName,'-spectrum.png']);
+    timeDomainVisualization(tracks,2,settingFigure,figuresOption,[outputPath 'annotation/' outputFileName,'-timeDomain.png']);
+    pianoRollVisualization(sceneObjects,sceneSchedule,score,3,settingFigure,figuresOption,[outputPath 'annotation/' outputFileName,'-pianoRoll.png'])
 end
 end
--- a/nonExposed/getBackground.m	Tue Dec 08 10:45:15 2015 +0100
+++ b/nonExposed/getBackground.m	Wed Jan 06 18:04:24 2016 +0100
@@ -1,4 +1,4 @@
-function [sceneSchedule,sceneObjects]=getBackground(inputPath,score)
+function [sceneSchedule,sceneObjects]=getBackground(inputPath,score,eventInfo,sr)
 
 % This program was written by Mathias Rossignol & Grégoire Lafay
 % is Copyright (C) 2015 IRCAM <http://www.ircam.fr>
@@ -17,7 +17,7 @@
 % with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 for i=1:length(score.backgrounds)
-    sceneObjects(i) = getSampleInfo(score.backgrounds{i}{1},score.backgrounds{i}{2},'background',inputPath,score.sceneDuration);
+    sceneObjects(i) = getSampleInfo(score.backgrounds{i}{1},score.backgrounds{i}{2},'background',inputPath,score.sceneDuration,eventInfo,sr);
     sceneSchedule(i).classId=i;
     sceneSchedule(i).classLabel=score.backgrounds{i}{2};
     sceneSchedule(i).position=0;
--- a/nonExposed/getEvent.m	Tue Dec 08 10:45:15 2015 +0100
+++ b/nonExposed/getEvent.m	Wed Jan 06 18:04:24 2016 +0100
@@ -1,4 +1,4 @@
-function [sceneSchedule,sceneObjects]=getEvent(sceneSchedule,sceneObjects,inputPath,score,timeMode,ebrMode,randomFlag)
+function [sceneSchedule,sceneObjects]=getEvent(sceneSchedule,sceneObjects,inputPath,score,timeMode,ebrMode,randomFlag,eventInfo,sr)
 
 % This program was written by Mathias Rossignol & Grégoire Lafay
 % is Copyright (C) 2015 IRCAM <http://www.ircam.fr>
@@ -28,7 +28,7 @@
     settings.ebr_mean = score.events{ii}{3};
     settings.ebr_std = score.events{ii}{4};
     
-    sceneObjects(settings.classId) = getSampleInfo(score.events{ii}{1}, score.events{ii}{2},'event',inputPath,score.events{ii}{8});
+    sceneObjects(settings.classId) = getSampleInfo(score.events{ii}{1}, score.events{ii}{2},'event',inputPath,score.events{ii}{8},eventInfo,sr);
     settings.duration_mean = mean(sceneObjects(settings.classId).endTimes-sceneObjects(settings.classId).startTimes);
     settings.duration_std =  std(sceneObjects(settings.classId).endTimes-sceneObjects(settings.classId).startTimes);
     settings.mean_time_between_instances = score.events{ii}{5};
--- a/nonExposed/getSampleInfo.m	Tue Dec 08 10:45:15 2015 +0100
+++ b/nonExposed/getSampleInfo.m	Wed Jan 06 18:04:24 2016 +0100
@@ -1,4 +1,4 @@
-function [o] = getSampleInfo(label,query,sampleType,inputData,trackLength)
+function [o] = getSampleInfo(label,query,sampleType,inputData,trackLength,eventInfo,sr)
 
 % This program was written by Mathias Rossignol & Grégoire Lafay
 % is Copyright (C) 2015 IRCAM <http://www.ircam.fr>
@@ -20,24 +20,33 @@
 o.classLabel = label;
 o.startTimes = [];
 o.endTimes = [];
+o.names={};
 o.query= query;
 o.trackLength=trackLength;
 path = [inputData sampleType '/'];
 
-if ~exist(path, 'dir')
-    error(['Could not find local dir ',path,'\n']);
+if any(strcmp(query,{eventInfo.query}))
+    o.startTimes=eventInfo(strcmp(query,{eventInfo.query})).startTimes;
+    o.endTimes=eventInfo(strcmp(query,{eventInfo.query})).endTimes;
+    o.names=eventInfo(strcmp(query,{eventInfo.query})).names;
+else
+    
+    if ~exist(path, 'dir')
+        error(['Could not find local dir ',path,'\n']);
+    end
+    
+    samples = dir([path '*wav']);
+    samplesInd = find(cellfun('isempty',regexpi({samples.name},query,'match'))==0);
+    
+    for ii=1:length(samplesInd)
+        samplesInfo=audioinfo([path,'/',samples(samplesInd(ii)).name]);
+        
+        if sr~=samplesInfo.SampleRate
+            error('Sample Rate must be 44100')
+        end
+        
+        o.startTimes(end+1) = 0;
+        o.endTimes(end+1) = samplesInfo.TotalSamples/samplesInfo.SampleRate;
+        o.names{end+1}=samples(samplesInd(ii)).name;
+    end
 end
-
-samples = dir([path '*wav']);
-samplesInd = find(cellfun('isempty',regexpi({samples.name},query,'match'))==0);
-
-for ii=1:length(samplesInd)
-%     [sampleSize,sr]=wavread([path,'/',samples(samplesInd(ii)).name],'size');
-    samplesInfo=audioinfo([path,'/',samples(samplesInd(ii)).name]);
-    sampleSize = samplesInfo.TotalSamples';
-    sr = samplesInfo.SampleRate;
-    
-    o.startTimes(end+1) = 0;
-    o.endTimes(end+1) = sampleSize(1)/sr;
-end
-
--- a/nonExposed/getSceneSchedule.m	Tue Dec 08 10:45:15 2015 +0100
+++ b/nonExposed/getSceneSchedule.m	Wed Jan 06 18:04:24 2016 +0100
@@ -22,10 +22,21 @@
     sceneSchedule(settings.schedPos).ebr= settings.ebr_mean+randn*settings.ebr_std;
 end
 
-if settings.randomFlag % Random choice of sample
-    inst = randi(length(sceneObjects(settings.classId).startTimes));
-else % Choose the sample closest in duration to the annotation.
-    [~,inst] = min(abs(sceneObjects(settings.classId).endTimes-sceneObjects(settings.classId).startTimes-(settings.end_times(indReplicate)-settings.start_times(indReplicate))));
+switch settings.randomFlag
+    case {'random'} % Random choice of sample
+        inst = randi(length(sceneObjects(settings.classId).startTimes));
+    case {'random-unique'} % Random choice of sample without repetition
+        instances=[sceneSchedule(1:end-1).instance];
+        instanceDone=instances([sceneSchedule(1:end-1).classId]==length(sceneObjects));
+        inst=1:length(sceneObjects(end).endTimes);
+        inst(arrayfun(@(x) any(instanceDone==x),inst))=[];
+        if isempty(inst)
+            error(['using samplechoice : random-unique; Not enough isolated samples for the class' sceneObjects(end).classLabel])
+        else
+            inst=inst(randperm(length(inst),1));
+        end
+    case {'close'} % Choose the sample closest in duration to the annotation.
+        [~,inst] = min(abs(sceneObjects(settings.classId).endTimes-sceneObjects(settings.classId).startTimes-(settings.end_times(indReplicate)-settings.start_times(indReplicate))));
 end
 
 switch settings.timeMode
--- a/nonExposed/timeDomainVisualization.m	Tue Dec 08 10:45:15 2015 +0100
+++ b/nonExposed/timeDomainVisualization.m	Wed Jan 06 18:04:24 2016 +0100
@@ -1,4 +1,4 @@
-function status = timeDomainVisualization (tracks, cmap, figNum, maxWidth, lineThickness, fileName)
+function status = timeDomainVisualization(tracks,figNum,settingFigure,figuresOption,fileName)
 
 % This program was written by Mathias Rossignol & Grégoire Lafay
 % is Copyright (C) 2015 IRCAM <http://www.ircam.fr>
@@ -16,45 +16,42 @@
 % You should have received a copy of the GNU General Public License along
 % with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-nbTracks = size(tracks,1);
-trackLength = length(tracks(1,:));
-
 % Producing a time domain visualization
-wSize = 8192;
-wStep = 512;
-for t=1:nbTracks
-    for i=0:ceil((trackLength-wSize)/wStep)
+step=0.5; % seconds
+wStep = round(step*settingFigure.sr);
+wSize = wStep*2;
+for t=1:size(tracks,1);
+    for i=0:floor((size(tracks,2)-wSize)/wStep)
         % Not really power, but more nicely additive, better suited for
         % this representation I think
-        powers(i+1,t) = norm(tracks(t,i*wStep+1:min(trackLength, i*wStep+wSize)));
+        powers(i+1,t) = norm(tracks(t,i*wStep+1:min(size(tracks,2), i*wStep+wSize)));
     end
 end
 
 powers(powers<max(powers(:))/500) = 0;
 
+switch figuresOption
+    case 1
+       f=figure('Visible', 'off');
+    case 2
+       f=figure(figNum);
+end
 
-% Screen res is ~90dpi, print res is 150dpi, hence the " /1.6 "
-imgWidth = min(maxWidth, 2*size(powers,1)) / 1.6;
 
-% Displayed version
-f=figure(figNum);
 clf;
-h=area(powers,'LineWidth', lineThickness/1.6, 'EdgeColor', [.3, .3, .3]);
-set(gca,'YTick', []);
-set(f, 'Position', [0, 0, imgWidth, 400],'Visible', 'off');
-colormap(cmap);
+area(powers,'LineWidth', 1/1.6, 'EdgeColor', [.3, .3, .3]);
+xlim([0 size(powers,1)])
+xtick=0:round(20/step):size(powers,1); % every 20 sec
+set(gca,'YTick', [],'YTicklabel', [],'xtick',xtick,'xticklabel',xtick*step);
+xlabel('time (sec)')
 
-% Version saved to graphic file
-f = figure(1000);
-clf;
-h = area(powers,'LineWidth', lineThickness/1.6, 'EdgeColor', [.3, .3, .3]);
-set(gca,'YTick', []);
-colormap(cmap);
-set(f, 'Visible', 'off');
-set(f, 'Position', [0, 0, imgWidth, 400]);
-set(f, 'PaperPositionMode', 'auto');
-print ('-dpng', '-r150', fileName);
+set(f,'PaperUnits','centimeters')
+set(f,'PaperPositionMode','manual')
+set(f,'papersize',[settingFigure.width,settingFigure.height])
+set(f,'paperposition',[0,0,settingFigure.width,settingFigure.height])
+set(findall(f,'-property','FontSize'),'FontSize',settingFigure.FontSize)
+set(findall(f,'-property','FontName'),'FontName','Arial')
 
-status = 1;
+print(f,fileName,'-dpng')
 
 end
--- a/simScene.m	Tue Dec 08 10:45:15 2015 +0100
+++ b/simScene.m	Wed Jan 06 18:04:24 2016 +0100
@@ -100,13 +100,16 @@
 %                       or 'replicate', this parameter is the path to the wav 
 %                       file of the reference scene sampled at 44100 Hz.
 %  
-%  - displayFigures: Boolean (default 0), save pictures (piano roll, time 
-%                    domain stacked visualization, overlaid spectrogram)
-% 
+%  - figuresOption: (default 1) save and show pictures (piano roll, time domain stacked visualization, overlaid spectrogram)
+%             0: don't save or display pictures
+%             1: save pictures without displaying them
+%             2: save and display pictures
+%
 %  - outputFileName: name of generated files with no extension
 %  
 %  - sampleChoice: method for choosing sample to schedule within a track
 %  		'random': unconstrained sampling
+%       'random-unique': unconstrained sampling with no sample repetition
 %  		'close': choose among the sampling dataset the sample that 
 %                has the closest duration to the reference one. 
 %                This mode is available only for the replicate timeMode.
@@ -152,7 +155,9 @@
 
 addpath(genpath('nonExposed'));
 
-[timeMode,ebrMode,instanceAnnotFile,instanceAudioFile,displayFigures,sampleChoice,outputFileName,minSpace,endCut]=process_options(varargin,'timeMode','generate','ebrMode','generate','instanceAnnotFile','none','instanceAudioFile','none','displayFigures','1','sampleChoice','random','outputFileName','simulatedScene','minSpace',-1,'endCut',0);
+[timeMode,ebrMode,instanceAnnotFile,instanceAudioFile,figuresOption,sampleChoice,outputFileName,minSpace,endCut,eventInfoPath,norm]=process_options(varargin,'timeMode','generate','ebrMode','generate','instanceAnnotFile','none','instanceAudioFile','none','figuresOption',1,'sampleChoice','random','outputFileName','simulatedScene','minSpace',-1,'endCut',0,'eventInfoPath','','norm',0);
+
+sr=44100;
 
 check_options(timeMode,ebrMode,score)
 
@@ -172,8 +177,15 @@
 end
 
 %% Get sceneSchedule and sceneObjects
-[sceneSchedule,sceneObjects]=getBackground(inputPath,score);
-[sceneSchedule,sceneObjects]=getEvent(sceneSchedule,sceneObjects,inputPath,score,timeMode,ebrMode,strcmp(sampleChoice,'random'));
+
+if ~strcmp(eventInfoPath,'')
+    load(eventInfoPath);
+else
+    eventInfo{1}.query='null';
+end
+
+[sceneSchedule,sceneObjects]=getBackground(inputPath,score,eventInfo,sr);
+[sceneSchedule,sceneObjects]=getEvent(sceneSchedule,sceneObjects,inputPath,score,timeMode,ebrMode,sampleChoice,eventInfo,sr);
 
 %% Manage overlapping
 if minSpace>=0
@@ -192,7 +204,7 @@
     mkdir([outputPath,'annotation'])
 end
 
-[simsSceneWav,sceneSchedule] = generateScene(sceneSchedule,sceneObjects,score,inputPath,outputPath,outputFileName,displayFigures,timeMode,endCut);
+[simsSceneWav,sceneSchedule] = generateScene(sceneSchedule,sceneObjects,score,inputPath,outputPath,outputFileName,figuresOption,timeMode,endCut,norm,sr);
 
 %% Check simulated scene
 
@@ -203,6 +215,5 @@
 end
 
 %% Generate Sound
-% wavwrite(simsSceneWav,44100,[outputPath,'sound/',outputFileName,'.wav']);
-audiowrite([outputPath,'sound/',outputFileName,'.wav'],simsSceneWav,44100);
+audiowrite([outputPath,'sound/',outputFileName,'.wav'],simsSceneWav,sr);
 end