diff options
author | Han-Wen Nienhuys <hanwen@xs4all.nl> | 2007-01-07 02:03:30 +0100 |
---|---|---|
committer | Han-Wen Nienhuys <hanwen@xs4all.nl> | 2007-01-07 02:03:30 +0100 |
commit | d9faeabdc6477426032aae237d753a674a53a901 (patch) | |
tree | 72f10505532937997d8ebc283d58bca2e65a9f88 | |
parent | b1f7f7fd184ef8b85734fb38889e24afac4b0d5b (diff) |
Fix #86; Fix midi dynamics coverage.
New_dynamic_performer, unified handling of absolute and span dynamics.
-rw-r--r-- | input/regression/midi-absolute-volume.ly | 34 | ||||
-rw-r--r-- | input/regression/midi-dynamics.ly | 24 | ||||
-rw-r--r-- | lily/audio-column.cc | 12 | ||||
-rw-r--r-- | lily/audio-item.cc | 79 | ||||
-rw-r--r-- | lily/dynamic-performer.cc | 131 | ||||
-rw-r--r-- | lily/include/audio-column.hh | 8 | ||||
-rw-r--r-- | lily/include/audio-item.hh | 18 | ||||
-rw-r--r-- | lily/midi-walker.cc | 8 | ||||
-rw-r--r-- | lily/score-performer.cc | 6 | ||||
-rw-r--r-- | lily/span-dynamic-performer.cc | 186 | ||||
-rw-r--r-- | ly/performer-init.ly | 4 |
11 files changed, 136 insertions, 374 deletions
diff --git a/input/regression/midi-absolute-volume.ly b/input/regression/midi-absolute-volume.ly deleted file mode 100644 index 8c3a24cd1c..0000000000 --- a/input/regression/midi-absolute-volume.ly +++ /dev/null @@ -1,34 +0,0 @@ - -\version "2.10.0" -\header { - texidoc = "@cindex Dynamic Absolute Volume -Absolute dynamics have an effect on MIDI files. -" -} - - -\score{ -\relative c''{ -%segfault in engraver -a1\ppp -a1\pp -a\p -a\mp -a\mf -a\f -a\ff -a\fff -a\sf -} -\layout{ ragged-right = ##t } - - \midi { - \context { - \Score - tempoWholesPerMinute = #(ly:make-moment 60 1) - } - } - - -} - diff --git a/input/regression/midi-dynamics.ly b/input/regression/midi-dynamics.ly new file mode 100644 index 0000000000..edff9c2f7a --- /dev/null +++ b/input/regression/midi-dynamics.ly @@ -0,0 +1,24 @@ +\header { + + texidoc = "Midi also handles crescendo and decrescendo, either + starting and ending from specified or unspecified sound level." + +} + +\version "2.11.10" + +\score { + \relative { + + \set midiMinimumVolume = #0.0 + \set midiMaximumVolume = #1.0 + c\ff c\pppp + c\ff\> c c c c\!\pppp + + c\< c c c c\! \ff + + c\> c c c \! + } + \midi {} + \layout{} +} diff --git a/lily/audio-column.cc b/lily/audio-column.cc index d0a36518a5..6365305675 100644 --- a/lily/audio-column.cc +++ b/lily/audio-column.cc @@ -11,9 +11,9 @@ #include "audio-item.hh" #include "performance.hh" -Audio_column::Audio_column (Moment at_mom) +Audio_column::Audio_column (Moment when) { - at_mom_ = at_mom; + when_ = when; } void @@ -24,14 +24,14 @@ Audio_column::add_audio_item (Audio_item *l) } Moment -Audio_column::at_mom () const +Audio_column::when () const { - return at_mom_; + return when_; } void -Audio_column::offset_at_mom (Moment m) +Audio_column::offset_when (Moment m) { - at_mom_ += m; + when_ += m; } diff --git a/lily/audio-item.cc b/lily/audio-item.cc index 4a3b9d4a41..3913527ea1 100644 --- a/lily/audio-item.cc +++ b/lily/audio-item.cc @@ -16,6 +16,17 @@ Audio_instrument::Audio_instrument (string instrument_string) str_ = instrument_string; } +void +Audio_item::render () +{ +} + +Audio_column * +Audio_item::get_column () const +{ + return audio_column_; +} + Audio_item::Audio_item () { audio_column_ = 0; @@ -47,11 +58,75 @@ Audio_key::Audio_key (int acc, bool major) major_ = major; } -Audio_dynamic::Audio_dynamic (Real volume) +Audio_dynamic::Audio_dynamic () +{ + volume_ = -1; +} + +Audio_span_dynamic::Audio_span_dynamic () +{ + grow_dir_ = CENTER; +} + +void +Audio_span_dynamic::add_absolute (Audio_dynamic *d) +{ + assert (d); + dynamics_.push_back (d); +} + +static Real +moment2real (Moment m) +{ + return m.main_part_.to_double () + + 0.1 * m.grace_part_.to_double (); +} + +void +Audio_span_dynamic::render () { - volume_ = volume; + if (dynamics_.size () <= 1) + return ; + + assert (dynamics_[0]->volume_ >= 0); + + if (dynamics_.back ()->volume_ > 0 + && sign (dynamics_.back ()->volume_ - dynamics_[0]->volume_) != grow_dir_) + { + dynamics_.erase (dynamics_.end () - 1); + assert (dynamics_.back ()->volume_ < 0); + } + + if (dynamics_.size () <= 1) + return ; + + Real delta_v = grow_dir_ * 0.1; + + Real start_v = dynamics_[0]->volume_; + if (dynamics_.back ()->volume_ < 0) + dynamics_.back ()->volume_ = max (min (start_v + grow_dir_ * 0.25, 1.0), 0.0); + + delta_v = dynamics_.back ()->volume_ - dynamics_[0]->volume_; + + Moment start = dynamics_[0]->get_column ()->when (); + + Real total_t = moment2real (dynamics_.back ()->get_column ()->when () - start); + + for (vsize i = 1; i < dynamics_.size(); i ++) + { + Moment dt_moment = dynamics_[i]->get_column ()->when () + - start; + + Real dt = moment2real (dt_moment); + + Real v = start_v + delta_v * (dt / total_t); + + dynamics_[i]->volume_ = v; + } } + + Audio_tempo::Audio_tempo (int per_minute_4) { per_minute_4_ = per_minute_4; diff --git a/lily/dynamic-performer.cc b/lily/dynamic-performer.cc deleted file mode 100644 index 52939ec2e3..0000000000 --- a/lily/dynamic-performer.cc +++ /dev/null @@ -1,131 +0,0 @@ -/* - dynamic-performer.cc -- implement Dynamic_performer - - source file of the GNU LilyPond music typesetter - - (c) 2000--2006 Jan Nieuwenhuizen <janneke@gnu.org> -*/ - -#include "performer.hh" - -#include "audio-item.hh" -#include "stream-event.hh" -#include "translator.icc" - -/* - TODO: - - handle multiple events - - perform absolute (text) dynamics -*/ -class Dynamic_performer : public Performer -{ -public: - TRANSLATOR_DECLARATIONS (Dynamic_performer); -protected: - void stop_translation_timestep (); - void process_music (); - - DECLARE_TRANSLATOR_LISTENER (absolute_dynamic); -private: - Stream_event *script_event_; - Audio_dynamic *audio_; -}; - -Dynamic_performer::Dynamic_performer () -{ - script_event_ = 0; - audio_ = 0; -} - -void -Dynamic_performer::process_music () -{ - 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); - - /* - properties override default equaliser setting - */ - SCM min = get_property ("midiMinimumVolume"); - SCM max = get_property ("midiMaximumVolume"); - if (scm_is_number (min) || scm_is_number (max)) - { - Interval iv (0, 1); - if (scm_is_number (min)) - iv[MIN] = scm_to_double (min); - if (scm_is_number (max)) - iv[MAX] = scm_to_double (max); - volume = iv[MIN] + iv.length () * volume; - } - else - { - /* - urg, code duplication:: staff_performer - */ - SCM s = get_property ("midiInstrument"); - - if (!scm_is_string (s)) - s = get_property ("instrumentName"); - - if (!scm_is_string (s)) - s = scm_from_locale_string ("piano"); - - SCM eq = get_property ("instrumentEqualizer"); - if (ly_is_procedure (eq)) - s = scm_call_1 (eq, s); - - if (is_number_pair (s)) - { - Interval iv = ly_scm2interval (s); - volume = iv[MIN] + iv.length () * volume; - } - } - - audio_ = new Audio_dynamic (volume); - Audio_element_info info (audio_, script_event_); - announce_element (info); - script_event_ = 0; - } -} - -void -Dynamic_performer::stop_translation_timestep () -{ - if (audio_) - { - audio_ = 0; - } -} - -IMPLEMENT_TRANSLATOR_LISTENER (Dynamic_performer, absolute_dynamic); -void -Dynamic_performer::listen_absolute_dynamic (Stream_event *r) -{ - if (!script_event_) - script_event_ = r; -} - -ADD_TRANSLATOR (Dynamic_performer, - /* doc */ "", - /* create */ "", - - /* read */ - "dynamicAbsoluteVolumeFunction " - "instrumentEqualizer " - "midiMaximumVolume " - "midiMinimumVolume " - "midiInstrument " - , - /*writes*/""); diff --git a/lily/include/audio-column.hh b/lily/include/audio-column.hh index 1cc827a276..1d0fb5ca18 100644 --- a/lily/include/audio-column.hh +++ b/lily/include/audio-column.hh @@ -19,21 +19,21 @@ class Audio_column : public Audio_element { public: - Audio_column (Moment at_mom); + Audio_column (Moment when); void add_audio_item (Audio_item *i); - Moment at_mom () const; + Moment when () const; vector<Audio_item*> audio_items_; protected: - void offset_at_mom (Moment m); + void offset_when (Moment m); friend class Score_performer; private: Audio_column (Audio_column const &); - Moment at_mom_; + Moment when_; }; #endif // AUDIO_COLUMN_HH diff --git a/lily/include/audio-item.hh b/lily/include/audio-item.hh index e6f0c9ad91..d450582feb 100644 --- a/lily/include/audio-item.hh +++ b/lily/include/audio-item.hh @@ -21,7 +21,10 @@ class Audio_item : public Audio_element public: Audio_item (); Audio_column *audio_column_; + Audio_column *get_column () const; + virtual void render (); + private: Audio_item (Audio_item const &); Audio_item &operator = (Audio_item const &); @@ -30,11 +33,24 @@ private: class Audio_dynamic : public Audio_item { public: - Audio_dynamic (Real volume); + Audio_dynamic (); Real volume_; }; +class Audio_span_dynamic : public Audio_element +{ +public: + Direction grow_dir_; + vector<Audio_dynamic*> dynamics_; + + + virtual void render (); + void add_absolute (Audio_dynamic*); + Audio_span_dynamic (); +}; + + class Audio_key : public Audio_item { public: diff --git a/lily/midi-walker.cc b/lily/midi-walker.cc index c2aaa085b1..8a315d6f2c 100644 --- a/lily/midi-walker.cc +++ b/lily/midi-walker.cc @@ -57,7 +57,7 @@ void Midi_walker::do_start_note (Midi_note *note) { Audio_item *ptr = (*items_)[index_]; - Moment stop_mom = note->get_length () + ptr->audio_column_->at_mom (); + Moment stop_mom = note->get_length () + ptr->audio_column_->when (); bool play_start = true; for (vsize i = 0; i < stop_note_queue.size (); i++) @@ -93,7 +93,7 @@ Midi_walker::do_start_note (Midi_note *note) stop_note_queue.insert (e); if (play_start) - output_event (ptr->audio_column_->at_mom (), note); + output_event (ptr->audio_column_->when (), note); } } @@ -142,7 +142,7 @@ void Midi_walker::process () { Audio_item *audio = (*items_)[index_]; - do_stop_notes (audio->audio_column_->at_mom ()); + do_stop_notes (audio->audio_column_->when ()); if (Midi_item *midi = Midi_item::get_midi (audio)) { @@ -156,7 +156,7 @@ Midi_walker::process () do_start_note (note); } else - output_event (audio->audio_column_->at_mom (), midi); + output_event (audio->audio_column_->when (), midi); } } diff --git a/lily/score-performer.cc b/lily/score-performer.cc index 73f79add86..0dfea54c6e 100644 --- a/lily/score-performer.cc +++ b/lily/score-performer.cc @@ -113,7 +113,7 @@ Score_performer::one_time_step (SCM) { if (!skipping_) { - skip_start_mom_ = audio_column_->at_mom (); + skip_start_mom_ = audio_column_->when (); skipping_ = true; } } @@ -121,11 +121,11 @@ Score_performer::one_time_step (SCM) { if (skipping_) { - offset_mom_ -= audio_column_->at_mom () - skip_start_mom_; + offset_mom_ -= audio_column_->when () - skip_start_mom_; skipping_ = false; } - audio_column_->offset_at_mom (offset_mom_); + audio_column_->offset_when (offset_mom_); precomputed_recurse_over_translators (context (), PROCESS_MUSIC, UP); do_announces (); } diff --git a/lily/span-dynamic-performer.cc b/lily/span-dynamic-performer.cc deleted file mode 100644 index e5938f0852..0000000000 --- a/lily/span-dynamic-performer.cc +++ /dev/null @@ -1,186 +0,0 @@ -/* - span-dynamic-performer.cc -- implement Span_dynamic_performer - - source file of the GNU LilyPond music typesetter - - (c) 2000--2006 Jan Nieuwenhuizen <janneke@gnu.org> -*/ - -#include "performer.hh" - -#include "audio-item.hh" -#include "international.hh" -#include "stream-event.hh" - -#include "translator.icc" - -/* - TODO: fold this into 1 engraver: \< and \> should also stop when - absdyn is encountered. -*/ -struct Audio_dynamic_tuple -{ - Audio_dynamic *audio_; - Moment mom_; -}; - -/** - perform span-dynamics -*/ -class Span_dynamic_performer : public Performer -{ -public: - TRANSLATOR_DECLARATIONS (Span_dynamic_performer); - -protected: - virtual void acknowledge_audio_element (Audio_element_info); - void process_music (); - void stop_translation_timestep (); - - DECLARE_TRANSLATOR_LISTENER (decrescendo); - DECLARE_TRANSLATOR_LISTENER (crescendo); -private: - Audio_dynamic *audio_; - Real last_volume_; - Stream_event *span_start_event_; - Drul_array<Stream_event *> span_events_; - vector<Audio_dynamic_tuple> dynamic_tuples_; - vector<Audio_dynamic_tuple> finished_dynamic_tuples_; - Direction dir_; - Direction finished_dir_; -}; - -Span_dynamic_performer::Span_dynamic_performer () -{ - span_events_[START] = 0; - span_events_[STOP] = 0; - span_start_event_ = 0; - audio_ = 0; - last_volume_ = 0; -} - -void -Span_dynamic_performer::acknowledge_audio_element (Audio_element_info i) -{ - if (Audio_dynamic *d = dynamic_cast<Audio_dynamic *> (i.elem_)) - last_volume_ = d->volume_; -} - -void -Span_dynamic_performer::process_music () -{ - if (span_start_event_ || span_events_[START]) - { - audio_ = new Audio_dynamic (0); - Audio_element_info info (audio_, span_events_[START] - ? span_events_[START] - : span_events_[STOP]); - announce_element (info); - Audio_dynamic_tuple a = { audio_, now_mom () }; - dynamic_tuples_.push_back (a); - } - - if (span_events_[STOP]) - { - if (!span_start_event_) - { - span_events_[STOP]->origin ()->warning (_ ("cannot find start of (de)crescendo")); - span_events_[STOP] = 0; - } - else - { - finished_dir_ = dir_; - finished_dynamic_tuples_ = dynamic_tuples_; - } - dynamic_tuples_.clear (); - span_start_event_ = 0; - } - - if (span_events_[START]) - { - dir_ = (span_events_[START]->in_event_class ("crescendo-event")) - ? RIGHT : LEFT; - span_start_event_ = span_events_[START]; - - dynamic_tuples_.clear (); - Audio_dynamic_tuple a = { audio_, now_mom () }; - dynamic_tuples_.push_back (a); - } - - if (span_events_[STOP]) - finished_dynamic_tuples_.back ().audio_->volume_ = last_volume_; - - if (span_events_[START]) - dynamic_tuples_[0].audio_->volume_ = last_volume_; - - span_events_[START] = 0; - span_events_[STOP] = 0; -} - -void -Span_dynamic_performer::stop_translation_timestep () -{ - if (finished_dynamic_tuples_.size () > 1) - { - Real start_volume = finished_dynamic_tuples_[0].audio_->volume_; - Real dv = finished_dynamic_tuples_.back ().audio_->volume_ - - start_volume; - /* - urg. - Catch and fix the case of: - - | | - x| x| - f cresc. -- -- -- -- -- pp - - Actually, we should provide a non-displayed dynamic/volume setting, - to set volume to 'ff' just before the pp. - */ - if (!dv || sign (dv) != finished_dir_) - { - // urg. 20%: about two volume steps - dv = (Real)finished_dir_ * 0.2; - if (!start_volume) - start_volume = finished_dynamic_tuples_.back ().audio_->volume_ - - dv; - } - Moment start_mom = finished_dynamic_tuples_[0].mom_; - Moment dt = finished_dynamic_tuples_.back ().mom_ - start_mom; - for (vsize i = 0; i < finished_dynamic_tuples_.size (); i++) - { - Audio_dynamic_tuple *a = &finished_dynamic_tuples_[i]; - Real volume = start_volume + dv * (Real) (a->mom_ - start_mom).main_part_ - / (Real)dt.main_part_; - a->audio_->volume_ = volume; - } - finished_dynamic_tuples_.clear (); - } - - if (audio_) - { - audio_ = 0; - } - - span_events_[STOP] = 0; - span_events_[START] = 0; -} - -IMPLEMENT_TRANSLATOR_LISTENER (Span_dynamic_performer, decrescendo); -void -Span_dynamic_performer::listen_decrescendo (Stream_event *r) -{ - Direction d = to_dir (r->get_property ("span-direction")); - span_events_[d] = r; -} - -IMPLEMENT_TRANSLATOR_LISTENER (Span_dynamic_performer, crescendo); -void -Span_dynamic_performer::listen_crescendo (Stream_event *r) -{ - Direction d = to_dir (r->get_property ("span-direction")); - span_events_[d] = r; -} - -ADD_TRANSLATOR (Span_dynamic_performer, - "", "", - "", ""); diff --git a/ly/performer-init.ly b/ly/performer-init.ly index 24f0da2b81..23e96dae3c 100644 --- a/ly/performer-init.ly +++ b/ly/performer-init.ly @@ -30,9 +30,7 @@ \context { \type "Performer_group" \name Voice - % The order of the dynamic performers is significant: absolute dynamic events must override crescendo events in midi. - \consists "Span_dynamic_performer" - \consists "Dynamic_performer" + \consists "New_dynamic_performer" \consists "Tie_performer" \consists "Piano_pedal_performer" \consists "Note_performer" |