Mercurial > hg > simscene-py
diff simScene.m @ 14:b1901e8d8f5f
initial commit
author | Mathieu Lagrange <mathieu.lagrange@cnrs.fr> |
---|---|
date | Tue, 17 Mar 2015 09:34:13 +0100 |
parents | |
children | 69410ac2a50d |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/simScene.m Tue Mar 17 09:34:13 2015 +0100 @@ -0,0 +1,208 @@ +function [] = simScene(inputPath,outputPath,score,varargin) +% [] = simScene(inputPath,outputPath,score,[opts ... ]) +% +% Generate a simulated auditory scene by mixing randomly chosen samples. +% The samples and their mixing properties are chosen partially randomly +% following user-provided guidelines. +% +% Required input variables are: +% +% - inputPath: a dataset of isolated sound events and backgrounds +% respectively located in inputPat/event/ and +% inputPat/background +% +% - outputPath: the repository where simscene will write the simulated scene +% as well as the annotations +% +% - score: a structure describing the scene to simulate +% +% score.sceneDuration: length of the simulated scene in second +% +% score.backgrounds: Backgrounds are continuous sounds that keep going +% over the whole duration of the scene. Several background samples +% may be mixed together. If 'sceneDuration' is more than the +% natural length of one of the selected bg sounds, they will be +% looped as necessary -- that may not sound great, depending on the +% sound... The format of the 'background' field controlling their +% selection and use is: +% +% {{'<bg 1 label>','<bg 1 sampleId>', 1}, +% {'<bg 2 label>','<bg 2 sampleId>', <bg 2 snr>}...} +% +% The value of 'snr' is ignored for the first bg sound. For the +% following ones, it will be evaluated against the sum of the +% previous ones. The value of 'Label' is the label of the +% background track. Simscene will use the value 'sampleId' to load +% the background sample(s) located in inputpath/background. +% Simscene will only use background sample(s) having a name +% containing the value 'sampleId'. +% +% score.events: The 'events' is an array of cell arrays containg data use +% to simulated the scenes. Event contains the following data: +% +% {{'<event 1 label>', +% '<event 1 sampleId>', +% <event 1 ebr>, +% <event 1 ebr_stddev>, +% <event 1 mean_time_between_instances>, +% <event 1 time_between_instances_stddev>, +% <event 1 start_time>, +% <event 1 end_time>, +% <event 1 fade_in_time>, +% <event 1 fade_out_time>}, +% {'<event 2 ...> ...}, +% {'<event 3 ...> ...} +% ...} +% +% If <mean_time_between_instances> is 0, then it will be set to the +% sample length (so if <time_between_instances_stddev> is also 0, +% the sample will be looped). +% If <mean_time_between_instances> is -1, then the sound will be +% played just once. The considered EBR value is the maximum EBR +% of the fg sample relative to the bg on windows of 1000 samples. +% The considered bg for this is the mix of all specified bgs. +% +% This version of simscene allows a lot of options to be controlled, as +% optional 'name', value pairs from the 4th argument. Here is a brief +% description of the optional parameters: +% +% - timeMode: control a time spacing between events. +% 'generate' (default): values must be set for each track using the +% score control structure +% 'abstract': values are computed from an abstract representation of +% an existing acoustic scene given as parameter +% 'replicate': values are replicated from an existing acoustic scene +% given as parameter +% +% - ebrMode: control the Event to Background power level Ratio (EBR) of events. +% Possible options are: 'generate' (default), 'abstract', 'replicate', see above. +% +% If ebrMode is set to 'replicate' or 'abstract', and score.events exist, +% simScene will use the values <ebr> and <ebr_stddev> as offsets for +% the class <label>. +% If timeMode is set to 'abstract' and score.events exist, simScene will use +% the values <mean_time_between_instances> and <time_between_instances_stddev>. +% as offsets for the class <label>. +% If one of the mode is not set to 'generate' and score.events exist, SimScene +% will also use the values <start_time>, <end_time>, <fade_in_time>, <fade_out_time> +% and '<sampleId>' of score.events, provided they are not equal to 0 or +% empty. +% +% - instanceAnnotFile: if timeMode and / or ebrMode are set to 'abstract' +% or 'replicate', this parameter is the path to the +% annotation of the reference scene. Annotation must +% be provided as a Comma Separated Value (CSV) file +% with one event per line with class identifier as a +% string, onset and offset times in second as floating +% point value. +% +% - instanceAudioFile: if timeMode and / or ebrMode are set to 'abstract' +% 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) +% +% - outputFileName: name of generated files with no extension +% +% - sampleChoice: method for choosing sample to schedule within a track +% 'random': unconstrained sampling +% '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. +% +% - minSpace: floating point value (default -1: overlapping between events allowed): +% minimal spacing in seconds between successive events +% +% - endCut: Boolean (default 0): adjust the duration of the last sample of +% each track if the latter ends after the track duration. +% If 1, cut the last sample to the track duration. If +% 0, the last sample is removed. +% +% SceneSchedule and SceneObject: +% +% - sceneObjects: This vector will contain detailed information concerning +% all the samples selected to build this scene. +% +% - sceneSchedule: This vector will contain all scheduling information +% (i.e. what sample goes where, with what scaling factor). +% The sample indices stored in it refer to the position +% in the previous vector. +% +% SceneSchedule, SceneObject, as well as score are saved in the .mat +% annotation file. + +% This program was written by Mathias Rossignol & Grégoire Lafay +% is Copyright (C) 2015 IRCAM <http://www.ircam.fr> +% +% This program is free software: you can redistribute it and/or modify it +% under the terms of the GNU General Public License as published by the Free +% Software Foundation, either version 3 of the License, or (at your option) +% any later version. +% +% This program is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +% or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +% for more details. +% +% You should have received a copy of the GNU General Public License along +% with this program. If not, see <http://www.gnu.org/licenses/>. +% +% Uses Mark Paskin's process_options.m from KPMtools + +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); + +check_options(timeMode,ebrMode,score) + +%% Get score (only if at least one of the modes is not set to generate). +% Else use score inpu variable +if (~strcmp(timeMode,'generate') || ~strcmp(ebrMode,'generate')) + template=getTemplate(instanceAnnotFile,instanceAudioFile); + if isfield(score,'events') + score.events=addUserOffsets(template.class,score.events,timeMode,ebrMode); + else + warning('score.event is empty: score.event will be created from the scene to replicate'); + score.events=template.class; + end + if ~isfield(score,'sceneDuration') + score.sceneDuration=template.sceneDuration; + end +end + +%% Get sceneSchedule and sceneObjects +[sceneSchedule,sceneObjects]=getBackground(inputPath,score); +[sceneSchedule,sceneObjects]=getEvent(sceneSchedule,sceneObjects,inputPath,score,timeMode,ebrMode,strcmp(sampleChoice,'random')); + +%% Manage overlapping +if minSpace>=0 + [sceneSchedule] = manageOverlapping(sceneSchedule,minSpace); +end + + +%% Generate Scene +if (~exist(outputPath, 'dir')) + mkdir(outputPath) +end +if (~exist([outputPath,'annotation'], 'dir')) + mkdir([outputPath,'sound']) +end +if (~exist([outputPath,'annotation'], 'dir')) + mkdir([outputPath,'annotation']) +end + +[simsSceneWav,sceneSchedule] = generateScene(sceneSchedule,sceneObjects,score,inputPath,outputPath,outputFileName,displayFigures,timeMode,endCut); + +%% Check simulated scene + +checkClassPresence(sceneSchedule,sceneObjects); + +if minSpace>=0 + checkOverlapping(sceneSchedule,score.sceneDuration) +end + +%% Generate Sound +wavwrite(simsSceneWav,44100,[outputPath,'sound/',outputFileName,'.wav']); + +end