/*
- dynamic-performer.cc -- implement Dynamic_performer
+ This file is part of LilyPond, the GNU music typesetter.
- source file of the GNU LilyPond music typesetter
+ Copyright (C) 2000--2014 Jan Nieuwenhuizen <janneke@gnu.org>
- (c) 2000--2007 Jan Nieuwenhuizen <janneke@gnu.org>
+ LilyPond 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.
+
+ LilyPond 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 LilyPond. If not, see <http://www.gnu.org/licenses/>.
*/
#include "performer.hh"
#include "audio-item.hh"
#include "stream-event.hh"
+#include "international.hh"
#include "translator.icc"
DECLARE_TRANSLATOR_LISTENER (absolute_dynamic);
private:
Stream_event *script_event_;
- Drul_array<Stream_event*> span_events_;
- Drul_array<Direction> grow_dir_;
+ Drul_array<Stream_event *> span_events_;
+ Drul_array<Direction> grow_dir_;
Real last_volume_;
+ bool last_volume_initialized_;
Audio_dynamic *absolute_;
Audio_span_dynamic *span_dynamic_;
Audio_span_dynamic *finished_span_dynamic_;
Dynamic_performer::Dynamic_performer ()
{
- last_volume_ = 0.5;
+ last_volume_ = 0.0;
+ last_volume_initialized_ = false;
script_event_ = 0;
absolute_ = 0;
- span_events_[LEFT] =
- span_events_[RIGHT] = 0;
+ span_events_[LEFT]
+ = span_events_[RIGHT] = 0;
span_dynamic_ = 0;
finished_span_dynamic_ = 0;
}
{
Interval iv (0, 1);
if (scm_is_number (min))
- iv[MIN] = scm_to_double (min);
+ iv[MIN] = scm_to_double (min);
if (scm_is_number (max))
- iv[MAX] = scm_to_double (max);
+ iv[MAX] = scm_to_double (max);
volume = iv[MIN] + iv.length () * volume;
}
else
{
/*
- urg, code duplication:: staff_performer
+ urg, code duplication:: staff_performer
*/
SCM s = get_property ("midiInstrument");
if (!scm_is_string (s))
- s = get_property ("instrumentName");
+ s = get_property ("instrumentName");
if (!scm_is_string (s))
- s = scm_from_locale_string ("piano");
+ s = scm_from_locale_string ("piano");
SCM eq = get_property ("instrumentEqualizer");
if (ly_is_procedure (eq))
- s = scm_call_1 (eq, s);
+ s = scm_call_1 (eq, s);
if (is_number_pair (s))
- {
- Interval iv = ly_scm2interval (s);
- volume = iv[MIN] + iv.length () * volume;
- }
+ {
+ Interval iv = ly_scm2interval (s);
+ volume = iv[MIN] + iv.length () * volume;
+ }
}
return volume;
}
-
void
Dynamic_performer::process_music ()
{
if (span_events_[STOP] || script_event_)
{
+ // End of a dynamic spanner, or an explicit dynamic script event.
finished_span_dynamic_ = span_dynamic_;
span_dynamic_ = 0;
}
if (span_events_[START])
{
- span_dynamic_ = new Audio_span_dynamic();
+ // Start of a dynamic spanner. Create a new Audio_span_dynamic for
+ // collecting changes in dynamics within this spanner.
+ span_dynamic_ = new Audio_span_dynamic (equalize_volume (0.1), equalize_volume (1.0));
announce_element (Audio_element_info (span_dynamic_, span_events_[START]));
span_dynamic_->grow_dir_ = grow_dir_[START];
+
+ if (!last_volume_initialized_ && !script_event_)
+ {
+ // No explicit dynamic script events have occurred yet, but there is
+ // nevertheless a dynamic spanner. Initialize last_volume_ to a
+ // value within the available range.
+ span_events_[START]->origin ()->warning (_ ("(De)crescendo with unspecified starting volume in MIDI."));
+ last_volume_ = equalize_volume (0.5);
+ last_volume_initialized_ = true;
+ }
}
if (script_event_
|| span_dynamic_
|| finished_span_dynamic_)
{
+ // New change in dynamics.
absolute_ = new Audio_dynamic ();
if (script_event_)
- {
- SCM proc = get_property ("dynamicAbsoluteVolumeFunction");
-
- SCM svolume = SCM_EOL;
- if (ly_is_procedure (proc))
- {
- // urg
- svolume = scm_call_1 (proc, script_event_->get_property ("text"));
- }
-
- Real volume = robust_scm2double (svolume, 0.5);
-
- last_volume_
- = absolute_->volume_ = equalize_volume (volume);
- }
-
+ {
+ // Explicit dynamic script event: determine the volume.
+ SCM proc = get_property ("dynamicAbsoluteVolumeFunction");
+
+ SCM svolume = SCM_EOL;
+ if (ly_is_procedure (proc))
+ {
+ // urg
+ svolume = scm_call_1 (proc, script_event_->get_property ("text"));
+ }
+
+ Real volume = robust_scm2double (svolume, 0.5);
+
+ last_volume_
+ = absolute_->volume_ = equalize_volume (volume);
+ last_volume_initialized_ = true;
+ }
+
Audio_element_info info (absolute_, script_event_);
announce_element (info);
}
+ if (!last_volume_initialized_)
+ {
+ absolute_ = new Audio_dynamic ();
+
+ last_volume_
+ = absolute_->volume_ = equalize_volume (0.71); // Backward compatible
+ last_volume_initialized_ = true;
+
+ Audio_element_info info (absolute_, script_event_);
+ announce_element (info);
+ }
if (span_dynamic_)
span_dynamic_->add_absolute (absolute_);
finished_span_dynamic_ = 0;
}
-
if (absolute_ && absolute_->volume_ < 0)
{
absolute_->volume_ = last_volume_;
else if (absolute_)
{
last_volume_ = absolute_->volume_;
+ last_volume_initialized_ = true;
}
-
+
absolute_ = 0;
script_event_ = 0;
- span_events_[LEFT] =
- span_events_[RIGHT] = 0;
+ span_events_[LEFT]
+ = span_events_[RIGHT] = 0;
}
IMPLEMENT_TRANSLATOR_LISTENER (Dynamic_performer, decrescendo);
}
ADD_TRANSLATOR (Dynamic_performer,
- /* doc */ "",
- /* create */ "",
-
- /* read */
- "dynamicAbsoluteVolumeFunction "
- "instrumentEqualizer "
- "midiMaximumVolume "
- "midiMinimumVolume "
- "midiInstrument "
- ,
- /*writes*/"");
+ /* doc */
+ "",
+
+ /* create */
+ "",
+
+ /* read */
+ "dynamicAbsoluteVolumeFunction "
+ "instrumentEqualizer "
+ "midiMaximumVolume "
+ "midiMinimumVolume "
+ "midiInstrument ",
+
+ /* write */
+ ""
+ );