]> git.donarmstrong.com Git - lilypond.git/blob - lily/dynamic-performer.cc
Merge with master
[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   
154   if (absolute_ && absolute_->volume_ < 0)
155     {
156       absolute_->volume_ = last_volume_;
157     }
158   else if (absolute_)
159     {
160       last_volume_ = absolute_->volume_;
161     }
162   
163   absolute_ = 0;
164   script_event_ = 0;
165   span_events_[LEFT] = 
166     span_events_[RIGHT] = 0;
167 }
168
169 IMPLEMENT_TRANSLATOR_LISTENER (Dynamic_performer, decrescendo);
170 void
171 Dynamic_performer::listen_decrescendo (Stream_event *r)
172 {
173   Direction d = to_dir (r->get_property ("span-direction"));
174   span_events_[d] = r;
175   grow_dir_[d] = SMALLER;
176 }
177
178 IMPLEMENT_TRANSLATOR_LISTENER (Dynamic_performer, crescendo);
179 void
180 Dynamic_performer::listen_crescendo (Stream_event *r)
181 {
182   Direction d = to_dir (r->get_property ("span-direction"));
183   span_events_[d] = r;
184   grow_dir_[d] = BIGGER;
185 }
186
187 IMPLEMENT_TRANSLATOR_LISTENER (Dynamic_performer, absolute_dynamic);
188 void
189 Dynamic_performer::listen_absolute_dynamic (Stream_event *r)
190 {
191   if (!script_event_)
192     script_event_ = r;
193 }
194
195 ADD_TRANSLATOR (Dynamic_performer,
196                 /* doc */                "",
197                 /* create */ "",
198
199                 /* read */
200                 "dynamicAbsoluteVolumeFunction "
201                 "instrumentEqualizer "
202                 "midiMaximumVolume "
203                 "midiMinimumVolume "
204                 "midiInstrument "
205                 ,
206                 /*writes*/"");