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