Added a first pass at a C++ sound manager class.
This commit is contained in:
parent
5d423a94b0
commit
e9591422f3
7 changed files with 312 additions and 51 deletions
src
Controls
FDM/LaRCsim
Main
|
@ -25,7 +25,9 @@
|
|||
#define _CONTROLS_HXX
|
||||
|
||||
#include <simgear/misc/props.hxx>
|
||||
|
||||
#include <Main/fgfs.hxx>
|
||||
#include <Main/globals.hxx>
|
||||
|
||||
#ifndef __cplusplus
|
||||
# error This library requires C++
|
||||
|
@ -144,10 +146,16 @@ public:
|
|||
CLAMP( &rudder, -1.0, 1.0 );
|
||||
}
|
||||
inline void set_flaps( double pos ) {
|
||||
if ( flaps != pos ) {
|
||||
globals->get_soundmgr()->play_once( "flaps" );
|
||||
}
|
||||
flaps = pos;
|
||||
CLAMP( &flaps, 0.0, 1.0 );
|
||||
}
|
||||
inline void move_flaps( double amt ) {
|
||||
if ( fabs(amt) > 0.0 ) {
|
||||
globals->get_soundmgr()->play_once( "flaps" );
|
||||
}
|
||||
flaps += amt;
|
||||
CLAMP( &flaps, 0.0, 1.0 );
|
||||
}
|
||||
|
|
|
@ -36,6 +36,9 @@
|
|||
|
||||
$Header$
|
||||
$Log$
|
||||
Revision 1.19 2001/03/02 21:37:01 curt
|
||||
Added a first pass at a C++ sound manager class.
|
||||
|
||||
Revision 1.18 2000/12/13 22:02:02 curt
|
||||
MacOS changes contributed by Darrell Walisser (12/13/2000)
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ fgfs_SOURCES = \
|
|||
globals.cxx globals.hxx \
|
||||
keyboard.cxx keyboard.hxx \
|
||||
options.cxx options.hxx \
|
||||
soundmgr.cxx soundmgr.hxx \
|
||||
splash.cxx splash.hxx \
|
||||
viewer.cxx viewer.hxx \
|
||||
viewer_lookat.cxx viewer_lookat.hxx \
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include <simgear/timing/sg_time.hxx>
|
||||
#include <simgear/misc/props.hxx>
|
||||
|
||||
#include "soundmgr.hxx"
|
||||
#include "viewmgr.hxx"
|
||||
|
||||
FG_USING_STD( vector );
|
||||
|
@ -77,6 +78,9 @@ private:
|
|||
// Global autopilot "route"
|
||||
SGRoute *route;
|
||||
|
||||
// sound manager
|
||||
FGSoundMgr *soundmgr;
|
||||
|
||||
// viewer maneger
|
||||
FGViewMgr *viewmgr;
|
||||
FGViewer *current_view;
|
||||
|
@ -124,6 +128,9 @@ public:
|
|||
inline SGRoute *get_route() const { return route; }
|
||||
inline void set_route( SGRoute *r ) { route = r; }
|
||||
|
||||
inline FGSoundMgr *get_soundmgr() const { return soundmgr; }
|
||||
inline void set_soundmgr( FGSoundMgr *sm ) { soundmgr = sm; }
|
||||
|
||||
inline FGViewMgr *get_viewmgr() const { return viewmgr; }
|
||||
inline void set_viewmgr( FGViewMgr *vm ) { viewmgr = vm; }
|
||||
inline FGViewer *get_current_view() const { return current_view; }
|
||||
|
|
|
@ -56,11 +56,6 @@
|
|||
#include <plib/pu.h>
|
||||
#include <plib/ssg.h>
|
||||
|
||||
#ifdef ENABLE_AUDIO_SUPPORT
|
||||
# include <plib/sl.h>
|
||||
# include <plib/sm.h>
|
||||
#endif
|
||||
|
||||
#include <simgear/constants.h> // for VERSION
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/math/polar3d.hxx>
|
||||
|
@ -124,6 +119,10 @@ int objc=0;
|
|||
#include "keyboard.hxx"
|
||||
#include "splash.hxx"
|
||||
|
||||
#ifdef ENABLE_AUDIO_SUPPORT
|
||||
# include "soundmgr.hxx"
|
||||
#endif
|
||||
|
||||
#ifdef macintosh
|
||||
# include <console.h> // -dw- for command line dialog
|
||||
#endif
|
||||
|
@ -146,12 +145,8 @@ void fgReshape( int width, int height );
|
|||
|
||||
// Global structures for the Audio library
|
||||
#ifdef ENABLE_AUDIO_SUPPORT
|
||||
slEnvelope pitch_envelope ( 1, SL_SAMPLE_ONE_SHOT ) ;
|
||||
slEnvelope volume_envelope ( 1, SL_SAMPLE_ONE_SHOT ) ;
|
||||
slScheduler *audio_sched;
|
||||
smMixer *audio_mixer;
|
||||
slSample *s1;
|
||||
slSample *s2;
|
||||
static FGSimpleSound *s1;
|
||||
static FGSimpleSound *s2;
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -1037,12 +1032,14 @@ static void fgMainLoop( void ) {
|
|||
|
||||
// Run audio scheduler
|
||||
#ifdef ENABLE_AUDIO_SUPPORT
|
||||
if ( fgGetBool("/sim/sound") && !audio_sched->not_working() ) {
|
||||
|
||||
if ( fgGetBool("/sim/sound") && globals->get_soundmgr()->is_working() ) {
|
||||
if ( fgGetString("/sim/aircraft") == "c172" ) {
|
||||
// pitch corresponds to rpm
|
||||
// volume corresponds to manifold pressure
|
||||
|
||||
// cout << "AUDIO working = "
|
||||
// << globals->get_soundmgr()->is_working() << endl;
|
||||
|
||||
double rpm_factor;
|
||||
if ( cur_fdm_state->get_engine(0) != NULL ) {
|
||||
rpm_factor = cur_fdm_state->get_engine(0)->get_RPM() / 2500.0;
|
||||
|
@ -1058,7 +1055,6 @@ static void fgMainLoop( void ) {
|
|||
// and sounds bad to boot. :-)
|
||||
if (pitch < 0.7) { pitch = 0.7; }
|
||||
if (pitch > 5.0) { pitch = 5.0; }
|
||||
// cout << "pitch = " << pitch << endl;
|
||||
|
||||
double mp_factor;
|
||||
if ( cur_fdm_state->get_engine(0) != NULL ) {
|
||||
|
@ -1077,15 +1073,15 @@ static void fgMainLoop( void ) {
|
|||
if ( volume > 1.0 ) { volume = 1.0; }
|
||||
// cout << "volume = " << volume << endl;
|
||||
|
||||
pitch_envelope.setStep ( 0, 0.01, pitch );
|
||||
volume_envelope.setStep ( 0, 0.01, volume );
|
||||
s1->set_pitch( pitch );
|
||||
s1->set_volume( volume );
|
||||
} else {
|
||||
double param = controls.get_throttle( 0 ) * 2.0 + 1.0;
|
||||
pitch_envelope.setStep ( 0, 0.01, param );
|
||||
volume_envelope.setStep ( 0, 0.01, param );
|
||||
s1->set_pitch( param );
|
||||
s1->set_volume( param );
|
||||
}
|
||||
|
||||
audio_sched -> update();
|
||||
globals->get_soundmgr()->update();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1185,40 +1181,19 @@ static void fgIdleFunction ( void ) {
|
|||
#endif // WIN32
|
||||
|
||||
if ( fgGetBool("/sim/sound") ) {
|
||||
audio_sched = new slScheduler ( 8000 );
|
||||
audio_mixer = new smMixer;
|
||||
audio_mixer -> setMasterVolume ( 80 ) ; /* 80% of max volume. */
|
||||
audio_sched -> setSafetyMargin ( 1.0 ) ;
|
||||
globals->get_soundmgr()->init();
|
||||
|
||||
FGPath slfile( globals->get_fg_root() );
|
||||
slfile.append( "Sounds/wasp.wav" );
|
||||
|
||||
s1 = new slSample ( (char *)slfile.c_str() );
|
||||
s1 = new FGSimpleSound( "Sounds/wasp.wav" );
|
||||
globals->get_soundmgr()->add( s1, "engine loop" );
|
||||
globals->get_soundmgr()->play_looped( "engine loop" );
|
||||
FG_LOG( FG_GENERAL, FG_INFO,
|
||||
"Rate = " << s1 -> getRate()
|
||||
<< " Bps = " << s1 -> getBps()
|
||||
<< " Stereo = " << s1 -> getStereo() );
|
||||
audio_sched -> loopSample ( s1 );
|
||||
"Rate = " << s1->get_sample()->getRate()
|
||||
<< " Bps = " << s1->get_sample()->getBps()
|
||||
<< " Stereo = " << s1->get_sample()->getStereo() );
|
||||
|
||||
if ( audio_sched->not_working() ) {
|
||||
// skip
|
||||
} else {
|
||||
pitch_envelope.setStep ( 0, 0.01, 0.6 );
|
||||
volume_envelope.setStep ( 0, 0.01, 0.6 );
|
||||
|
||||
audio_sched -> addSampleEnvelope( s1, 0, 0,
|
||||
&pitch_envelope,
|
||||
SL_PITCH_ENVELOPE );
|
||||
audio_sched -> addSampleEnvelope( s1, 0, 1,
|
||||
&volume_envelope,
|
||||
SL_VOLUME_ENVELOPE );
|
||||
}
|
||||
|
||||
// strcpy(slfile, path);
|
||||
// strcat(slfile, "thunder.wav");
|
||||
// s2 -> loadFile ( slfile );
|
||||
// s2 -> adjustVolume(0.5);
|
||||
// audio_sched -> playSample ( s2 );
|
||||
s2 = new FGSimpleSound( "Sounds/corflaps.wav" );
|
||||
s2->set_volume( 2.0 );
|
||||
globals->get_soundmgr()->add( s2, "flaps" );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1404,6 +1379,11 @@ int main( int argc, char **argv ) {
|
|||
SGRoute *route = new SGRoute;
|
||||
globals->set_route( route );
|
||||
|
||||
#ifdef ENABLE_AUDIO_SUPPORT
|
||||
FGSoundMgr *soundmgr = new FGSoundMgr;
|
||||
globals->set_soundmgr( soundmgr );
|
||||
#endif
|
||||
|
||||
FGViewMgr *viewmgr = new FGViewMgr;
|
||||
globals->set_viewmgr( viewmgr );
|
||||
|
||||
|
|
149
src/Main/soundmgr.cxx
Normal file
149
src/Main/soundmgr.cxx
Normal file
|
@ -0,0 +1,149 @@
|
|||
// soundmgr.cxx -- Sound effect management class
|
||||
//
|
||||
// Written by Curtis Olson, started March 2001.
|
||||
//
|
||||
// Copyright (C) 2001 Curtis L. Olson - curt@flightgear.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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id$
|
||||
|
||||
|
||||
#include <simgear/misc/fgpath.hxx>
|
||||
|
||||
#include "globals.hxx"
|
||||
#include "soundmgr.hxx"
|
||||
|
||||
|
||||
// constructor
|
||||
FGSimpleSound::FGSimpleSound( string file ) {
|
||||
FGPath slfile( globals->get_fg_root() );
|
||||
slfile.append( file );
|
||||
sample = new slSample ( (char *)slfile.c_str() );
|
||||
pitch_envelope = new slEnvelope( 1, SL_SAMPLE_ONE_SHOT );
|
||||
volume_envelope = new slEnvelope( 1, SL_SAMPLE_ONE_SHOT );
|
||||
pitch_envelope->setStep ( 0, 0.01, 1.0 );
|
||||
volume_envelope->setStep ( 0, 0.01, 1.0 );
|
||||
}
|
||||
|
||||
// destructor
|
||||
FGSimpleSound::~FGSimpleSound() {
|
||||
delete pitch_envelope;
|
||||
delete volume_envelope;
|
||||
delete sample;
|
||||
}
|
||||
|
||||
|
||||
// constructor
|
||||
FGSoundMgr::FGSoundMgr() {
|
||||
audio_sched = new slScheduler( 8000 );
|
||||
audio_mixer = new smMixer;
|
||||
}
|
||||
|
||||
// destructor
|
||||
FGSoundMgr::~FGSoundMgr() {
|
||||
sound_map_iterator current = sounds.begin();
|
||||
sound_map_iterator end = sounds.end();
|
||||
for ( ; current != end; ++current ) {
|
||||
FGSimpleSound *s = current->second;
|
||||
delete s->get_sample();
|
||||
delete s;
|
||||
}
|
||||
|
||||
delete audio_sched;
|
||||
delete audio_mixer;
|
||||
}
|
||||
|
||||
|
||||
// initialize the sound manager
|
||||
bool FGSoundMgr::init() {
|
||||
audio_mixer -> setMasterVolume ( 80 ) ; /* 80% of max volume. */
|
||||
audio_sched -> setSafetyMargin ( 1.0 ) ;
|
||||
|
||||
sound_map_iterator current = sounds.begin();
|
||||
sound_map_iterator end = sounds.end();
|
||||
for ( ; current != end; ++current ) {
|
||||
FGSimpleSound *s = current->second;
|
||||
delete s->get_sample();
|
||||
delete s;
|
||||
}
|
||||
sounds.clear();
|
||||
|
||||
if ( audio_sched->not_working() ) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// run the audio scheduler
|
||||
bool FGSoundMgr::update() {
|
||||
if ( !audio_sched->not_working() ) {
|
||||
audio_sched -> update();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// add a sound effect
|
||||
bool FGSoundMgr::add( FGSimpleSound *sound, const string& refname ) {
|
||||
sounds[refname] = sound;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// tell the scheduler to play the indexed sample in a continuous
|
||||
// loop
|
||||
bool FGSoundMgr::play_looped( const string& refname ) {
|
||||
sound_map_iterator it = sounds.find( refname );
|
||||
if ( it != sounds.end() ) {
|
||||
FGSimpleSound *sample = it->second;
|
||||
audio_sched->loopSample( sample->get_sample() );
|
||||
audio_sched->addSampleEnvelope( sample->get_sample(), 0, 0,
|
||||
sample->get_pitch_envelope(),
|
||||
SL_PITCH_ENVELOPE );
|
||||
audio_sched->addSampleEnvelope( sample->get_sample(), 0, 1,
|
||||
sample->get_volume_envelope(),
|
||||
SL_VOLUME_ENVELOPE );
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// tell the scheduler to play the indexed sample once
|
||||
bool FGSoundMgr::FGSoundMgr::play_once( const string& refname ) {
|
||||
sound_map_iterator it = sounds.find( refname );
|
||||
if ( it != sounds.end() ) {
|
||||
FGSimpleSound *sample = it->second;
|
||||
audio_sched->playSample( sample->get_sample() );
|
||||
audio_sched->addSampleEnvelope( sample->get_sample(), 0, 0,
|
||||
sample->get_pitch_envelope(),
|
||||
SL_PITCH_ENVELOPE );
|
||||
audio_sched->addSampleEnvelope( sample->get_sample(), 0, 1,
|
||||
sample->get_volume_envelope(),
|
||||
SL_VOLUME_ENVELOPE );
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
113
src/Main/soundmgr.hxx
Normal file
113
src/Main/soundmgr.hxx
Normal file
|
@ -0,0 +1,113 @@
|
|||
// soundmgr.hxx -- Sound effect management class
|
||||
//
|
||||
// Written by Curtis Olson, started March 2001.
|
||||
//
|
||||
// Copyright (C) 2001 Curtis L. Olson - curt@flightgear.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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id$
|
||||
|
||||
|
||||
#ifndef _SOUNDMGR_HXX
|
||||
#define _SOUNDMGR_HXX
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include STL_STRING
|
||||
#include <map>
|
||||
|
||||
#include <plib/sl.h>
|
||||
#include <plib/sm.h>
|
||||
|
||||
FG_USING_STD(map);
|
||||
FG_USING_STD(string);
|
||||
|
||||
|
||||
// manages everything we need to know for an individual sound sample
|
||||
class FGSimpleSound {
|
||||
|
||||
slSample *sample;
|
||||
slEnvelope *pitch_envelope;
|
||||
slEnvelope *volume_envelope;
|
||||
double pitch;
|
||||
double volume;
|
||||
|
||||
public:
|
||||
|
||||
FGSimpleSound( string file );
|
||||
~FGSimpleSound();
|
||||
|
||||
inline double get_pitch() const { return pitch; }
|
||||
inline void set_pitch( double p ) {
|
||||
pitch = p;
|
||||
pitch_envelope->setStep( 0, 0.01, pitch );
|
||||
}
|
||||
inline double get_volume() const { return volume; }
|
||||
inline void set_volume( double v ) {
|
||||
volume = v;
|
||||
volume_envelope->setStep( 0, 0.01, volume );
|
||||
}
|
||||
|
||||
inline slSample *get_sample() { return sample; }
|
||||
inline slEnvelope *get_pitch_envelope() { return pitch_envelope; }
|
||||
inline slEnvelope *get_volume_envelope() { return volume_envelope; }
|
||||
};
|
||||
|
||||
|
||||
typedef map < string, FGSimpleSound * > sound_map;
|
||||
typedef sound_map::iterator sound_map_iterator;
|
||||
typedef sound_map::const_iterator const_sound_map_iterator;
|
||||
|
||||
|
||||
class FGSoundMgr {
|
||||
|
||||
slScheduler *audio_sched;
|
||||
smMixer *audio_mixer;
|
||||
sound_map sounds;
|
||||
|
||||
public:
|
||||
|
||||
FGSoundMgr();
|
||||
~FGSoundMgr();
|
||||
|
||||
// initialize the sound manager
|
||||
bool init();
|
||||
|
||||
// run the audio scheduler
|
||||
bool update();
|
||||
|
||||
// is audio working?
|
||||
inline bool is_working() const { return !audio_sched->not_working(); }
|
||||
|
||||
// add a sound effect, return the index of the sound
|
||||
bool add( FGSimpleSound *sound, const string& refname );
|
||||
|
||||
// tell the scheduler to play the indexed sample in a continuous
|
||||
// loop
|
||||
bool play_looped( const string& refname );
|
||||
|
||||
// tell the scheduler to play the indexed sample once
|
||||
bool play_once( const string& refname );
|
||||
};
|
||||
|
||||
|
||||
#endif // _SOUNDMGR_HXX
|
||||
|
||||
|
Loading…
Add table
Reference in a new issue