gregoirelafay@17: function [sceneSchedule] = generateScene (sceneSchedule,sceneObjects,score,inputPath,outputPath,outputFileName,figuresOption,timeMode,endCut,norm,sr,channelOption) 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 gregoire@16: % 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: 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 gregoire@16: 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 gregoire@16: gregoire@16: %% Init tab gregoire@16: gregoire@16: trackLength = sr*score.sceneDuration; gregoire@16: gregoire@16: tracks = zeros(length(sceneObjects), trackLength); mathieu@14: bg = zeros(trackLength, 1); 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) gregoire@24: if strcmp(sceneObjects(i).classLabel,'noise') gregoire@24: waves=score.backgrounds{1}{2}'; gregoire@24: else gregoire@24: waves = audioread([inputPath 'background/' sceneObjects(id).names{1}]); gregoire@24: [MinSizeWaves,indMinSizeWaves]=min(size(waves)); gregoire@24: if MinSizeWaves==2 gregoire@24: waves=mean(waves,indMinSizeWaves); gregoire@24: end gregoire@23: end mathieu@14: scale = 1; mathieu@14: if (i>1) gregoire@16: scale = adjustScaleForEBR(waves, bg, 1, sceneSchedule(i).ebr, 1, 0.01); mathieu@14: end gregoire@16: if (length(waves) < trackLength) mathieu@14: % need to loop the sample to fill the bg. Linear crossfade gregoire@19: fadeLen = sr; mathieu@14: fadeIn = transpose(0:1/fadeLen:1); mathieu@14: fadeOut = transpose(1:-1/fadeLen:0); gregoire@19: loop = waves; 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); gregoire@19: loop = scale * loop'; gregoire@19: startLoop=waves; gregoire@19: startLoop(length(startLoop)-fadeLen+1:length(startLoop)) = startLoop(length(startLoop)+1-fadeLen:length(startLoop)) .* fadeOut(1:fadeLen); gregoire@19: startLoop = scale * startLoop'; 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); gregoire@19: if l gregoire@19: tracks(id,t1:t2) = tracks(id,t1:t2) + loop(1:t2-t1+1); gregoire@19: else gregoire@19: tracks(id,t1:t2) = tracks(id,t1:t2) + startLoop(1:t2-t1+1); gregoire@19: end mathieu@14: end mathieu@14: else gregoire@16: dim = min(trackLength, length(waves)); gregoire@19: tracks(id,1:dim) = tracks(id,1:dim) + scale*waves(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; gregoire@16: waves = audioread([inputPath 'event/' sceneObjects(id).names{inst}]); gregoire@23: [MinSizeWaves,indMinSizeWaves]=min(size(waves)); gregoire@23: if MinSizeWaves==2 gregoire@23: waves=mean(waves,indMinSizeWaves); gregoire@23: end mathieu@14: pos = max(1,floor(sr*sceneSchedule(i).position)); mathieu@14: mathieu@14: switch timeMode mathieu@14: case {'replicate'} gregoire@16: if(length(waves)/sr - sceneSchedule(i).duration > 0.5) mathieu@14: endTime = round(sceneSchedule(i).duration*sr); mathieu@14: else gregoire@16: endTime = length(waves); mathieu@14: end mathieu@14: case {'abstract'} mathieu@14: endTime = round(sceneSchedule(i).duration*sr); mathieu@14: otherwise gregoire@16: endTime = length(waves); mathieu@14: end gregoire@16: mathieu@14: if endCut gregoire@16: pos2Test=pos; mathieu@14: else mathieu@14: gregoire@16: 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@31: mathieu@14: save ([outputPath 'annotation/' outputFileName '.mat'],'score', 'sceneObjects', 'sceneSchedule','dominantTrack', 'dominantObject','simulatedEBR'); mathieu@14: saveAnnotationTxt(sceneSchedule,outputPath,outputFileName); mathieu@14: gregoire@19: w = sum(tracks,1); gregoire@19: if norm %Normalize to [-norm,norm] gregoire@19: w = w*norm/max(abs(w)); gregoire@19: end gregoire@19: gregoirelafay@26: audiowrite([outputPath 'sound/' outputFileName '.wav'],w,sr); gregoire@19: gregoirelafay@17: switch channelOption gregoire@19: case 1 gregoirelafay@17: if norm %Normalize to [-norm,norm] gregoire@19: tracks = tracks*norm/max(abs(sum(tracks,1))); gregoirelafay@17: end gregoire@19: audiowrite([outputPath 'sound/' outputFileName '_channel_split' '.wav'],tracks',sr); gregoirelafay@17: case 2 gregoire@19: if norm %Normalize to [-norm,norm] mathieu@34: tracks = tracks*norm/(1.05*max(abs(sum(tracks,1)))); gregoirelafay@17: end gregoirelafay@17: for jj=1:size(tracks,1) gregoire@19: audiowrite([outputPath 'sound/' outputFileName '_channel_' num2str(jj) '_class_' sceneObjects(jj).classLabel '.wav'],tracks(jj,:),sr); gregoirelafay@17: end gregoire@16: end gregoire@19: gregoire@16: gregoire@16: if figuresOption mathieu@34: settingFigure.cmap = pleasantnessColormap(sceneObjects); mathieu@34: if any(~sum(settingFigure.cmap, 2)) mathieu@34: fprintf(2, 'Unable to get some of the pleasantness tags, revert to randomized colors'); mathieu@34: settingFigure.cmap = randomColormap(sceneObjects); mathieu@34: end gregoire@16: settingFigure.width=29.7; % cm gregoire@16: settingFigure.height=21; % cm gregoire@16: settingFigure.FontSize=16; gregoire@16: settingFigure.sr=sr; gregoire@16: settingFigure.sceneDuration=score.sceneDuration; mathieu@14: mathieu@34: nbBg = 0; mathieu@34: for k=1:length(sceneObjects) mathieu@34: if sceneObjects(k).isBackground mathieu@34: nbBg = nbBg+1; mathieu@34: bgo(nbBg, :) = resample(abs(tracks(k, :)), 1, 44100); mathieu@34: end mathieu@34: end mathieu@34: mathieu@34: mathieu@34: mathieu@34: [~, bgOrder] = sort(mean(bgo, 2)./median(bgo, 2)); mathieu@34: [~, eventOrder] = sort(sum(tracks(nbBg+1:end,:)==0, 2)); mathieu@34: trackOrder = [bgOrder; eventOrder+nbBg]; mathieu@34: tracks = tracks(trackOrder, :); mathieu@34: sceneObjects = sceneObjects(trackOrder); mathieu@34: settingFigure.cmap = settingFigure.cmap(trackOrder, :); mathieu@34: gregoire@16: coloredSpectrumVisualization(tracks,1,settingFigure,figuresOption,[outputPath 'annotation/' outputFileName,'-spectrum.png']); gregoire@16: timeDomainVisualization(tracks,2,settingFigure,figuresOption,[outputPath 'annotation/' outputFileName,'-timeDomain.png']); gregoire@16: pianoRollVisualization(sceneObjects,sceneSchedule,score,3,settingFigure,figuresOption,[outputPath 'annotation/' outputFileName,'-pianoRoll.png']) mathieu@14: end