diff --git a/panda/src/audio/audioSound.cxx b/panda/src/audio/audioSound.cxx index f309329dce..6285b1bbf9 100644 --- a/panda/src/audio/audioSound.cxx +++ b/panda/src/audio/audioSound.cxx @@ -44,6 +44,17 @@ get_3d_attributes(PN_stdfloat *px, PN_stdfloat *py, PN_stdfloat *pz, PN_stdfloat // Intentionally blank. } +void AudioSound:: +set_3d_direction(LVector3 d) { + // Intentionally blank. +} + +LVector3 AudioSound:: +get_3d_direction() const { + // Intentionally blank. + return ( 0.0f, 0.0f, 0.0f ); +} + void AudioSound:: set_3d_min_distance(PN_stdfloat dist) { // Intentionally blank. @@ -66,6 +77,39 @@ get_3d_max_distance() const { return 0.0f; } +void AudioSound:: +set_3d_cone_inner_angle(PN_stdfloat angle) { + // Intentionally blank. +} + +PN_stdfloat AudioSound:: +get_3d_cone_inner_angle() const { + // Intentionally blank. + return 0.0f; +} + +void AudioSound:: +set_3d_cone_outer_angle(PN_stdfloat angle) { + // Intentionally blank. +} + +PN_stdfloat AudioSound:: +get_3d_cone_outer_angle() const { + // Intentionally blank. + return 0.0f; +} + +void AudioSound:: +set_3d_cone_outer_gain(PN_stdfloat gain) { + // Intentionally blank. +} + +PN_stdfloat AudioSound:: +get_3d_cone_outer_gain() const { + // Intentionally blank. + return 0.0f; +} + /** * For use only with FMOD. */ diff --git a/panda/src/audio/audioSound.h b/panda/src/audio/audioSound.h index e7c418de91..c1aa059c35 100644 --- a/panda/src/audio/audioSound.h +++ b/panda/src/audio/audioSound.h @@ -19,6 +19,7 @@ #include "typedReferenceCount.h" #include "pointerTo.h" #include "filterProperties.h" +#include "luse.h" class AudioManager; @@ -96,11 +97,12 @@ PUBLISHED: // Controls the position of this sound's emitter. px, py and pz are the // emitter's position. vx, vy and vz are the emitter's velocity in UNITS // PER SECOND (default: meters). - virtual void set_3d_attributes(PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz, - PN_stdfloat vx, PN_stdfloat vy, PN_stdfloat vz); - virtual void get_3d_attributes(PN_stdfloat *px, PN_stdfloat *py, PN_stdfloat *pz, - PN_stdfloat *vx, PN_stdfloat *vy, PN_stdfloat *vz); + virtual void set_3d_attributes(PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz, PN_stdfloat vx, PN_stdfloat vy, PN_stdfloat vz); + virtual void get_3d_attributes(PN_stdfloat *px, PN_stdfloat *py, PN_stdfloat *pz, PN_stdfloat *vx, PN_stdfloat *vy, PN_stdfloat *vz); + // Controls the direction of this sound emitter. Currently implemented only for OpenAL. + virtual void set_3d_direction(LVector3 d); + virtual LVector3 get_3d_direction() const; // Controls the distance (in units) that this sound begins to fall off. // Also affects the rate it falls off. Default is 1.0 CloserFaster, <1.0 @@ -114,6 +116,19 @@ PUBLISHED: virtual void set_3d_max_distance(PN_stdfloat dist); virtual PN_stdfloat get_3d_max_distance() const; + // Sets the angle of the inner cone of a directional sound source. In the zone inside of the inner cone + // sound is emitted with the (normal) volume set by set_volume(). + virtual void set_3d_cone_inner_angle(PN_stdfloat angle); + virtual PN_stdfloat get_3d_cone_inner_angle() const; + // Sets the angle of the outer cone of a directional sound source. In the zone between + // the inner and the outer cone the volume is attenuated. + virtual void set_3d_cone_outer_angle(PN_stdfloat angle); + virtual PN_stdfloat get_3d_cone_outer_angle() const; + // Sets a factor applied to the volume set by set_volume() for the zone outside the outer cone. + // By default this is 0 (so no sound is heard inside the outer zone). + virtual void set_3d_cone_outer_gain(PN_stdfloat gain); + virtual PN_stdfloat get_3d_cone_outer_gain() const; + // speaker_mix is for use with FMOD. virtual PN_stdfloat get_speaker_mix(int speaker); virtual void set_speaker_mix(PN_stdfloat frontleft, PN_stdfloat frontright, PN_stdfloat center, PN_stdfloat sub, PN_stdfloat backleft, PN_stdfloat backright, PN_stdfloat sideleft, PN_stdfloat sideright); diff --git a/panda/src/audiotraits/openalAudioSound.cxx b/panda/src/audiotraits/openalAudioSound.cxx index 07d753f86b..cba7940f83 100644 --- a/panda/src/audiotraits/openalAudioSound.cxx +++ b/panda/src/audiotraits/openalAudioSound.cxx @@ -33,7 +33,7 @@ TypeHandle OpenALAudioSound::_type_handle; */ OpenALAudioSound:: -OpenALAudioSound(OpenALAudioManager* manager, +OpenALAudioSound(OpenALAudioManager *manager, MovieAudio *movie, bool positional, int mode) : @@ -59,7 +59,10 @@ OpenALAudioSound(OpenALAudioManager* manager, _current_time(0.0), _basename(movie->get_filename().get_basename()), _active(manager->get_active()), - _paused(false) + _paused(false), + _cone_inner_angle(360.0f), + _cone_outer_angle(360.0f), + _cone_outer_gain(0.0f) { _location[0] = 0.0f; _location[1] = 0.0f; @@ -67,6 +70,9 @@ OpenALAudioSound(OpenALAudioManager* manager, _velocity[0] = 0.0f; _velocity[1] = 0.0f; _velocity[2] = 0.0f; + _direction[0] = 0.0f; + _direction[1] = 0.0f; + _direction[2] = 0.0f; ReMutexHolder holder(OpenALAudioManager::_lock); @@ -122,7 +128,7 @@ play() { if (!is_valid()) return; - PN_stdfloat px,py,pz,vx,vy,vz; + PN_stdfloat px, py, pz, vx, vy, vz; if (!_active) { _paused = true; @@ -157,8 +163,9 @@ play() { set_3d_min_distance(_min_dist); set_3d_max_distance(_max_dist); set_3d_drop_off_factor(_drop_off_factor); - get_3d_attributes(&px,&py,&pz,&vx,&vy,&vz); + get_3d_attributes(&px, &py, &pz, &vx, &vy, &vz); set_3d_attributes(px, py, pz, vx, vy, vz); + set_3d_direction(get_3d_direction()); _playing_loops = _loop_count; if (_playing_loops == 0) { @@ -762,6 +769,41 @@ get_3d_attributes(PN_stdfloat *px, PN_stdfloat *py, PN_stdfloat *pz, PN_stdfloat *vz = _velocity[1]; } +/** +* Set the direction of this sound +* +* Both Panda3D and OpenAL use a right handed coordinate system. However, in +* Panda3D the Y-Axis is going into the Screen and the Z-Axis is going up. In +* OpenAL the Y-Axis is going up and the Z-Axis is coming out of the screen. +* +* The solution is simple, we just flip the Y and Z axis and negate the Z, as +* we move coordinates from Panda to OpenAL and back. +*/ +void OpenALAudioSound:: +set_3d_direction(LVector3 d) { + ReMutexHolder holder(OpenALAudioManager::_lock); + _direction[0] = d.get_x(); + _direction[1] = d.get_z(); + _direction[2] = -d.get_y(); + + if (is_playing()) { + _manager->make_current(); + + alGetError(); // clear errors + alSourcefv(_source, AL_DIRECTION, _direction); + al_audio_errcheck("alSourcefv(_source,AL_DIRECTION)"); + } +} + +/** + * Get the direction of this sound. + */ +LVector3 OpenALAudioSound:: +get_3d_direction() const { + ReMutexHolder holder(OpenALAudioManager::_lock); + return LVector3(_direction[0], -_direction[2], _direction[1]); +} + /** * Set the distance that this sound begins to fall off. Also affects the rate * it falls off. @@ -838,6 +880,81 @@ get_3d_drop_off_factor() const { return _drop_off_factor; } +/** + * Set the inner angle of a directional sound + */ +void OpenALAudioSound:: +set_3d_cone_inner_angle(PN_stdfloat angle) { + ReMutexHolder holder(OpenALAudioManager::_lock); + _cone_inner_angle = angle; + + if (is_playing()) { + _manager->make_current(); + + alGetError(); // clear errors + alSourcef(_source, AL_CONE_INNER_ANGLE, _cone_inner_angle); + al_audio_errcheck("alSourcefv(_source,AL_CONE_INNER_ANGLE)"); + } +} + +/** + * Get the inner angle of a directional sound + */ +PN_stdfloat OpenALAudioSound:: +get_3d_cone_inner_angle() const { + return _cone_inner_angle; +} + +/** + * Set the outer angle of a directional sound + */ +void OpenALAudioSound:: +set_3d_cone_outer_angle(PN_stdfloat angle) { + ReMutexHolder holder(OpenALAudioManager::_lock); + _cone_outer_angle = angle; + + if (is_playing()) { + _manager->make_current(); + + alGetError(); // clear errors + alSourcef(_source, AL_CONE_OUTER_ANGLE, _cone_outer_angle); + al_audio_errcheck("alSourcefv(_source,AL_CONE_OUTER_ANGLE)"); + } +} + +/** + * Get the outer angle of a directional sound + */ +PN_stdfloat OpenALAudioSound:: +get_3d_cone_outer_angle() const { + return _cone_outer_angle; +} + +/** + * Set the outer gain factor of a directional sound + */ +void OpenALAudioSound:: +set_3d_cone_outer_gain(PN_stdfloat gain) { + ReMutexHolder holder(OpenALAudioManager::_lock); + _cone_outer_gain = gain; + + if (is_playing()) { + _manager->make_current(); + + alGetError(); // clear errors + alSourcef(_source, AL_CONE_OUTER_GAIN, _cone_outer_gain); + al_audio_errcheck("alSourcefv(_source,AL_CONE_OUTER_GAIN)"); + } +} + +/** + * Get the outer gain of a directional sound + */ +PN_stdfloat OpenALAudioSound:: +get_3d_cone_outer_gain() const { + return _cone_outer_gain; +} + /** * Sets whether the sound is marked "active". By default, the active flag is * true for all sounds. If the active flag is set to false for any particular diff --git a/panda/src/audiotraits/openalAudioSound.h b/panda/src/audiotraits/openalAudioSound.h index 4b050cef74..a3d19dca08 100644 --- a/panda/src/audiotraits/openalAudioSound.h +++ b/panda/src/audiotraits/openalAudioSound.h @@ -90,6 +90,10 @@ public: void set_3d_attributes(PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz, PN_stdfloat vx, PN_stdfloat vy, PN_stdfloat vz); void get_3d_attributes(PN_stdfloat *px, PN_stdfloat *py, PN_stdfloat *pz, PN_stdfloat *vx, PN_stdfloat *vy, PN_stdfloat *vz); + // Controls the direction of this sound emitter. + void set_3d_direction(LVector3 d); + LVector3 get_3d_direction() const; + void set_3d_min_distance(PN_stdfloat dist); PN_stdfloat get_3d_min_distance() const; @@ -99,6 +103,15 @@ public: void set_3d_drop_off_factor(PN_stdfloat factor); PN_stdfloat get_3d_drop_off_factor() const; + void set_3d_cone_inner_angle(PN_stdfloat angle); + PN_stdfloat get_3d_cone_inner_angle() const; + + void set_3d_cone_outer_angle(PN_stdfloat angle); + PN_stdfloat get_3d_cone_outer_angle() const; + + void set_3d_cone_outer_gain(PN_stdfloat gain); + PN_stdfloat get_3d_cone_outer_gain() const; + AudioSound::SoundStatus status() const; void finished(); @@ -154,6 +167,7 @@ private: ALfloat _location[3]; ALfloat _velocity[3]; + ALfloat _direction[3]; PN_stdfloat _min_dist; PN_stdfloat _max_dist; @@ -191,6 +205,14 @@ private: bool _active; bool _paused; + // these settings are used to define a directional sound source. The inner angle + // defines a cone wherein the sound can be heard with normal volume. _cone_outer_angle defines a second cone. + // Between the inner and the outer cone the volume is attenuated. + // _cone_outer_gain is a factor applied to the volume setting to define the volume in the zone outside of the outer cone. + PN_stdfloat _cone_inner_angle; + PN_stdfloat _cone_outer_angle; + PN_stdfloat _cone_outer_gain; + public: static TypeHandle get_class_type() { return _type_handle;