1 // voiceplayer.cxx -- voice/sound sample player
3 // Written by Jean-Yves Lefort, started September 2005.
5 // Copyright (C) 2005, 2006 Jean-Yves Lefort - jylefort@FreeBSD.org
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.
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.
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.
21 ///////////////////////////////////////////////////////////////////////////////
24 # pragma warning( disable: 4355 )
31 #include "voiceplayer.hxx"
41 #include <simgear/debug/logstream.hxx>
42 #include <simgear/sound/soundmgr_openal.hxx>
43 #include <simgear/sound/sample_group.hxx>
44 #include <simgear/structure/exception.hxx>
50 ///////////////////////////////////////////////////////////////////////////////
51 // constants //////////////////////////////////////////////////////////////////
52 ///////////////////////////////////////////////////////////////////////////////
55 ///////////////////////////////////////////////////////////////////////////////
56 // helpers ////////////////////////////////////////////////////////////////////
57 ///////////////////////////////////////////////////////////////////////////////
58 #define ADD_VOICE(Var,Sample,Twice) \
59 { make_voice(&Var);append(Var,Sample);\
60 if (Twice) append(Var,Sample); }
62 #define test_bits(_bits, _test) (((_bits) & (_test)) != 0)
64 /////////////////////////////////////////////////////////////////////////
65 // FGVoicePlayer::Voice::SampleElement ///////////////////////////
66 /////////////////////////////////////////////////////////////////////////
68 FGVoicePlayer::Voice::SampleElement::SampleElement (SGSharedPtr<SGSoundSample> sample, float volume)
69 : _sample(sample), _volume(volume)
74 void FGVoicePlayer::Voice::SampleElement::play (float volume)
76 if (_sample && (volume > 0.05)) { set_volume(volume); _sample->play_once(); }
79 void FGVoicePlayer::Voice::SampleElement::stop ()
81 if (_sample) _sample->stop();
84 bool FGVoicePlayer::Voice::SampleElement::is_playing ()
86 return _sample ? _sample->is_playing() : false;
89 void FGVoicePlayer::Voice::SampleElement::set_volume (float volume)
91 if (_sample) _sample->set_volume(volume * _volume);
94 ///////////////////////////////////////////////////////////////////////////////
95 // FGVoicePlayer //////////////////////////////////////////////////////////////
96 ///////////////////////////////////////////////////////////////////////////////
99 FGVoicePlayer::Speaker::bind (SGPropertyNode *node)
101 // uses xmlsound property names
102 tie(node, "volume", &volume);
103 tie(node, "pitch", &pitch);
107 FGVoicePlayer::Speaker::update_configuration ()
109 map< string, SGSharedPtr<SGSoundSample> >::iterator iter;
110 for (iter = player->samples.begin(); iter != player->samples.end(); iter++)
112 SGSoundSample *sample = (*iter).second;
114 sample->set_pitch(pitch);
118 player->voice->volume_changed();
121 FGVoicePlayer::Voice::~Voice ()
123 for (iter = elements.begin(); iter != elements.end(); iter++)
124 delete *iter; // we owned the element
129 FGVoicePlayer::Voice::play ()
131 iter = elements.begin();
134 element->play(get_volume());
138 FGVoicePlayer::Voice::stop (bool now)
142 if (now || element->silence)
148 iter = elements.end() - 1; // stop after the current element finishes
153 FGVoicePlayer::Voice::set_volume (float _volume)
160 FGVoicePlayer::Voice::volume_changed ()
163 element->set_volume(get_volume());
167 FGVoicePlayer::Voice::update ()
171 if (! element->is_playing())
173 if (++iter == elements.end())
178 element->play(get_volume());
184 FGVoicePlayer::FGVoicePlayer (PropertiesHandler* properties_handler, string _dev_name)
185 : volume(1.0), voice(NULL), next_voice(NULL), paused(false),
186 dev_name(_dev_name), dir_prefix(""),
187 speaker(this,properties_handler)
192 FGVoicePlayer::~FGVoicePlayer ()
194 vector<Voice *>::iterator iter1;
195 for (iter1 = _voices.begin(); iter1 != _voices.end(); iter1++)
202 FGVoicePlayer::bind (SGPropertyNode *node, const char* default_dir_prefix)
204 dir_prefix = node->getStringValue("voice/file-prefix", default_dir_prefix);
209 FGVoicePlayer::init ()
211 SGSoundMgr *smgr = globals->get_soundmgr();
212 _sgr = smgr->find("avionics", true);
213 _sgr->tie_to_listener();
214 speaker.update_configuration();
218 FGVoicePlayer::pause()
231 FGVoicePlayer::resume()
243 FGVoicePlayer::get_sample (const char *name)
246 refname = dev_name + "/" + dir_prefix + name;
248 SGSoundSample *sample = _sgr->find(refname);
251 string filename = dir_prefix + string(name) + ".wav";
252 sample = new SGSoundSample(filename.c_str(), SGPath());
254 _sgr->add(sample, refname);
255 samples[refname] = sample;
262 FGVoicePlayer::play (Voice *_voice, unsigned int flags)
266 if (test_bits(flags, PLAY_NOW) || ! voice ||
267 (voice->element && voice->element->silence))
273 looped = test_bits(flags, PLAY_LOOPED);
284 next_looped = test_bits(flags, PLAY_LOOPED);
289 FGVoicePlayer::stop (unsigned int flags)
293 voice->stop(test_bits(flags, STOP_NOW));
303 FGVoicePlayer::set_volume (float _volume)
307 voice->volume_changed();
311 FGVoicePlayer::update ()
319 if (! voice->element || voice->element->silence)
322 looped = next_looped;
332 if (! voice->element)
344 FGVoicePlayer::append (Voice *voice, const char *sample_name)
346 voice->append(new Voice::SampleElement(get_sample(sample_name)));