]> git.donarmstrong.com Git - lilypond.git/blob - lily/new-dynamic-performer.cc
7afc555c7a9bc05f6f034aec49fa261c684a7627
[lilypond.git] / lily / new-dynamic-performer.cc
1 /*
2   dynamic-performer.cc -- implement New_dynamic_performer
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 2000--2006 Jan Nieuwenhuizen <janneke@gnu.org>
7 */
8
9 #include "performer.hh"
10 #include "audio-item.hh"
11 #include "stream-event.hh"
12
13 #include "translator.icc"
14
15 /*
16   TODO:
17
18   handle multiple events
19
20   perform absolute (text) dynamics
21 */
22 class New_dynamic_performer : public Performer
23 {
24 public:
25   TRANSLATOR_DECLARATIONS (New_dynamic_performer);
26 protected:
27   void stop_translation_timestep ();
28   void process_music ();
29   Real equalize_volume (Real);
30
31   DECLARE_TRANSLATOR_LISTENER (decrescendo);
32   DECLARE_TRANSLATOR_LISTENER (crescendo);
33   DECLARE_TRANSLATOR_LISTENER (absolute_dynamic);
34 private:
35   Stream_event *script_event_;
36   Drul_array<Stream_event*> span_events_; 
37   Drul_array<Direction> grow_dir_; 
38   Real last_volume_;
39   Audio_dynamic *absolute_;
40   Audio_span_dynamic *span_dynamic_;
41   Audio_span_dynamic *finished_span_dynamic_;
42 };
43
44 New_dynamic_performer::New_dynamic_performer ()
45 {
46   last_volume_ = 0.5;
47   script_event_ = 0;
48   absolute_ = 0;
49   span_events_[LEFT] = 
50     span_events_[RIGHT] = 0;
51   span_dynamic_ = 0;
52   finished_span_dynamic_ = 0;
53 }
54
55 Real
56 New_dynamic_performer::equalize_volume (Real volume)
57 {
58   /*
59     properties override default equaliser setting
60   */
61   SCM min = get_property ("midiMinimumVolume");
62   SCM max = get_property ("midiMaximumVolume");
63   if (scm_is_number (min) || scm_is_number (max))
64     {
65       Interval iv (0, 1);
66       if (scm_is_number (min))
67         iv[MIN] = scm_to_double (min);
68       if (scm_is_number (max))
69         iv[MAX] = scm_to_double (max);
70       volume = iv[MIN] + iv.length () * volume;
71     }
72   else
73     {
74       /*
75         urg, code duplication:: staff_performer
76       */
77       SCM s = get_property ("midiInstrument");
78
79       if (!scm_is_string (s))
80         s = get_property ("instrumentName");
81
82       if (!scm_is_string (s))
83         s = scm_from_locale_string ("piano");
84
85       SCM eq = get_property ("instrumentEqualizer");
86       if (ly_is_procedure (eq))
87         s = scm_call_1 (eq, s);
88
89       if (is_number_pair (s))
90         {
91           Interval iv = ly_scm2interval (s);
92           volume = iv[MIN] + iv.length () * volume;
93         }
94     }
95   return volume;
96 }
97
98
99 void
100 New_dynamic_performer::process_music ()
101 {
102   if (span_events_[STOP] || script_event_)
103     {
104       finished_span_dynamic_ = span_dynamic_;
105       span_dynamic_ = 0;
106     }
107
108   if (span_events_[START])
109     {
110       span_dynamic_ = new Audio_span_dynamic();
111       announce_element (Audio_element_info (span_dynamic_, span_events_[START]));
112
113       span_dynamic_->grow_dir_ = grow_dir_[START];
114     }
115
116   if (script_event_
117       || span_dynamic_
118       || finished_span_dynamic_)
119     {
120       absolute_ = new Audio_dynamic ();
121
122       if (script_event_)
123         {
124           SCM proc = get_property ("dynamicAbsoluteVolumeFunction");
125
126           SCM svolume = SCM_EOL;
127           if (ly_is_procedure (proc))
128             {
129               // urg
130               svolume = scm_call_1 (proc, script_event_->get_property ("text"));
131             }
132
133           Real volume = robust_scm2double (svolume, 0.5);
134
135           last_volume_
136             = absolute_->volume_ = equalize_volume (volume);
137         }
138       
139       Audio_element_info info (absolute_, script_event_);
140       announce_element (info);
141     }
142
143
144   if (span_dynamic_)
145     span_dynamic_->add_absolute (absolute_);
146
147   if (finished_span_dynamic_)
148     finished_span_dynamic_->add_absolute (absolute_);
149 }
150
151 void
152 New_dynamic_performer::stop_translation_timestep ()
153 {
154   if (finished_span_dynamic_)
155     {
156       finished_span_dynamic_->render ();
157       finished_span_dynamic_ = 0;
158     }
159
160   
161   if (absolute_ && absolute_->volume_ < 0)
162     {
163       absolute_->volume_ = last_volume_;
164     }
165   else if (absolute_)
166     {
167       last_volume_ = absolute_->volume_;
168     }
169   
170   absolute_ = 0;
171   script_event_ = 0;
172   span_events_[LEFT] = 
173     span_events_[RIGHT] = 0;
174 }
175
176 IMPLEMENT_TRANSLATOR_LISTENER (New_dynamic_performer, decrescendo);
177 void
178 New_dynamic_performer::listen_decrescendo (Stream_event *r)
179 {
180   Direction d = to_dir (r->get_property ("span-direction"));
181   span_events_[d] = r;
182   grow_dir_[d] = SMALLER;
183 }
184
185 IMPLEMENT_TRANSLATOR_LISTENER (New_dynamic_performer, crescendo);
186 void
187 New_dynamic_performer::listen_crescendo (Stream_event *r)
188 {
189   Direction d = to_dir (r->get_property ("span-direction"));
190   span_events_[d] = r;
191   grow_dir_[d] = BIGGER;
192 }
193
194 IMPLEMENT_TRANSLATOR_LISTENER (New_dynamic_performer, absolute_dynamic);
195 void
196 New_dynamic_performer::listen_absolute_dynamic (Stream_event *r)
197 {
198   if (!script_event_)
199     script_event_ = r;
200 }
201
202 ADD_TRANSLATOR (New_dynamic_performer,
203                 /* doc */                "",
204                 /* create */ "",
205
206                 /* read */
207                 "dynamicAbsoluteVolumeFunction "
208                 "instrumentEqualizer "
209                 "midiMaximumVolume "
210                 "midiMinimumVolume "
211                 "midiInstrument "
212                 ,
213                 /*writes*/"");