mathieu@14
|
1 function [] = simScene(inputPath,outputPath,score,varargin)
|
mathieu@14
|
2 % [] = simScene(inputPath,outputPath,score,[opts ... ])
|
mathieu@14
|
3 %
|
mathieu@14
|
4 % Generate a simulated auditory scene by mixing randomly chosen samples.
|
mathieu@14
|
5 % The samples and their mixing properties are chosen partially randomly
|
mathieu@14
|
6 % following user-provided guidelines.
|
mathieu@14
|
7 %
|
mathieu@14
|
8 % Required input variables are:
|
mathieu@14
|
9 %
|
mathieu@14
|
10 % - inputPath: a dataset of isolated sound events and backgrounds
|
mathieu@14
|
11 % respectively located in inputPat/event/ and
|
mathieu@14
|
12 % inputPat/background
|
mathieu@14
|
13 %
|
mathieu@14
|
14 % - outputPath: the repository where simscene will write the simulated scene
|
mathieu@14
|
15 % as well as the annotations
|
mathieu@14
|
16 %
|
mathieu@14
|
17 % - score: a structure describing the scene to simulate
|
mathieu@14
|
18 %
|
mathieu@14
|
19 % score.sceneDuration: length of the simulated scene in second
|
mathieu@14
|
20 %
|
mathieu@14
|
21 % score.backgrounds: Backgrounds are continuous sounds that keep going
|
mathieu@14
|
22 % over the whole duration of the scene. Several background samples
|
mathieu@14
|
23 % may be mixed together. If 'sceneDuration' is more than the
|
mathieu@14
|
24 % natural length of one of the selected bg sounds, they will be
|
mathieu@14
|
25 % looped as necessary -- that may not sound great, depending on the
|
mathieu@14
|
26 % sound... The format of the 'background' field controlling their
|
mathieu@14
|
27 % selection and use is:
|
mathieu@14
|
28 %
|
mathieu@14
|
29 % {{'<bg 1 label>','<bg 1 sampleId>', 1},
|
mathieu@14
|
30 % {'<bg 2 label>','<bg 2 sampleId>', <bg 2 snr>}...}
|
mathieu@14
|
31 %
|
mathieu@14
|
32 % The value of 'snr' is ignored for the first bg sound. For the
|
mathieu@14
|
33 % following ones, it will be evaluated against the sum of the
|
mathieu@14
|
34 % previous ones. The value of 'Label' is the label of the
|
mathieu@14
|
35 % background track. Simscene will use the value 'sampleId' to load
|
mathieu@14
|
36 % the background sample(s) located in inputpath/background.
|
mathieu@14
|
37 % Simscene will only use background sample(s) having a name
|
mathieu@14
|
38 % containing the value 'sampleId'.
|
mathieu@14
|
39 %
|
mathieu@14
|
40 % score.events: The 'events' is an array of cell arrays containg data use
|
mathieu@14
|
41 % to simulated the scenes. Event contains the following data:
|
mathieu@14
|
42 %
|
mathieu@14
|
43 % {{'<event 1 label>',
|
mathieu@14
|
44 % '<event 1 sampleId>',
|
mathieu@14
|
45 % <event 1 ebr>,
|
mathieu@14
|
46 % <event 1 ebr_stddev>,
|
mathieu@14
|
47 % <event 1 mean_time_between_instances>,
|
mathieu@14
|
48 % <event 1 time_between_instances_stddev>,
|
mathieu@14
|
49 % <event 1 start_time>,
|
mathieu@14
|
50 % <event 1 end_time>,
|
mathieu@14
|
51 % <event 1 fade_in_time>,
|
mathieu@14
|
52 % <event 1 fade_out_time>},
|
mathieu@14
|
53 % {'<event 2 ...> ...},
|
mathieu@14
|
54 % {'<event 3 ...> ...}
|
mathieu@14
|
55 % ...}
|
mathieu@14
|
56 %
|
mathieu@14
|
57 % If <mean_time_between_instances> is 0, then it will be set to the
|
mathieu@14
|
58 % sample length (so if <time_between_instances_stddev> is also 0,
|
mathieu@14
|
59 % the sample will be looped).
|
mathieu@14
|
60 % If <mean_time_between_instances> is -1, then the sound will be
|
mathieu@14
|
61 % played just once. The considered EBR value is the maximum EBR
|
mathieu@14
|
62 % of the fg sample relative to the bg on windows of 1000 samples.
|
mathieu@14
|
63 % The considered bg for this is the mix of all specified bgs.
|
mathieu@14
|
64 %
|
mathieu@14
|
65 % This version of simscene allows a lot of options to be controlled, as
|
mathieu@14
|
66 % optional 'name', value pairs from the 4th argument. Here is a brief
|
mathieu@14
|
67 % description of the optional parameters:
|
gregoirelafay@17
|
68 % save pictures without displaying them
|
mathieu@14
|
69 % - timeMode: control a time spacing between events.
|
mathieu@14
|
70 % 'generate' (default): values must be set for each track using the
|
mathieu@14
|
71 % score control structure
|
mathieu@14
|
72 % 'abstract': values are computed from an abstract representation of
|
mathieu@14
|
73 % an existing acoustic scene given as parameter
|
mathieu@14
|
74 % 'replicate': values are replicated from an existing acoustic scene
|
mathieu@14
|
75 % given as parameter
|
mathieu@14
|
76 %
|
mathieu@14
|
77 % - ebrMode: control the Event to Background power level Ratio (EBR) of events.
|
mathieu@14
|
78 % Possible options are: 'generate' (default), 'abstract', 'replicate', see above.
|
mathieu@14
|
79 %
|
mathieu@14
|
80 % If ebrMode is set to 'replicate' or 'abstract', and score.events exist,
|
mathieu@14
|
81 % simScene will use the values <ebr> and <ebr_stddev> as offsets for
|
mathieu@14
|
82 % the class <label>.
|
mathieu@14
|
83 % If timeMode is set to 'abstract' and score.events exist, simScene will use
|
mathieu@14
|
84 % the values <mean_time_between_instances> and <time_between_instances_stddev>.
|
mathieu@14
|
85 % as offsets for the class <label>.
|
mathieu@14
|
86 % If one of the mode is not set to 'generate' and score.events exist, SimScene
|
mathieu@14
|
87 % will also use the values <start_time>, <end_time>, <fade_in_time>, <fade_out_time>
|
mathieu@14
|
88 % and '<sampleId>' of score.events, provided they are not equal to 0 or
|
mathieu@14
|
89 % empty.
|
mathieu@14
|
90 %
|
mathieu@14
|
91 % - instanceAnnotFile: if timeMode and / or ebrMode are set to 'abstract'
|
mathieu@14
|
92 % or 'replicate', this parameter is the path to the
|
mathieu@14
|
93 % annotation of the reference scene. Annotation must
|
mathieu@14
|
94 % be provided as a Comma Separated Value (CSV) file
|
mathieu@14
|
95 % with one event per line with class identifier as a
|
mathieu@14
|
96 % string, onset and offset times in second as floating
|
mathieu@14
|
97 % point value.
|
mathieu@14
|
98 %
|
mathieu@14
|
99 % - instanceAudioFile: if timeMode and / or ebrMode are set to 'abstract'
|
mathieu@14
|
100 % or 'replicate', this parameter is the path to the wav
|
mathieu@14
|
101 % file of the reference scene sampled at 44100 Hz.
|
mathieu@14
|
102 %
|
gregoirelafay@17
|
103 % - figure: (default 0) save and show pictures (piano roll, time domain stacked visualization, overlaid spectrogram)
|
gregoire@16
|
104 % 0: don't save or display pictures
|
gregoire@16
|
105 % 1: save pictures without displaying them
|
gregoire@16
|
106 % 2: save and display pictures
|
gregoire@16
|
107 %
|
gregoirelafay@17
|
108 % - channel: (default 0) number of audio channels contained in the file
|
gregoirelafay@17
|
109 % 0: 1 channel (mono)
|
gregoirelafay@17
|
110 % 1: As many channel as sound classes (events+textures)
|
gregoirelafay@17
|
111 % 2: As many channel as sound classes (events+textures). Each
|
gregoirelafay@17
|
112 % channel is saved in a separated wav file.
|
gregoirelafay@17
|
113 %
|
mathieu@14
|
114 % - outputFileName: name of generated files with no extension
|
mathieu@14
|
115 %
|
mathieu@14
|
116 % - sampleChoice: method for choosing sample to schedule within a track
|
mathieu@14
|
117 % 'random': unconstrained sampling
|
gregoire@16
|
118 % 'random-unique': unconstrained sampling with no sample repetition
|
mathieu@14
|
119 % 'close': choose among the sampling dataset the sample that
|
mathieu@14
|
120 % has the closest duration to the reference one.
|
mathieu@14
|
121 % This mode is available only for the replicate timeMode.
|
mathieu@14
|
122 %
|
mathieu@14
|
123 % - minSpace: floating point value (default -1: overlapping between events allowed):
|
mathieu@14
|
124 % minimal spacing in seconds between successive events
|
mathieu@14
|
125 %
|
mathieu@14
|
126 % - endCut: Boolean (default 0): adjust the duration of the last sample of
|
mathieu@14
|
127 % each track if the latter ends after the track duration.
|
mathieu@14
|
128 % If 1, cut the last sample to the track duration. If
|
mathieu@14
|
129 % 0, the last sample is removed.
|
mathieu@14
|
130 %
|
mathieu@14
|
131 % SceneSchedule and SceneObject:
|
mathieu@14
|
132 %
|
mathieu@14
|
133 % - sceneObjects: This vector will contain detailed information concerning
|
mathieu@14
|
134 % all the samples selected to build this scene.
|
mathieu@14
|
135 %
|
mathieu@14
|
136 % - sceneSchedule: This vector will contain all scheduling information
|
mathieu@14
|
137 % (i.e. what sample goes where, with what scaling factor).
|
mathieu@14
|
138 % The sample indices stored in it refer to the position
|
mathieu@14
|
139 % in the previous vector.
|
mathieu@14
|
140 %
|
mathieu@14
|
141 % SceneSchedule, SceneObject, as well as score are saved in the .mat
|
mathieu@14
|
142 % annotation file.
|
mathieu@14
|
143
|
mathieu@14
|
144 % This program was written by Mathias Rossignol & Grégoire Lafay
|
mathieu@14
|
145 % is Copyright (C) 2015 IRCAM <http://www.ircam.fr>
|
mathieu@14
|
146 %
|
mathieu@14
|
147 % This program is free software: you can redistribute it and/or modify it
|
mathieu@14
|
148 % under the terms of the GNU General Public License as published by the Free
|
mathieu@14
|
149 % Software Foundation, either version 3 of the License, or (at your option)
|
mathieu@14
|
150 % any later version.
|
mathieu@14
|
151 %
|
mathieu@14
|
152 % This program is distributed in the hope that it will be useful, but
|
mathieu@14
|
153 % WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
mathieu@14
|
154 % or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
mathieu@14
|
155 % for more details.
|
mathieu@14
|
156 %
|
mathieu@14
|
157 % You should have received a copy of the GNU General Public License along
|
mathieu@14
|
158 % with this program. If not, see <http://www.gnu.org/licenses/>.
|
mathieu@14
|
159 %
|
mathieu@14
|
160 % Uses Mark Paskin's process_options.m from KPMtools
|
mathieu@14
|
161
|
mathieu@14
|
162 addpath(genpath('nonExposed'));
|
mathieu@14
|
163
|
gregoire@24
|
164 [timeMode,ebrMode,instanceAnnotFile,instanceAudioFile,figuresOption,sampleChoice,outputFileName,minSpace,endCut,eventInfoPath,norm,channelsOption,noiseLevel,noiseFiltMaxFreq,noiseFiltOrder]=process_options(varargin,'timeMode','generate','ebrMode','generate','instanceAnnotFile','none','instanceAudioFile','none','figure',0,'sampleChoice','random','outputFileName','simulatedScene','minSpace',-1,'endCut',0,'eventInfoPath','','norm',.75,'channel',0,'noiseLevel',-24,'noiseFiltMaxFreq',0,'noiseFiltOrder',12);
|
gregoire@16
|
165
|
gregoire@16
|
166 sr=44100;
|
mathieu@14
|
167
|
mathieu@14
|
168 check_options(timeMode,ebrMode,score)
|
mathieu@14
|
169
|
mathieu@14
|
170 %% Get score (only if at least one of the modes is not set to generate).
|
mathieu@14
|
171 % Else use score inpu variable
|
mathieu@14
|
172 if (~strcmp(timeMode,'generate') || ~strcmp(ebrMode,'generate'))
|
mathieu@14
|
173 template=getTemplate(instanceAnnotFile,instanceAudioFile);
|
mathieu@14
|
174 if isfield(score,'events')
|
mathieu@14
|
175 score.events=addUserOffsets(template.class,score.events,timeMode,ebrMode);
|
mathieu@14
|
176 else
|
mathieu@32
|
177 fprintf(2, 'score.event is empty: score.event will be created from the scene to replicate');
|
mathieu@14
|
178 score.events=template.class;
|
mathieu@14
|
179 end
|
mathieu@14
|
180 if ~isfield(score,'sceneDuration')
|
mathieu@14
|
181 score.sceneDuration=template.sceneDuration;
|
mathieu@14
|
182 end
|
mathieu@14
|
183 end
|
mathieu@14
|
184
|
mathieu@14
|
185 %% Get sceneSchedule and sceneObjects
|
gregoire@16
|
186
|
gregoire@16
|
187 if ~strcmp(eventInfoPath,'')
|
gregoire@16
|
188 load(eventInfoPath);
|
gregoire@16
|
189 else
|
gregoire@18
|
190 eventInfo(1).query='null';
|
gregoire@16
|
191 end
|
gregoire@16
|
192
|
gregoire@24
|
193 [sceneSchedule,sceneObjects,score]=getBackground(inputPath,score,eventInfo,sr,noiseLevel,noiseFiltMaxFreq,noiseFiltOrder);
|
gregoire@16
|
194 [sceneSchedule,sceneObjects]=getEvent(sceneSchedule,sceneObjects,inputPath,score,timeMode,ebrMode,sampleChoice,eventInfo,sr);
|
mathieu@14
|
195
|
mathieu@14
|
196 %% Manage overlapping
|
mathieu@14
|
197 if minSpace>=0
|
mathieu@14
|
198 [sceneSchedule] = manageOverlapping(sceneSchedule,minSpace);
|
mathieu@14
|
199 end
|
mathieu@14
|
200
|
mathieu@14
|
201
|
mathieu@14
|
202 %% Generate Scene
|
mathieu@14
|
203 if (~exist(outputPath, 'dir'))
|
mathieu@14
|
204 mkdir(outputPath)
|
mathieu@14
|
205 end
|
mathieu@14
|
206 if (~exist([outputPath,'annotation'], 'dir'))
|
mathieu@14
|
207 mkdir([outputPath,'sound'])
|
mathieu@14
|
208 end
|
mathieu@14
|
209 if (~exist([outputPath,'annotation'], 'dir'))
|
mathieu@14
|
210 mkdir([outputPath,'annotation'])
|
mathieu@14
|
211 end
|
mathieu@14
|
212
|
gregoirelafay@17
|
213 [sceneSchedule] = generateScene(sceneSchedule,sceneObjects,score,inputPath,outputPath,outputFileName,figuresOption,timeMode,endCut,norm,sr,channelsOption);
|
mathieu@14
|
214
|
mathieu@14
|
215 %% Check simulated scene
|
mathieu@14
|
216
|
mathieu@14
|
217 checkClassPresence(sceneSchedule,sceneObjects);
|
mathieu@14
|
218
|
mathieu@14
|
219 if minSpace>=0
|
mathieu@14
|
220 checkOverlapping(sceneSchedule,score.sceneDuration)
|
mathieu@14
|
221 end
|
mathieu@14
|
222
|
mathieu@14
|
223 end
|