// voiceplayer.hxx -- voice/sound sample player // // Written by Jean-Yves Lefort, started September 2005. // // Copyright (C) 2005, 2006 Jean-Yves Lefort - jylefort@FreeBSD.org // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. #ifndef __SOUND_VOICEPLAYER_HXX #define __SOUND_VOICEPLAYER_HXX #include #include #include #include #include #include class SGSampleGroup; class SGSoundSample; #include
#ifdef _MSC_VER # pragma warning( push ) # pragma warning( disable: 4355 ) #endif ///////////////////////////////////////////////////////////////////////////// // FGVoicePlayer ///////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// class FGVoicePlayer { public: ///////////////////////////////////////////////////////////////////////////// // MK::RawValueMethodsData ///////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// template class RawValueMethodsData : public SGRawValue { public: typedef VT (C::*getter_t) (DT) const; typedef void (C::*setter_t) (DT, VT); RawValueMethodsData (C &obj, DT data, getter_t getter = 0, setter_t setter = 0) : _obj(obj), _data(data), _getter(getter), _setter(setter) {} virtual VT getValue () const { if (_getter) return (_obj.*_getter)(_data); else return SGRawValue::DefaultValue(); } virtual bool setValue (VT value) { if (_setter) { (_obj.*_setter)(_data, value); return true; } else return false; } virtual SGRawValue *clone () const { return new RawValueMethodsData(_obj, _data, _getter, _setter); } private: C &_obj; DT _data; getter_t _getter; setter_t _setter; }; class PropertiesHandler : public simgear::TiedPropertyList { public: template inline void tie (SGPropertyNode *node, const SGRawValue &raw_value) { Tie(node,raw_value); } template inline void tie (SGPropertyNode *node, const char *relative_path, const SGRawValue &raw_value) { Tie(node->getNode(relative_path, true),raw_value); } PropertiesHandler() {}; void unbind () {Untie();} }; /////////////////////////////////////////////////////////////////////////// // FGVoicePlayer::Voice //////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// class Voice { public: ///////////////////////////////////////////////////////////////////////// // FGVoicePlayer::Voice::Element //////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// class Element { public: bool silence; virtual ~Element() {} virtual inline void play (float volume) {} virtual inline void stop () {} virtual bool is_playing () = 0; virtual inline void set_volume (float volume) {} }; ///////////////////////////////////////////////////////////////////////// // FGVoicePlayer::Voice::SampleElement /////////////////////////// ///////////////////////////////////////////////////////////////////////// class SampleElement : public Element { SGSharedPtr _sample; float _volume; public: SampleElement (SGSharedPtr sample, float volume = 1.0); virtual void play (float volume); virtual void stop (); virtual bool is_playing (); virtual void set_volume (float volume); }; ///////////////////////////////////////////////////////////////////////// // FGVoicePlayer::Voice::SilenceElement ////////////////////////// ///////////////////////////////////////////////////////////////////////// class SilenceElement : public Element { double _duration; double start_time; public: inline SilenceElement (double duration) : _duration(duration) { silence = true; } virtual inline void play (float volume) { start_time = globals->get_sim_time_sec(); } virtual inline bool is_playing () { return globals->get_sim_time_sec() - start_time < _duration; } }; ///////////////////////////////////////////////////////////////////////// // FGVoicePlayer::Voice (continued) ////////////////////////////// ///////////////////////////////////////////////////////////////////////// Element *element; inline Voice (FGVoicePlayer *_player) : element(NULL), player(_player), volume(1.0) {} virtual ~Voice (); inline void append (Element *_element) { elements.push_back(_element); } void play (); void stop (bool now); void set_volume (float _volume); void volume_changed (); void update (); private: FGVoicePlayer *player; float volume; std::vector elements; std::vector::iterator iter; inline float get_volume () const { return player->volume * player->speaker.volume * volume; } }; /////////////////////////////////////////////////////////////////////////// // FGVoicePlayer (continued) /////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// struct { float volume; } conf; float volume; Voice *voice; Voice *next_voice; bool paused; std::string dev_name; std::string dir_prefix; FGVoicePlayer (PropertiesHandler* properties_handler, std::string _dev_name); virtual ~FGVoicePlayer (); void init (); void pause(); void resume(); bool is_playing() { return (voice!=NULL);} enum { PLAY_NOW = 1 << 0, PLAY_LOOPED = 1 << 1 }; void play (Voice *_voice, unsigned int flags = 0); enum { STOP_NOW = 1 << 0 }; void stop (unsigned int flags = 0); void set_volume (float _volume); void update (); void bind (SGPropertyNode *node, const char* default_dir_prefix); public: /////////////////////////////////////////////////////////////////////////// // FGVoicePlayer::Speaker ////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// class Speaker { FGVoicePlayer *player; PropertiesHandler* properties_handler; double pitch; template inline void tie (SGPropertyNode *node, const char *name, T *ptr) { properties_handler->tie (node, (std::string("speaker/") + name).c_str(), RawValueMethodsData (*this, ptr, &FGVoicePlayer::Speaker::get_property, &FGVoicePlayer::Speaker::set_property)); } public: template inline void set_property (T *ptr, T value) { *ptr = value; update_configuration(); } template inline T get_property (T *ptr) const { return *ptr; } float volume; inline Speaker (FGVoicePlayer *_player,PropertiesHandler* _properties_handler) : player(_player), properties_handler(_properties_handler), pitch(1), volume(1) { } void bind (SGPropertyNode *node); void update_configuration (); }; protected: /////////////////////////////////////////////////////////////////////////// // FGVoicePlayer (continued) /////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// SGSharedPtr _sgr; Speaker speaker; std::map< std::string, SGSharedPtr > samples; std::vector _voices; bool looped; bool next_looped; SGSoundSample *get_sample (const char *name); inline void append (Voice *voice, Voice::Element *element) { voice->append(element); } void append (Voice *voice, const char *sample_name); inline void append (Voice *voice, double silence) { voice->append(new Voice::SilenceElement(silence)); } inline void make_voice (Voice **voice) { *voice = new Voice(this); _voices.push_back(*voice); } template inline void make_voice (Voice **voice, T1 e1) { make_voice(voice); append(*voice, e1); } template inline void make_voice (Voice **voice, T1 e1, T2 e2) { make_voice(voice, e1); append(*voice, e2); } template inline void make_voice (Voice **voice, T1 e1, T2 e2, T3 e3) { make_voice(voice, e1, e2); append(*voice, e3); } template inline void make_voice (Voice **voice, T1 e1, T2 e2, T3 e3, T4 e4) { make_voice(voice, e1, e2, e3); append(*voice, e4); } }; #endif // __SOUND_VOICEPLAYER_HXX