Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(133)

Delta Between Two Patch Sets: lily/dynamic-performer.cc

Issue 302910043: Issue 4048: Improve crescendo performance with unspecified dynamics (Closed)
Left Patch Set: Handle multiple (de)crescendi in depart-return groups Created 8 years, 9 months ago
Right Patch Set: review response Created 8 years, 8 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « lily/audio-item.cc ('k') | lily/include/audio-item.hh » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 /* 1 /*
2 This file is part of LilyPond, the GNU music typesetter. 2 This file is part of LilyPond, the GNU music typesetter.
3 3
4 Copyright (C) 2000--2015 Jan Nieuwenhuizen <janneke@gnu.org> 4 Copyright (C) 2000--2015 Jan Nieuwenhuizen <janneke@gnu.org>
5 5
6 LilyPond is free software: you can redistribute it and/or modify 6 LilyPond is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by 7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or 8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version. 9 (at your option) any later version.
10 10
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 void close_and_enqueue_span (); 43 void close_and_enqueue_span ();
44 Real compute_departure_volume (Direction depart_dir, 44 Real compute_departure_volume (Direction depart_dir,
45 Real start_vol, 45 Real start_vol,
46 Real end_vol, 46 Real end_vol,
47 Real min_vol, 47 Real min_vol,
48 Real max_vol); 48 Real max_vol);
49 bool drive_state_machine (Direction next_grow_dir); 49 bool drive_state_machine (Direction next_grow_dir);
50 // next_vol < 0 means select a target dynamic based on growth direction. 50 // next_vol < 0 means select a target dynamic based on growth direction.
51 // return actual next volume (computed if not provided) 51 // return actual next volume (computed if not provided)
52 Real finish_queued_spans (Real next_vol = -1.0); 52 Real finish_queued_spans (Real next_vol = -1.0);
53 Real look_up_absolute_volume(SCM dynamicString, 53 Real look_up_absolute_volume (SCM dynamicString,
ht 2016/07/09 18:16:50 missing space after open parenthesis
Dan Eble 2016/07/12 05:01:15 Thank you. I've run fixcc.py on dynamic-performer
54 Real defaultValue); 54 Real defaultValue);
55 55
56 private: 56 private:
57 // This performer queues a number of dynamic spans waiting for the following 57 // This performer queues a number of dynamic spans waiting for the following
58 // pattern before computing their volume levels. 58 // pattern before computing their volume levels.
59 // 59 //
60 // 1. the first (de)crescendo, followed by ... 60 // 1. the first (de)crescendo, followed by ...
61 // 2. zero or more spans that either change in the same direction as the 61 // 2. zero or more spans that either change in the same direction as the
62 // first or do not change, followed by ... 62 // first or do not change, followed by ...
63 // 3. zero or more spans that either change in the opposite direction as the 63 // 3. zero or more spans that either change in the opposite direction as the
64 // first or do not change 64 // first or do not change
65 // 65 //
66 // The search may be cut short by an absolute dynamic or the end of the 66 // The search may be cut short by an absolute dynamic or the end of the
67 // context. 67 // context.
68 enum State 68 enum State
69 { 69 {
70 STATE_INITIAL = 0, // waiting for a (de)crescendo 70 STATE_INITIAL = 0, // waiting for a (de)crescendo
71 STATE_DEPART, // enqueued the first span, gathering same-direction spans 71 STATE_DEPART, // enqueued the first span, gathering same-direction spans
72 STATE_RETURN // gathering opposite-direction spans 72 STATE_RETURN // gathering opposite-direction spans
73 }; 73 };
74 74
75 struct UnfinishedSpan 75 struct UnfinishedSpan
76 { 76 {
77 Audio_span_dynamic *dynamic_; 77 Audio_span_dynamic *dynamic_;
78 Direction grow_dir_; 78 Direction grow_dir_;
79 79
80 UnfinishedSpan () : dynamic_ (0), grow_dir_ (CENTER) {} 80 UnfinishedSpan () : dynamic_ (0), grow_dir_ (CENTER) {}
81 }; 81 };
82 82
83 struct DynamicQueue 83 struct DynamicQueue
84 { 84 {
85 vector<UnfinishedSpan> spans_; 85 vector<UnfinishedSpan> spans_;
86 // total duration of (de)crescendi (i.e. excluding fixed-volume spans) 86 // total duration of (de)crescendi (i.e. excluding fixed-volume spans)
87 Real change_duration_; 87 Real change_duration_;
88 Real min_target_vol_; 88 Real min_target_vol_;
89 Real max_target_vol_; 89 Real max_target_vol_;
90 90
91 DynamicQueue () : change_duration_ (0) {} 91 DynamicQueue () : change_duration_ (0) {}
92 92
93 void clear () 93 void clear ()
94 { 94 {
95 spans_.clear (); 95 spans_.clear ();
96 change_duration_ = 0; 96 change_duration_ = 0;
97 } 97 }
98 98
99 void push_back (const UnfinishedSpan& span, 99 void push_back (const UnfinishedSpan &span,
100 Real min_target_vol, 100 Real min_target_vol,
101 Real max_target_vol) 101 Real max_target_vol)
ht 2016/07/09 18:16:50 Assuming that equalizer settings do not change bet
Dan Eble 2016/07/12 05:01:15 Assuming that context properties do not change in
102 { 102 {
103 if (span.grow_dir_ != CENTER) 103 if (span.grow_dir_ != CENTER)
104 change_duration_ += span.dynamic_->get_duration (); 104 change_duration_ += span.dynamic_->get_duration ();
105 min_target_vol_ = min_target_vol; 105 min_target_vol_ = min_target_vol;
106 max_target_vol_ = max_target_vol; 106 max_target_vol_ = max_target_vol;
107 spans_.push_back (span); 107 spans_.push_back (span);
108 } 108 }
109 109
110 void set_volume (Real start_vol, Real target_vol); 110 void set_volume (Real start_vol, Real target_vol);
111 }; 111 };
112 112
113 private: 113 private:
114 Stream_event *script_event_; 114 Stream_event *script_event_;
115 Drul_array<Stream_event *> span_events_; 115 Drul_array<Stream_event *> span_events_;
116 Direction next_grow_dir_; 116 Direction next_grow_dir_;
117 Direction depart_dir_; 117 Direction depart_dir_;
118 UnfinishedSpan open_span_; 118 UnfinishedSpan open_span_;
119 DynamicQueue depart_queue_; 119 DynamicQueue depart_queue_;
120 DynamicQueue return_queue_; 120 DynamicQueue return_queue_;
121 State state_; 121 State state_;
122 }; 122 };
123 123
124 Dynamic_performer::Dynamic_performer () 124 Dynamic_performer::Dynamic_performer ()
125 : script_event_ (0), 125 : script_event_ (0),
126 next_grow_dir_ (CENTER), 126 next_grow_dir_ (CENTER),
127 depart_dir_ (CENTER), 127 depart_dir_ (CENTER),
128 state_ (STATE_INITIAL) 128 state_ (STATE_INITIAL)
129 { 129 {
130 span_events_[LEFT] 130 span_events_[LEFT]
131 = span_events_[RIGHT] = 0; 131 = span_events_[RIGHT] = 0;
132 } 132 }
133 133
134 bool 134 bool
135 Dynamic_performer::drive_state_machine (Direction next_grow_dir) 135 Dynamic_performer::drive_state_machine (Direction next_grow_dir)
136 { 136 {
137 switch (state_) 137 switch (state_)
138 { 138 {
139 case STATE_INITIAL: 139 case STATE_INITIAL:
140 if (next_grow_dir != CENTER) 140 if (next_grow_dir != CENTER)
141 { 141 {
142 state_ = STATE_DEPART; 142 state_ = STATE_DEPART;
143 depart_dir_ = next_grow_dir; 143 depart_dir_ = next_grow_dir;
144 } 144 }
145 break; 145 break;
146 146
147 case STATE_DEPART: 147 case STATE_DEPART:
148 if (next_grow_dir == -depart_dir_) 148 if (next_grow_dir == -depart_dir_)
149 state_ = STATE_RETURN; 149 state_ = STATE_RETURN;
150 break; 150 break;
151 151
152 case STATE_RETURN: 152 case STATE_RETURN:
153 if (next_grow_dir == depart_dir_) 153 if (next_grow_dir == depart_dir_)
154 { 154 {
155 state_ = STATE_DEPART; 155 state_ = STATE_DEPART;
156 depart_dir_ = next_grow_dir;
ht 2016/07/09 18:16:50 This looks like a redundant assignment due to the
Dan Eble 2016/07/12 05:01:15 Yes. I appreciate your attention to detail.
157 return true; 156 return true;
158 } 157 }
159 break; 158 break;
160 } 159 }
161 160
162 return false; 161 return false;
163 } 162 }
164 163
165 void 164 void
166 Dynamic_performer::close_and_enqueue_span () 165 Dynamic_performer::close_and_enqueue_span ()
167 { 166 {
168 if (!open_span_.dynamic_) 167 if (!open_span_.dynamic_)
169 programming_error("no open dynamic span"); 168 programming_error ("no open dynamic span");
170 else 169 else
171 { 170 {
172 DynamicQueue& dq = 171 DynamicQueue &dq
173 (state_ == STATE_RETURN) ? return_queue_ : depart_queue_; 172 = (state_ == STATE_RETURN) ? return_queue_ : depart_queue_;
174 173
175 // Changing equalizer settings in the course of the performance does not 174 // Changing equalizer settings in the course of the performance does not
176 // seem very likely. This is a fig leaf: Equalize these limit volumes 175 // seem very likely. This is a fig leaf: Equalize these limit volumes
177 // now as the required context properties are current. Note that only 176 // now as the required context properties are current. Note that only
178 // the limits at the end of the last span in the queue are kept. 177 // the limits at the end of the last span in the queue are kept.
179 178
180 // Resist diminishing to silence. (Idea: Look up "ppppp" 179 // Resist diminishing to silence. (Idea: Look up "ppppp"
181 // with dynamicAbsoluteVolumeFunction, however that would yield 0.25.) 180 // with dynamicAbsoluteVolumeFunction, however that would yield 0.25.)
182 const Real min_target = equalize_volume (0.1); 181 const Real min_target = equalize_volume (0.1);
183 const Real max_target = 182 const Real max_target
184 equalize_volume (Audio_span_dynamic::MAXIMUM_VOLUME); 183 = equalize_volume (Audio_span_dynamic::MAXIMUM_VOLUME);
185 184
186 open_span_.dynamic_->set_end_moment (now_mom ()); 185 open_span_.dynamic_->set_end_moment (now_mom ());
187 dq.push_back (open_span_, min_target, max_target); 186 dq.push_back (open_span_, min_target, max_target);
188 } 187 }
189 188
190 open_span_ = UnfinishedSpan (); 189 open_span_ = UnfinishedSpan ();
191 } 190 }
192 191
193 // Set the starting and target volume for each span in the queue. The gain 192 // Set the starting and target volume for each span in the queue. The gain
194 // (loss) of any (de)crescendo is proportional to its share of the total time 193 // (loss) of any (de)crescendo is proportional to its share of the total time
(...skipping 12 matching lines...) Expand all
207 if (it->grow_dir_ != CENTER) 206 if (it->grow_dir_ != CENTER)
208 { 207 {
209 // grant this (de)crescendo its portion of the gain 208 // grant this (de)crescendo its portion of the gain
210 dur += it->dynamic_->get_duration (); 209 dur += it->dynamic_->get_duration ();
211 vol = start_vol + gain * (dur / change_duration_); 210 vol = start_vol + gain * (dur / change_duration_);
212 } 211 }
213 it->dynamic_->set_volume (prev_vol, vol); 212 it->dynamic_->set_volume (prev_vol, vol);
214 } 213 }
215 } 214 }
216 215
217 // Return a volume which is reasonably distant from the given volumes in the 216 // Return a volume which is reasonably distant from the given start and end
ht 2016/07/09 18:16:50 I guess that the "given volumes" mean only start_
Dan Eble 2016/07/12 05:01:15 Yes. I added max and min parameters after documen
218 // given direction, for use as a peak volume in a passage with a crescendo 217 // volumes in the given direction, for use as a peak volume in a passage with a
219 // followed by a decrescendo (or vice versa). If the given volumes are equal, 218 // crescendo followed by a decrescendo (or vice versa). If the given volumes
220 // the returned volume is a also reasonable target volume for a single 219 // are equal, the returned volume is a also reasonable target volume for a
221 // (de)crescendo. 220 // single (de)crescendo.
221 //
222 // The given minimum and maximum volumes are the allowable dynamic range.
222 Real 223 Real
223 Dynamic_performer::compute_departure_volume (Direction depart_dir, 224 Dynamic_performer::compute_departure_volume (Direction depart_dir,
224 Real start_vol, 225 Real start_vol,
225 Real end_vol, 226 Real end_vol,
226 Real min_vol, 227 Real min_vol,
227 Real max_vol) 228 Real max_vol)
228 { 229 {
229 if (depart_dir == CENTER) 230 if (depart_dir == CENTER)
230 return start_vol; 231 return start_vol;
231 232
232 // Try to find a volume that is a minimum distance from the starting and 233 // Try to find a volume that is a minimum distance from the starting and
233 // ending volumes. If the endpoint volumes differ, the nearer one is padded 234 // ending volumes. If the endpoint volumes differ, the nearer one is padded
234 // less than the farther one. 235 // less than the farther one.
ht 2016/07/09 18:16:50 I believe I eventually understood what this functi
Dan Eble 2016/07/12 05:01:15 That was my intent. Consider mf < ... > p. The p
235 236
236 // Idea: Use a context property or callback, e.g. the difference between two 237 // Idea: Use a context property or callback, e.g. the difference between two
237 // dynamics in dynamicAbsoluteVolumeFunction. 0.25 is the default difference 238 // dynamics in dynamicAbsoluteVolumeFunction. 0.25 is the default difference
238 // between "p" and "ff". (Isn't that rather wide for this purpose?) 239 // between "p" and "ff". (Isn't that rather wide for this purpose?)
ht 2016/07/09 18:16:50 I think using "0.25 * the available volume range"
239 const Real far_padding = 0.25; 240 const Real far_padding = 0.25;
240 const Real near_padding = 0.07; 241 const Real near_padding = 0.07;
241 242
242 // If for some reason one of the endpoints is already below the supposed 243 // If for some reason one of the endpoints is already below the supposed
243 // minimum or maximum, just accept it. 244 // minimum or maximum, just accept it.
244 // TODO: If this is impossible, programming_error.
ht 2016/07/09 18:16:50 Is there still something left to be done here?
Dan Eble 2016/07/12 05:01:15 I've removed the comment.
245 min_vol = min (min (min_vol, start_vol), end_vol); 245 min_vol = min (min (min_vol, start_vol), end_vol);
246 max_vol = max (max (max_vol, start_vol), end_vol); 246 max_vol = max (max (max_vol, start_vol), end_vol);
247 247
248 const Real vol_range = max_vol - min_vol; 248 const Real vol_range = max_vol - min_vol;
249 249
250 const Real near = minmax (depart_dir, start_vol, end_vol) 250 const Real near = minmax (depart_dir, start_vol, end_vol)
251 + depart_dir * near_padding * vol_range; 251 + depart_dir * near_padding * vol_range;
252 const Real far = minmax (-depart_dir, start_vol, end_vol) 252 const Real far = minmax (-depart_dir, start_vol, end_vol)
253 + depart_dir * far_padding * vol_range; 253 + depart_dir * far_padding * vol_range;
254 const Real depart_vol = minmax (depart_dir, near, far); 254 const Real depart_vol = minmax (depart_dir, near, far);
255 return max (min (depart_vol, max_vol), min_vol); 255 return max (min (depart_vol, max_vol), min_vol);
256 } 256 }
257 257
258 Real 258 Real
259 Dynamic_performer::finish_queued_spans (Real next_vol) 259 Dynamic_performer::finish_queued_spans (Real next_vol)
260 { 260 {
261 if (depart_queue_.spans_.empty ()) 261 if (depart_queue_.spans_.empty ())
262 { 262 {
263 programming_error("no dynamic span to finish"); 263 programming_error ("no dynamic span to finish");
ht 2016/07/09 18:16:50 missing whitespace before open parenthesis
264 return next_vol; 264 return next_vol;
265 } 265 }
266 266
267 const Real start_vol = depart_queue_.spans_.front ().dynamic_->get_start_volum e (); 267 const Real start_vol = depart_queue_.spans_.front ().dynamic_->get_start_volum e ();
268 268
269 if (return_queue_.spans_.empty ()) 269 if (return_queue_.spans_.empty ())
270 { 270 {
271 Real depart_vol = next_vol; 271 Real depart_vol = next_vol;
272 272
273 // If the next dynamic is not specified or is inconsistent with the 273 // If the next dynamic is not specified or is inconsistent with the
274 // direction of growth, choose a reasonable target. 274 // direction of growth, choose a reasonable target.
275 if ((next_vol < 0) || (depart_dir_ != sign (next_vol - start_vol))) 275 if ((next_vol < 0) || (depart_dir_ != sign (next_vol - start_vol)))
276 { 276 {
277 depart_vol = compute_departure_volume (depart_dir_, 277 depart_vol = compute_departure_volume (depart_dir_,
278 start_vol, start_vol, 278 start_vol, start_vol,
279 depart_queue_.min_target_vol_, 279 depart_queue_.min_target_vol_,
280 depart_queue_.max_target_vol_); 280 depart_queue_.max_target_vol_);
281 } 281 }
282 282
283 depart_queue_.set_volume(start_vol, depart_vol); 283 depart_queue_.set_volume (start_vol, depart_vol);
ht 2016/07/09 18:16:50 missing whitespace before open parenthesis
284 depart_queue_.clear (); 284 depart_queue_.clear ();
285 return (next_vol >= 0) ? next_vol : depart_vol; 285 return (next_vol >= 0) ? next_vol : depart_vol;
286 } 286 }
287 else 287 else
288 { 288 {
289 // If the next dynamic is not specified, return to the starting volume. 289 // If the next dynamic is not specified, return to the starting volume.
290 const Real return_vol = (next_vol >= 0) ? next_vol : start_vol; 290 const Real return_vol = (next_vol >= 0) ? next_vol : start_vol;
291 Real depart_vol = compute_departure_volume(depart_dir_, 291 Real depart_vol = compute_departure_volume (depart_dir_,
ht 2016/07/09 18:16:50 missing whitespace before open parenthesis
292 start_vol, return_vol, 292 start_vol, return_vol,
293 depart_queue_.min_target_vol_, 293 depart_queue_.min_target_vol_,
294 depart_queue_.max_target_vol_); 294 depart_queue_.max_target_vol_) ;
295 depart_queue_.set_volume (start_vol, depart_vol); 295 depart_queue_.set_volume (start_vol, depart_vol);
296 depart_queue_.clear (); 296 depart_queue_.clear ();
297 return_queue_.set_volume (depart_vol, return_vol); 297 return_queue_.set_volume (depart_vol, return_vol);
298 return_queue_.clear (); 298 return_queue_.clear ();
299 return return_vol; 299 return return_vol;
300 } 300 }
301 } 301 }
302 302
303 Real 303 Real
304 Dynamic_performer::equalize_volume (Real volume) 304 Dynamic_performer::equalize_volume (Real volume)
(...skipping 30 matching lines...) Expand all
335 if (ly_is_procedure (eq)) 335 if (ly_is_procedure (eq))
336 s = scm_call_1 (eq, s); 336 s = scm_call_1 (eq, s);
337 337
338 if (is_number_pair (s)) 338 if (is_number_pair (s))
339 { 339 {
340 Interval iv = ly_scm2interval (s); 340 Interval iv = ly_scm2interval (s);
341 volume = iv[MIN] + iv.length () * volume; 341 volume = iv[MIN] + iv.length () * volume;
342 } 342 }
343 } 343 }
344 return std::max (std::min (volume, Audio_span_dynamic::MAXIMUM_VOLUME), 344 return std::max (std::min (volume, Audio_span_dynamic::MAXIMUM_VOLUME),
345 Audio_span_dynamic::MINIMUM_VOLUME); 345 Audio_span_dynamic::MINIMUM_VOLUME);
ht 2016/07/09 18:16:50 max and min are usually used without namespace
Dan Eble 2016/07/12 05:01:15 That's currently true in Lilypond, but someone has
346 } 346 }
347 347
348 void 348 void
349 Dynamic_performer::finalize () 349 Dynamic_performer::finalize ()
350 { 350 {
351 if (open_span_.dynamic_) 351 if (open_span_.dynamic_)
352 close_and_enqueue_span (); 352 close_and_enqueue_span ();
353 finish_queued_spans (); 353 finish_queued_spans ();
354 } 354 }
355 355
356 Real 356 Real
357 Dynamic_performer::look_up_absolute_volume(SCM dynamicString, 357 Dynamic_performer::look_up_absolute_volume (SCM dynamicString,
358 Real defaultValue) 358 Real defaultValue)
359 { 359 {
360 SCM proc = get_property ("dynamicAbsoluteVolumeFunction"); 360 SCM proc = get_property ("dynamicAbsoluteVolumeFunction");
361 361
362 SCM svolume = SCM_EOL; 362 SCM svolume = SCM_EOL;
363 if (ly_is_procedure (proc)) 363 if (ly_is_procedure (proc))
364 svolume = scm_call_1 (proc, dynamicString); 364 svolume = scm_call_1 (proc, dynamicString);
365 365
366 return robust_scm2double (svolume, defaultValue); 366 return robust_scm2double (svolume, defaultValue);
367 } 367 }
368 368
369 void 369 void
370 Dynamic_performer::process_music () 370 Dynamic_performer::process_music ()
371 { 371 {
372 Real volume = -1; 372 Real volume = -1;
373 373
374 if (script_event_) // explicit dynamic 374 if (script_event_) // explicit dynamic
375 { 375 {
376 volume = look_up_absolute_volume (script_event_->get_property ("text"), 376 volume = look_up_absolute_volume (script_event_->get_property ("text"),
377 Audio_span_dynamic::DEFAULT_VOLUME); 377 Audio_span_dynamic::DEFAULT_VOLUME);
378 volume = equalize_volume (volume); 378 volume = equalize_volume (volume);
379 } 379 }
380 else if (!open_span_.dynamic_) // first time only 380 else if (!open_span_.dynamic_) // first time only
381 { 381 {
ht 2016/07/09 18:16:50 Could this case be combined with the code further
Dan Eble 2016/07/12 05:01:16 This block is executed the first time only, but th
382 // Idea: look_up_absolute_volume (ly_symbol2scm ("mf")). 382 // Idea: look_up_absolute_volume (ly_symbol2scm ("mf")).
ht 2016/07/09 18:16:50 Actually, the value 90.0/127.0 for Audio_span_dyna
Dan Eble 2016/07/12 05:01:16 I know. Did you mean to suggest that this idea is
383 // It is likely to change regtests. 383 // It is likely to change regtests.
384 volume = equalize_volume (Audio_span_dynamic::DEFAULT_VOLUME); 384 volume = equalize_volume (Audio_span_dynamic::DEFAULT_VOLUME);
385 } 385 }
386 386
387 // end the current span at relevant points 387 // end the current span at relevant points
388 if (open_span_.dynamic_ 388 if (open_span_.dynamic_
389 && (span_events_[START] || span_events_[STOP] || script_event_)) 389 && (span_events_[START] || span_events_[STOP] || script_event_))
390 { 390 {
391 close_and_enqueue_span (); 391 close_and_enqueue_span ();
392 if (script_event_) 392 if (script_event_)
393 { 393 {
394 state_ = STATE_INITIAL; 394 state_ = STATE_INITIAL;
395 volume = finish_queued_spans (volume); 395 volume = finish_queued_spans (volume);
396 } 396 }
397 } 397 }
398 398
399 // start a new span so that some dynamic is always in effect 399 // start a new span so that some dynamic is always in effect
400 if (!open_span_.dynamic_) 400 if (!open_span_.dynamic_)
401 { 401 {
402 if (drive_state_machine (next_grow_dir_)) 402 if (drive_state_machine (next_grow_dir_))
403 volume = finish_queued_spans (volume); 403 volume = finish_queued_spans (volume);
404 404
405 // if not known by now, use a default volume for robustness 405 // if not known by now, use a default volume for robustness
406 if (volume < 0) 406 if (volume < 0)
407 volume = Audio_span_dynamic::DEFAULT_VOLUME; 407 volume = equalize_volume (Audio_span_dynamic::DEFAULT_VOLUME);
ht 2016/07/09 18:16:50 Should equalization be applied to this default vol
Dan Eble 2016/07/12 05:01:16 I believe it makes no difference because in the ca
408 408
409 Stream_event *cause = 409 Stream_event *cause
410 span_events_[START] ? span_events_[START] : 410 = span_events_[START] ? span_events_[START]
411 script_event_ ? script_event_ : 411 : script_event_ ? script_event_
412 span_events_[STOP]; 412 : span_events_[STOP];
413 413
414 open_span_.dynamic_ = new Audio_span_dynamic (now_mom (), volume); 414 open_span_.dynamic_ = new Audio_span_dynamic (now_mom (), volume);
415 open_span_.grow_dir_ = next_grow_dir_; 415 open_span_.grow_dir_ = next_grow_dir_;
416 announce_element (Audio_element_info (open_span_.dynamic_, cause)); 416 announce_element (Audio_element_info (open_span_.dynamic_, cause));
417 } 417 }
418 } 418 }
419 419
420 void 420 void
421 Dynamic_performer::stop_translation_timestep () 421 Dynamic_performer::stop_translation_timestep ()
422 { 422 {
423 script_event_ = 0; 423 script_event_ = 0;
424 span_events_[LEFT] 424 span_events_[LEFT]
425 = span_events_[RIGHT] = 0; 425 = span_events_[RIGHT] = 0;
426 next_grow_dir_ = CENTER; 426 next_grow_dir_ = CENTER;
427 } 427 }
428 428
429 void 429 void
430 Dynamic_performer::listen_decrescendo (Stream_event *r) 430 Dynamic_performer::listen_decrescendo (Stream_event *r)
431 { 431 {
432 Direction d = to_dir (r->get_property ("span-direction")); 432 Direction d = to_dir (r->get_property ("span-direction"));
433 if (ASSIGN_EVENT_ONCE (span_events_[d], r) && (d == START)) 433 if (ASSIGN_EVENT_ONCE (span_events_[d], r) && (d == START))
434 next_grow_dir_ = SMALLER; 434 next_grow_dir_ = SMALLER;
435 } 435 }
(...skipping 15 matching lines...) Expand all
451 void 451 void
452 Dynamic_performer::boot () 452 Dynamic_performer::boot ()
453 { 453 {
454 ADD_LISTENER (Dynamic_performer, decrescendo); 454 ADD_LISTENER (Dynamic_performer, decrescendo);
455 ADD_LISTENER (Dynamic_performer, crescendo); 455 ADD_LISTENER (Dynamic_performer, crescendo);
456 ADD_LISTENER (Dynamic_performer, absolute_dynamic); 456 ADD_LISTENER (Dynamic_performer, absolute_dynamic);
457 } 457 }
458 458
459 ADD_TRANSLATOR (Dynamic_performer, 459 ADD_TRANSLATOR (Dynamic_performer,
460 /* doc */ 460 /* doc */
461 "", 461 "",
ht 2016/07/09 18:16:50 Now that the logic of Dynamic_performer is being r
Dan Eble 2016/07/12 05:01:15 If someone can point me to a good example of IM do
462 462
463 /* create */ 463 /* create */
464 "", 464 "",
465 465
466 /* read */ 466 /* read */
467 "dynamicAbsoluteVolumeFunction " 467 "dynamicAbsoluteVolumeFunction "
468 "instrumentEqualizer " 468 "instrumentEqualizer "
469 "midiMaximumVolume " 469 "midiMaximumVolume "
470 "midiMinimumVolume " 470 "midiMinimumVolume "
471 "midiInstrument ", 471 "midiInstrument ",
472 472
473 /* write */ 473 /* write */
474 "" 474 ""
475 ); 475 );
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b