summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHan-Wen Nienhuys <hanwen@xs4all.nl>2007-01-07 02:03:30 +0100
committerHan-Wen Nienhuys <hanwen@xs4all.nl>2007-01-07 02:03:30 +0100
commitd9faeabdc6477426032aae237d753a674a53a901 (patch)
tree72f10505532937997d8ebc283d58bca2e65a9f88
parentb1f7f7fd184ef8b85734fb38889e24afac4b0d5b (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.ly34
-rw-r--r--input/regression/midi-dynamics.ly24
-rw-r--r--lily/audio-column.cc12
-rw-r--r--lily/audio-item.cc79
-rw-r--r--lily/dynamic-performer.cc131
-rw-r--r--lily/include/audio-column.hh8
-rw-r--r--lily/include/audio-item.hh18
-rw-r--r--lily/midi-walker.cc8
-rw-r--r--lily/score-performer.cc6
-rw-r--r--lily/span-dynamic-performer.cc186
-rw-r--r--ly/performer-init.ly4
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"