Mercurial > hg > simscene-py
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