]> git.mxchange.org Git - flightgear.git/blob - src/Sound/voiceplayer.hxx
Merge branch 'next' of http://git.gitorious.org/fg/flightgear into next
[flightgear.git] / src / Sound / voiceplayer.hxx
1 // voiceplayer.hxx -- voice/sound sample player
2 //
3 // Written by Jean-Yves Lefort, started September 2005.
4 //
5 // Copyright (C) 2005, 2006  Jean-Yves Lefort - jylefort@FreeBSD.org
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
21
22 #ifndef __SOUND_VOICEPLAYER_HXX
23 #define __SOUND_VOICEPLAYER_HXX
24
25 #include <assert.h>
26
27 #include <vector>
28 #include <deque>
29 #include <map>
30
31 #include <simgear/props/props.hxx>
32 #include <simgear/props/tiedpropertylist.hxx>
33 #include <simgear/sound/sample_openal.hxx>
34 using std::vector;
35 using std::deque;
36 using std::map;
37
38 class SGSampleGroup;
39
40 #include <Main/globals.hxx>
41
42 #ifdef _MSC_VER
43 #  pragma warning( push )
44 #  pragma warning( disable: 4355 )
45 #endif
46
47 /////////////////////////////////////////////////////////////////////////////
48 // FGVoicePlayer /////////////////////////////////////////////////////
49 /////////////////////////////////////////////////////////////////////////////
50
51 class FGVoicePlayer
52 {
53 public:
54
55     /////////////////////////////////////////////////////////////////////////////
56     // MK::RawValueMethodsData /////////////////////////////////////////////
57     /////////////////////////////////////////////////////////////////////////////
58
59     template <class C, class VT, class DT>
60     class RawValueMethodsData : public SGRawValue<VT>
61     {
62     public:
63       typedef VT (C::*getter_t) (DT) const;
64       typedef void (C::*setter_t) (DT, VT);
65
66       RawValueMethodsData (C &obj, DT data, getter_t getter = 0, setter_t setter = 0)
67         : _obj(obj), _data(data), _getter(getter), _setter(setter) {}
68
69       virtual VT getValue () const
70       {
71         if (_getter)
72       return (_obj.*_getter)(_data);
73         else
74       return SGRawValue<VT>::DefaultValue();
75       }
76       virtual bool setValue (VT value)
77       {
78         if (_setter)
79       {
80         (_obj.*_setter)(_data, value);
81         return true;
82       }
83         else
84       return false;
85       }
86       virtual SGRawValue<VT> *clone () const 
87       {
88         return new RawValueMethodsData<C,VT,DT>(_obj, _data, _getter, _setter);
89       }
90
91     private:
92       C       &_obj;
93       DT      _data;
94       getter_t    _getter;
95       setter_t    _setter;
96     };
97     
98     class PropertiesHandler : public simgear::TiedPropertyList
99     {
100     public:
101
102       template <class T>
103       inline void tie (SGPropertyNode *node, const SGRawValue<T> &raw_value)
104       {
105           Tie(node,raw_value);
106       }
107
108       template <class T>
109       inline void tie (SGPropertyNode *node,
110                const char *relative_path,
111                const SGRawValue<T> &raw_value)
112       {
113         Tie(node->getNode(relative_path, true),raw_value);
114       }
115
116       PropertiesHandler() {};
117
118       void unbind () {Untie();}
119     };
120
121   ///////////////////////////////////////////////////////////////////////////
122   // FGVoicePlayer::Voice ////////////////////////////////////////////
123   ///////////////////////////////////////////////////////////////////////////
124
125   class Voice
126   {
127   public:
128
129     /////////////////////////////////////////////////////////////////////////
130     // FGVoicePlayer::Voice::Element ////////////////////////////////////////
131     /////////////////////////////////////////////////////////////////////////
132
133     class Element
134     {
135     public:
136         bool silence;
137
138         virtual ~Element() {}
139         virtual inline void play (float volume) {}
140         virtual inline void stop () {}
141         virtual bool is_playing () = 0;
142         virtual inline void set_volume (float volume) {}
143     };
144
145     /////////////////////////////////////////////////////////////////////////
146     // FGVoicePlayer::Voice::SampleElement ///////////////////////////
147     /////////////////////////////////////////////////////////////////////////
148
149     class SampleElement : public Element
150     {
151         SGSharedPtr<SGSoundSample>  _sample;
152         float               _volume;
153
154     public:
155         inline SampleElement (SGSharedPtr<SGSoundSample> sample, float volume = 1.0)
156           : _sample(sample), _volume(volume) { silence = false; }
157
158         virtual inline void play (float volume) { if (_sample && (volume > 0.05)) { set_volume(volume); _sample->play_once(); } }
159         virtual inline void stop () { if (_sample) _sample->stop(); }
160         virtual inline bool is_playing () { return _sample ? _sample->is_playing() : false; }
161         virtual inline void set_volume (float volume) { if (_sample) _sample->set_volume(volume * _volume); }
162     };
163
164     /////////////////////////////////////////////////////////////////////////
165     // FGVoicePlayer::Voice::SilenceElement //////////////////////////
166     /////////////////////////////////////////////////////////////////////////
167
168     class SilenceElement : public Element
169     {
170         double _duration;
171         double start_time;
172
173     public:
174         inline SilenceElement (double duration)
175           : _duration(duration) { silence = true; }
176
177         virtual inline void play (float volume) { start_time = globals->get_sim_time_sec(); }
178         virtual inline bool is_playing () { return globals->get_sim_time_sec() - start_time < _duration; }
179     };
180
181     /////////////////////////////////////////////////////////////////////////
182     // FGVoicePlayer::Voice (continued) //////////////////////////////
183     /////////////////////////////////////////////////////////////////////////
184
185     Element *element;
186
187     inline Voice (FGVoicePlayer *_player)
188       : element(NULL), player(_player), volume(1.0) {}
189
190     virtual ~Voice ();
191
192     inline void append (Element *_element) { elements.push_back(_element); }
193
194     void play ();
195     void stop (bool now);
196     void set_volume (float _volume);
197     void volume_changed ();
198     void update ();
199
200   private:
201       FGVoicePlayer *player;
202
203       float volume;
204
205       vector<Element *>         elements;
206       vector<Element *>::iterator   iter;
207
208       inline float get_volume () const { return player->volume * player->speaker.volume * volume; }
209   };
210
211   ///////////////////////////////////////////////////////////////////////////
212   // FGVoicePlayer (continued) ///////////////////////////////////////
213   ///////////////////////////////////////////////////////////////////////////
214
215   struct
216   {
217     float volume;
218   } conf;
219
220   float volume;
221
222   Voice *voice;
223   Voice *next_voice;
224   bool paused;
225   string dev_name;
226   string dir_prefix;
227
228   inline FGVoicePlayer (PropertiesHandler* properties_handler, string _dev_name)
229     : volume(1.0), voice(NULL), next_voice(NULL), paused(false),
230       dev_name(_dev_name), dir_prefix(""),
231       speaker(this,properties_handler) {}
232
233   virtual ~FGVoicePlayer ();
234
235   void init ();
236   void pause();
237   void resume();
238   bool is_playing() { return (voice!=NULL);}
239
240   enum
241   {
242     PLAY_NOW      = 1 << 0,
243     PLAY_LOOPED   = 1 << 1
244   };
245   void play (Voice *_voice, unsigned int flags = 0);
246
247   enum
248   {
249     STOP_NOW      = 1 << 0
250   };
251   void stop (unsigned int flags = 0);
252
253   void set_volume (float _volume);
254   void update ();
255
256   void bind (SGPropertyNode *node, const char* default_dir_prefix);
257
258 public:
259
260   ///////////////////////////////////////////////////////////////////////////
261   // FGVoicePlayer::Speaker //////////////////////////////////////////
262   ///////////////////////////////////////////////////////////////////////////
263
264   class Speaker
265   {
266     FGVoicePlayer *player;
267     PropertiesHandler* properties_handler;
268
269     double    pitch;
270
271     template <class T>
272     inline void tie (SGPropertyNode *node, const char *name, T *ptr)
273     {
274     properties_handler->tie
275     (node, (string("speaker/") + name).c_str(),
276      RawValueMethodsData<FGVoicePlayer::Speaker,T,T*>
277      (*this, ptr,
278       &FGVoicePlayer::Speaker::get_property,
279       &FGVoicePlayer::Speaker::set_property));
280     }
281
282   public:
283     template <class T>
284     inline void set_property (T *ptr, T value) { *ptr = value; update_configuration(); }
285
286     template <class T>
287     inline T get_property (T *ptr) const { return *ptr; }
288
289     float volume;
290
291     inline Speaker (FGVoicePlayer *_player,PropertiesHandler* _properties_handler)
292   : player(_player),
293     properties_handler(_properties_handler),
294     pitch(1),
295     volume(1)
296     {
297     }
298
299     void bind (SGPropertyNode *node);
300     void update_configuration ();
301   };
302
303 protected:
304   ///////////////////////////////////////////////////////////////////////////
305   // FGVoicePlayer (continued) ///////////////////////////////////////
306   ///////////////////////////////////////////////////////////////////////////
307
308   SGSharedPtr<SGSampleGroup> _sgr;
309   Speaker speaker;
310
311   map< string, SGSharedPtr<SGSoundSample> >   samples;
312   vector<Voice *>         _voices;
313
314   bool looped;
315   bool next_looped;
316
317   SGSoundSample *get_sample (const char *name);
318
319   inline void append (Voice *voice, Voice::Element *element) { voice->append(element); }
320   inline void append (Voice *voice, const char *sample_name) { voice->append(new Voice::SampleElement(get_sample(sample_name))); }
321   inline void append (Voice *voice, double silence) { voice->append(new Voice::SilenceElement(silence)); }
322
323   inline void make_voice (Voice **voice) { *voice = new Voice(this); _voices.push_back(*voice); }
324
325   template <class T1>
326   inline void make_voice (Voice **voice, T1 e1) { make_voice(voice); append(*voice, e1); }
327   template <class T1, class T2>
328   inline void make_voice (Voice **voice, T1 e1, T2 e2) { make_voice(voice, e1); append(*voice, e2); }
329   template <class T1, class T2, class T3>
330   inline void make_voice (Voice **voice, T1 e1, T2 e2, T3 e3) { make_voice(voice, e1, e2); append(*voice, e3); }
331   template <class T1, class T2, class T3, class T4>
332   inline void make_voice (Voice **voice, T1 e1, T2 e2, T3 e3, T4 e4) { make_voice(voice, e1, e2, e3); append(*voice, e4); }
333 };
334
335 #endif // __SOUND_VOICEPLAYER_HXX