1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3 
4   Copyright (C) 2000--2021 Jan Nieuwenhuizen <janneke@gnu.org>
5 
6   LilyPond is free software: you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation, either version 3 of the License, or
9   (at your option) any later version.
10 
11   LilyPond is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15 
16   You should have received a copy of the GNU General Public License
17   along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "piano-pedal.hh"
21 #include "performer.hh"
22 
23 #include "audio-item.hh"
24 #include "international.hh"
25 #include "stream-event.hh"
26 #include "warn.hh"
27 
28 #include "translator.icc"
29 
30 using std::string;
31 using std::vector;
32 
33 /**
34    perform Piano pedals
35 */
36 class Piano_pedal_performer : public Performer
37 {
38   struct Pedal_info
39   {
40     Stream_event *start_event_;
41     Drul_array<Stream_event *> event_drul_;
42   };
43 
44 public:
45   TRANSLATOR_DECLARATIONS (Piano_pedal_performer);
46 
47 protected:
48   void initialize () override;
49   void process_music ();
50   void stop_translation_timestep ();
51   void start_translation_timestep ();
52   void listen_sustain (Stream_event *);
53   void listen_una_corda (Stream_event *);
54   void listen_sostenuto (Stream_event *);
55 private:
56   vector<Audio_piano_pedal *> audios_;
57   Pedal_info info_alist_[NUM_PEDAL_TYPES];
58 };
59 
Piano_pedal_performer(Context * c)60 Piano_pedal_performer::Piano_pedal_performer (Context *c)
61   : Performer (c)
62 {
63 }
64 
65 void
initialize()66 Piano_pedal_performer::initialize ()
67 {
68   Pedal_info *p = info_alist_;
69 
70   for (int i = 0; i < NUM_PEDAL_TYPES; i++, p++)
71     {
72       p->event_drul_[START] = 0;
73       p->event_drul_[STOP] = 0;
74       p->start_event_ = 0;
75     }
76 }
77 
78 void
process_music()79 Piano_pedal_performer::process_music ()
80 {
81   Pedal_info *p = info_alist_;
82 
83   for (int i = 0; i < NUM_PEDAL_TYPES; i++, p++)
84     {
85       if (p->event_drul_[STOP])
86         {
87           if (!p->start_event_)
88             p->event_drul_[STOP]->warning (_ ("cannot find start of piano pedal"));
89           else
90             {
91               Audio_piano_pedal *a = new Audio_piano_pedal;
92               a->type_ = static_cast<Pedal_type> (i);
93               a->dir_ = STOP;
94               audios_.push_back (a);
95               Audio_element_info info (a, p->event_drul_[STOP]);
96               announce_element (info);
97             }
98           p->start_event_ = 0;
99         }
100 
101       if (p->event_drul_[START])
102         {
103           p->start_event_ = p->event_drul_[START];
104           Audio_piano_pedal *a = new Audio_piano_pedal;
105           a->type_ = static_cast<Pedal_type> (i);
106           a->dir_ = START;
107           audios_.push_back (a);
108           Audio_element_info info (a, p->event_drul_[START]);
109           announce_element (info);
110         }
111       p->event_drul_[START] = 0;
112       p->event_drul_[STOP] = 0;
113     }
114 }
115 
116 void
stop_translation_timestep()117 Piano_pedal_performer::stop_translation_timestep ()
118 {
119   audios_.clear ();
120 }
121 
122 void
start_translation_timestep()123 Piano_pedal_performer::start_translation_timestep ()
124 {
125   Pedal_info *p = info_alist_;
126   for (int i = 0; i < NUM_PEDAL_TYPES; i++, p++)
127     {
128       p->event_drul_[STOP] = 0;
129       p->event_drul_[START] = 0;
130     }
131 }
132 
133 void
listen_sostenuto(Stream_event * r)134 Piano_pedal_performer::listen_sostenuto (Stream_event *r)
135 {
136   Direction d = from_scm<Direction> (get_property (r, "span-direction"));
137   info_alist_[SOSTENUTO].event_drul_[d] = r;
138 }
139 
140 void
listen_sustain(Stream_event * r)141 Piano_pedal_performer::listen_sustain (Stream_event *r)
142 {
143   Direction d = from_scm<Direction> (get_property (r, "span-direction"));
144   info_alist_[SUSTAIN].event_drul_[d] = r;
145 }
146 
147 void
listen_una_corda(Stream_event * r)148 Piano_pedal_performer::listen_una_corda (Stream_event *r)
149 {
150   Direction d = from_scm<Direction> (get_property (r, "span-direction"));
151   info_alist_[UNA_CORDA].event_drul_[d] = r;
152 }
153 
154 void
boot()155 Piano_pedal_performer::boot ()
156 {
157   ADD_LISTENER (Piano_pedal_performer, sostenuto);
158   ADD_LISTENER (Piano_pedal_performer, sustain);
159   ADD_LISTENER (Piano_pedal_performer, una_corda);
160 }
161 
162 ADD_TRANSLATOR (Piano_pedal_performer,
163                 /* doc */
164                 "",
165 
166                 /* create */
167                 "",
168 
169                 /* read */
170                 "",
171 
172                 /* write */
173                 ""
174                );
175