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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 34 class SGSampleGroup; 35 class SGSoundSample; 36 37 #include <Main/globals.hxx> 38 39 #ifdef _MSC_VER 40 # pragma warning( push ) 41 # pragma warning( disable: 4355 ) 42 #endif 43 44 ///////////////////////////////////////////////////////////////////////////// 45 // FGVoicePlayer ///////////////////////////////////////////////////// 46 ///////////////////////////////////////////////////////////////////////////// 47 48 class FGVoicePlayer 49 { 50 public: 51 52 ///////////////////////////////////////////////////////////////////////////// 53 // MK::RawValueMethodsData ///////////////////////////////////////////// 54 ///////////////////////////////////////////////////////////////////////////// 55 56 template <class C, class VT, class DT> 57 class RawValueMethodsData : public SGRawValue<VT> 58 { 59 public: 60 typedef VT (C::*getter_t) (DT) const; 61 typedef void (C::*setter_t) (DT, VT); 62 RawValueMethodsData(C & obj,DT data,getter_t getter=0,setter_t setter=0)63 RawValueMethodsData (C &obj, DT data, getter_t getter = 0, setter_t setter = 0) 64 : _obj(obj), _data(data), _getter(getter), _setter(setter) {} 65 getValue() const66 virtual VT getValue () const 67 { 68 if (_getter) 69 return (_obj.*_getter)(_data); 70 else 71 return SGRawValue<VT>::DefaultValue(); 72 } setValue(VT value)73 virtual bool setValue (VT value) 74 { 75 if (_setter) 76 { 77 (_obj.*_setter)(_data, value); 78 return true; 79 } 80 else 81 return false; 82 } clone() const83 virtual SGRawValue<VT> *clone () const 84 { 85 return new RawValueMethodsData<C,VT,DT>(_obj, _data, _getter, _setter); 86 } 87 88 private: 89 C &_obj; 90 DT _data; 91 getter_t _getter; 92 setter_t _setter; 93 }; 94 95 class PropertiesHandler : public simgear::TiedPropertyList 96 { 97 public: 98 99 template <class T> tie(SGPropertyNode * node,const SGRawValue<T> & raw_value)100 inline void tie (SGPropertyNode *node, const SGRawValue<T> &raw_value) 101 { 102 Tie(node,raw_value); 103 } 104 105 template <class T> tie(SGPropertyNode * node,const char * relative_path,const SGRawValue<T> & raw_value)106 inline void tie (SGPropertyNode *node, 107 const char *relative_path, 108 const SGRawValue<T> &raw_value) 109 { 110 Tie(node->getNode(relative_path, true),raw_value); 111 } 112 PropertiesHandler()113 PropertiesHandler() {}; 114 unbind()115 void unbind () {Untie();} 116 }; 117 118 /////////////////////////////////////////////////////////////////////////// 119 // FGVoicePlayer::Voice //////////////////////////////////////////// 120 /////////////////////////////////////////////////////////////////////////// 121 122 class Voice 123 { 124 public: 125 126 ///////////////////////////////////////////////////////////////////////// 127 // FGVoicePlayer::Voice::Element //////////////////////////////////////// 128 ///////////////////////////////////////////////////////////////////////// 129 130 class Element 131 { 132 public: 133 bool silence; 134 ~Element()135 virtual ~Element() {} play(float volume)136 virtual inline void play (float volume) {} stop()137 virtual inline void stop () {} 138 virtual bool is_playing () = 0; set_volume(float volume)139 virtual inline void set_volume (float volume) {} 140 }; 141 142 ///////////////////////////////////////////////////////////////////////// 143 // FGVoicePlayer::Voice::SampleElement /////////////////////////// 144 ///////////////////////////////////////////////////////////////////////// 145 146 class SampleElement : public Element 147 { 148 SGSharedPtr<SGSoundSample> _sample; 149 float _volume; 150 151 public: 152 SampleElement (SGSharedPtr<SGSoundSample> sample, float volume = 1.0); 153 154 virtual void play (float volume); 155 virtual void stop (); 156 virtual bool is_playing (); 157 virtual void set_volume (float volume); 158 }; 159 160 ///////////////////////////////////////////////////////////////////////// 161 // FGVoicePlayer::Voice::SilenceElement ////////////////////////// 162 ///////////////////////////////////////////////////////////////////////// 163 164 class SilenceElement : public Element 165 { 166 double _duration; 167 double start_time; 168 169 public: SilenceElement(double duration)170 inline SilenceElement (double duration) 171 : _duration(duration) { silence = true; } 172 play(float volume)173 virtual inline void play (float volume) { start_time = globals->get_sim_time_sec(); } is_playing()174 virtual inline bool is_playing () { return globals->get_sim_time_sec() - start_time < _duration; } 175 }; 176 177 ///////////////////////////////////////////////////////////////////////// 178 // FGVoicePlayer::Voice (continued) ////////////////////////////// 179 ///////////////////////////////////////////////////////////////////////// 180 181 Element *element; 182 Voice(FGVoicePlayer * _player)183 inline Voice (FGVoicePlayer *_player) 184 : element(NULL), player(_player), volume(1.0) {} 185 186 virtual ~Voice (); 187 append(Element * _element)188 inline void append (Element *_element) { elements.push_back(_element); } 189 190 void play (); 191 void stop (bool now); 192 void set_volume (float _volume); 193 void volume_changed (); 194 void update (); 195 196 private: 197 FGVoicePlayer *player; 198 199 float volume; 200 201 std::vector<Element *> elements; 202 std::vector<Element *>::iterator iter; 203 get_volume() const204 inline float get_volume () const { return player->volume * player->speaker.volume * volume; } 205 }; 206 207 /////////////////////////////////////////////////////////////////////////// 208 // FGVoicePlayer (continued) /////////////////////////////////////// 209 /////////////////////////////////////////////////////////////////////////// 210 211 struct 212 { 213 float volume; 214 } conf; 215 216 float volume; 217 218 Voice *voice; 219 Voice *next_voice; 220 bool paused; 221 std::string dev_name; 222 std::string dir_prefix; 223 224 FGVoicePlayer (PropertiesHandler* properties_handler, std::string _dev_name); 225 226 virtual ~FGVoicePlayer (); 227 228 void init (); 229 void pause(); 230 void resume(); is_playing()231 bool is_playing() { return (voice!=NULL);} 232 233 enum 234 { 235 PLAY_NOW = 1 << 0, 236 PLAY_LOOPED = 1 << 1 237 }; 238 void play (Voice *_voice, unsigned int flags = 0); 239 240 enum 241 { 242 STOP_NOW = 1 << 0 243 }; 244 void stop (unsigned int flags = 0); 245 246 void set_volume (float _volume); 247 void update (); 248 249 void bind (SGPropertyNode *node, const char* default_dir_prefix); 250 251 public: 252 253 /////////////////////////////////////////////////////////////////////////// 254 // FGVoicePlayer::Speaker ////////////////////////////////////////// 255 /////////////////////////////////////////////////////////////////////////// 256 257 class Speaker 258 { 259 FGVoicePlayer *player; 260 PropertiesHandler* properties_handler; 261 262 double pitch; 263 264 template <class T> tie(SGPropertyNode * node,const char * name,T * ptr)265 inline void tie (SGPropertyNode *node, const char *name, T *ptr) 266 { 267 properties_handler->tie 268 (node, (std::string("speaker/") + name).c_str(), 269 RawValueMethodsData<FGVoicePlayer::Speaker,T,T*> 270 (*this, ptr, 271 &FGVoicePlayer::Speaker::get_property, 272 &FGVoicePlayer::Speaker::set_property)); 273 } 274 275 public: 276 template <class T> set_property(T * ptr,T value)277 inline void set_property (T *ptr, T value) { *ptr = value; update_configuration(); } 278 279 template <class T> get_property(T * ptr) const280 inline T get_property (T *ptr) const { return *ptr; } 281 282 float volume; 283 Speaker(FGVoicePlayer * _player,PropertiesHandler * _properties_handler)284 inline Speaker (FGVoicePlayer *_player,PropertiesHandler* _properties_handler) 285 : player(_player), 286 properties_handler(_properties_handler), 287 pitch(1), 288 volume(1) 289 { 290 } 291 292 void bind (SGPropertyNode *node); 293 void update_configuration (); 294 }; 295 296 protected: 297 /////////////////////////////////////////////////////////////////////////// 298 // FGVoicePlayer (continued) /////////////////////////////////////// 299 /////////////////////////////////////////////////////////////////////////// 300 301 SGSharedPtr<SGSampleGroup> _sgr; 302 Speaker speaker; 303 304 std::map< std::string, SGSharedPtr<SGSoundSample> > samples; 305 std::vector<Voice *> _voices; 306 307 bool looped; 308 bool next_looped; 309 310 SGSoundSample *get_sample (const char *name); 311 append(Voice * voice,Voice::Element * element)312 inline void append (Voice *voice, Voice::Element *element) { voice->append(element); } 313 void append (Voice *voice, const char *sample_name); append(Voice * voice,double silence)314 inline void append (Voice *voice, double silence) { voice->append(new Voice::SilenceElement(silence)); } 315 make_voice(Voice ** voice)316 inline void make_voice (Voice **voice) { *voice = new Voice(this); _voices.push_back(*voice); } 317 318 template <class T1> make_voice(Voice ** voice,T1 e1)319 inline void make_voice (Voice **voice, T1 e1) { make_voice(voice); append(*voice, e1); } 320 template <class T1, class T2> make_voice(Voice ** voice,T1 e1,T2 e2)321 inline void make_voice (Voice **voice, T1 e1, T2 e2) { make_voice(voice, e1); append(*voice, e2); } 322 template <class T1, class T2, class T3> make_voice(Voice ** voice,T1 e1,T2 e2,T3 e3)323 inline void make_voice (Voice **voice, T1 e1, T2 e2, T3 e3) { make_voice(voice, e1, e2); append(*voice, e3); } 324 template <class T1, class T2, class T3, class T4> make_voice(Voice ** voice,T1 e1,T2 e2,T3 e3,T4 e4)325 inline void make_voice (Voice **voice, T1 e1, T2 e2, T3 e3, T4 e4) { make_voice(voice, e1, e2, e3); append(*voice, e4); } 326 }; 327 328 #endif // __SOUND_VOICEPLAYER_HXX 329