audiotraits: Add directional sound support to OpenAL (#1451)

This commit is contained in:
git2323 2023-02-07 13:10:36 +01:00 committed by rdb
parent c076d5ad08
commit e28697f670
4 changed files with 206 additions and 8 deletions

View File

@ -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.
*/

View File

@ -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);

View File

@ -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

View File

@ -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;