mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 09:57:26 +02:00
Restore legacy attenuation behavior for system sounds and scripts that do not set position.
JS detects when "position" was not set by the script. C++ explicitly sets .positionSet=false when not set (for system sounds). Local rendering uses a direct mix (no attenuation/HRTF) when not set.
This commit is contained in:
parent
fdd86876cb
commit
fa08e42da6
8 changed files with 58 additions and 25 deletions
|
@ -4030,7 +4030,9 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
||||||
if (!isShifted && !isMeta && !isOption && !event->isAutoRepeat()) {
|
if (!isShifted && !isMeta && !isOption && !event->isAutoRepeat()) {
|
||||||
AudioInjectorOptions options;
|
AudioInjectorOptions options;
|
||||||
options.localOnly = true;
|
options.localOnly = true;
|
||||||
|
options.positionSet = false; // system sound
|
||||||
options.stereo = true;
|
options.stereo = true;
|
||||||
|
|
||||||
Setting::Handle<bool> notificationSounds{ MenuOption::NotificationSounds, true };
|
Setting::Handle<bool> notificationSounds{ MenuOption::NotificationSounds, true };
|
||||||
Setting::Handle<bool> notificationSoundSnapshot{ MenuOption::NotificationSoundsSnapshot, true };
|
Setting::Handle<bool> notificationSoundSnapshot{ MenuOption::NotificationSoundsSnapshot, true };
|
||||||
if (notificationSounds.get() && notificationSoundSnapshot.get()) {
|
if (notificationSounds.get() && notificationSoundSnapshot.get()) {
|
||||||
|
|
|
@ -1310,10 +1310,17 @@ bool AudioClient::mixLocalAudioInjectors(float* mixBuffer) {
|
||||||
memset(_localScratchBuffer, 0, bytesToRead);
|
memset(_localScratchBuffer, 0, bytesToRead);
|
||||||
if (0 < injectorBuffer->readData((char*)_localScratchBuffer, bytesToRead)) {
|
if (0 < injectorBuffer->readData((char*)_localScratchBuffer, bytesToRead)) {
|
||||||
|
|
||||||
|
float gain = injector->getVolume();
|
||||||
|
|
||||||
if (injector->isAmbisonic()) {
|
if (injector->isAmbisonic()) {
|
||||||
|
|
||||||
// no distance attenuation
|
if (injector->isPositionSet()) {
|
||||||
float gain = injector->getVolume();
|
|
||||||
|
// distance attenuation
|
||||||
|
glm::vec3 relativePosition = injector->getPosition() - _positionGetter();
|
||||||
|
float distance = glm::max(glm::length(relativePosition), EPSILON);
|
||||||
|
gain = gainForSource(distance, gain);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Calculate the soundfield orientation relative to the listener.
|
// Calculate the soundfield orientation relative to the listener.
|
||||||
|
@ -1327,33 +1334,49 @@ bool AudioClient::mixLocalAudioInjectors(float* mixBuffer) {
|
||||||
float qy = -relativeOrientation.x;
|
float qy = -relativeOrientation.x;
|
||||||
float qz = relativeOrientation.y;
|
float qz = relativeOrientation.y;
|
||||||
|
|
||||||
// Ambisonic gets spatialized into mixBuffer
|
// spatialize into mixBuffer
|
||||||
injector->getLocalFOA().render(_localScratchBuffer, mixBuffer, HRTF_DATASET_INDEX,
|
injector->getLocalFOA().render(_localScratchBuffer, mixBuffer, HRTF_DATASET_INDEX,
|
||||||
qw, qx, qy, qz, gain, AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL);
|
qw, qx, qy, qz, gain, AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL);
|
||||||
|
|
||||||
} else if (injector->isStereo()) {
|
} else if (injector->isStereo()) {
|
||||||
|
|
||||||
// calculate distance, gain
|
if (injector->isPositionSet()) {
|
||||||
glm::vec3 relativePosition = injector->getPosition() - _positionGetter();
|
|
||||||
float distance = glm::max(glm::length(relativePosition), EPSILON);
|
|
||||||
float gain = gainForSource(distance, injector->getVolume());
|
|
||||||
|
|
||||||
// stereo gets directly mixed into mixBuffer
|
// distance attenuation
|
||||||
for (int i = 0; i < AudioConstants::NETWORK_FRAME_SAMPLES_STEREO; i++) {
|
glm::vec3 relativePosition = injector->getPosition() - _positionGetter();
|
||||||
mixBuffer[i] += convertToFloat(_localScratchBuffer[i]) * gain;
|
float distance = glm::max(glm::length(relativePosition), EPSILON);
|
||||||
|
gain = gainForSource(distance, gain);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
// direct mix into mixBuffer
|
||||||
|
for (int i = 0; i < AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL; i++) {
|
||||||
|
mixBuffer[2*i+0] += convertToFloat(_localScratchBuffer[2*i+0]) * gain;
|
||||||
|
mixBuffer[2*i+1] += convertToFloat(_localScratchBuffer[2*i+1]) * gain;
|
||||||
|
}
|
||||||
|
|
||||||
// calculate distance, gain and azimuth for hrtf
|
} else { // injector is mono
|
||||||
glm::vec3 relativePosition = injector->getPosition() - _positionGetter();
|
|
||||||
float distance = glm::max(glm::length(relativePosition), EPSILON);
|
|
||||||
float gain = gainForSource(distance, injector->getVolume());
|
|
||||||
float azimuth = azimuthForSource(relativePosition);
|
|
||||||
|
|
||||||
// mono gets spatialized into mixBuffer
|
if (injector->isPositionSet()) {
|
||||||
injector->getLocalHRTF().render(_localScratchBuffer, mixBuffer, HRTF_DATASET_INDEX,
|
|
||||||
azimuth, distance, gain, AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL);
|
// distance attenuation
|
||||||
|
glm::vec3 relativePosition = injector->getPosition() - _positionGetter();
|
||||||
|
float distance = glm::max(glm::length(relativePosition), EPSILON);
|
||||||
|
gain = gainForSource(distance, gain);
|
||||||
|
|
||||||
|
float azimuth = azimuthForSource(relativePosition);
|
||||||
|
|
||||||
|
// spatialize into mixBuffer
|
||||||
|
injector->getLocalHRTF().render(_localScratchBuffer, mixBuffer, HRTF_DATASET_INDEX,
|
||||||
|
azimuth, distance, gain, AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// direct mix into mixBuffer
|
||||||
|
for (int i = 0; i < AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL; i++) {
|
||||||
|
float sample = convertToFloat(_localScratchBuffer[i]) * gain;
|
||||||
|
mixBuffer[2*i+0] += sample;
|
||||||
|
mixBuffer[2*i+1] += sample;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -67,6 +67,7 @@ public:
|
||||||
|
|
||||||
bool isLocalOnly() const { return _options.localOnly; }
|
bool isLocalOnly() const { return _options.localOnly; }
|
||||||
float getVolume() const { return _options.volume; }
|
float getVolume() const { return _options.volume; }
|
||||||
|
bool isPositionSet() const { return _options.positionSet; }
|
||||||
glm::vec3 getPosition() const { return _options.position; }
|
glm::vec3 getPosition() const { return _options.position; }
|
||||||
glm::quat getOrientation() const { return _options.orientation; }
|
glm::quat getOrientation() const { return _options.orientation; }
|
||||||
bool isStereo() const { return _options.stereo; }
|
bool isStereo() const { return _options.stereo; }
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
AudioInjectorOptions::AudioInjectorOptions() :
|
AudioInjectorOptions::AudioInjectorOptions() :
|
||||||
position(0.0f, 0.0f, 0.0f),
|
position(0.0f, 0.0f, 0.0f),
|
||||||
|
positionSet(true), // default to legacy behavior
|
||||||
volume(1.0f),
|
volume(1.0f),
|
||||||
loop(false),
|
loop(false),
|
||||||
orientation(glm::vec3(0.0f, 0.0f, 0.0f)),
|
orientation(glm::vec3(0.0f, 0.0f, 0.0f)),
|
||||||
|
@ -29,12 +30,12 @@ AudioInjectorOptions::AudioInjectorOptions() :
|
||||||
secondOffset(0.0f),
|
secondOffset(0.0f),
|
||||||
pitch(1.0f)
|
pitch(1.0f)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QScriptValue injectorOptionsToScriptValue(QScriptEngine* engine, const AudioInjectorOptions& injectorOptions) {
|
QScriptValue injectorOptionsToScriptValue(QScriptEngine* engine, const AudioInjectorOptions& injectorOptions) {
|
||||||
QScriptValue obj = engine->newObject();
|
QScriptValue obj = engine->newObject();
|
||||||
obj.setProperty("position", vec3ToScriptValue(engine, injectorOptions.position));
|
obj.setProperty("position", vec3ToScriptValue(engine, injectorOptions.position));
|
||||||
|
obj.setProperty("positionSet", injectorOptions.positionSet);
|
||||||
obj.setProperty("volume", injectorOptions.volume);
|
obj.setProperty("volume", injectorOptions.volume);
|
||||||
obj.setProperty("loop", injectorOptions.loop);
|
obj.setProperty("loop", injectorOptions.loop);
|
||||||
obj.setProperty("orientation", quatToScriptValue(engine, injectorOptions.orientation));
|
obj.setProperty("orientation", quatToScriptValue(engine, injectorOptions.orientation));
|
||||||
|
@ -68,12 +69,18 @@ void injectorOptionsFromScriptValue(const QScriptValue& object, AudioInjectorOpt
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (injectorOptions.positionSet == false) {
|
||||||
|
qWarning() << "Audio injector options: injectorOptionsFromScriptValue() called more than once?";
|
||||||
|
}
|
||||||
|
injectorOptions.positionSet = false;
|
||||||
|
|
||||||
QScriptValueIterator it(object);
|
QScriptValueIterator it(object);
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
it.next();
|
it.next();
|
||||||
|
|
||||||
if (it.name() == "position") {
|
if (it.name() == "position") {
|
||||||
vec3FromScriptValue(object.property("position"), injectorOptions.position);
|
vec3FromScriptValue(object.property("position"), injectorOptions.position);
|
||||||
|
injectorOptions.positionSet = true;
|
||||||
} else if (it.name() == "orientation") {
|
} else if (it.name() == "orientation") {
|
||||||
quatFromScriptValue(object.property("orientation"), injectorOptions.orientation);
|
quatFromScriptValue(object.property("orientation"), injectorOptions.orientation);
|
||||||
} else if (it.name() == "volume") {
|
} else if (it.name() == "volume") {
|
||||||
|
|
|
@ -21,6 +21,7 @@ class AudioInjectorOptions {
|
||||||
public:
|
public:
|
||||||
AudioInjectorOptions();
|
AudioInjectorOptions();
|
||||||
glm::vec3 position;
|
glm::vec3 position;
|
||||||
|
bool positionSet;
|
||||||
float volume;
|
float volume;
|
||||||
bool loop;
|
bool loop;
|
||||||
glm::quat orientation;
|
glm::quat orientation;
|
||||||
|
|
|
@ -38,10 +38,10 @@ void AudioScriptingInterface::setLocalAudioInterface(AbstractAudioInterface* aud
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptAudioInjector* AudioScriptingInterface::playSystemSound(SharedSoundPointer sound, const QVector3D& position) {
|
ScriptAudioInjector* AudioScriptingInterface::playSystemSound(SharedSoundPointer sound) {
|
||||||
AudioInjectorOptions options;
|
AudioInjectorOptions options;
|
||||||
options.position = glm::vec3(position.x(), position.y(), position.z());
|
|
||||||
options.localOnly = true;
|
options.localOnly = true;
|
||||||
|
options.positionSet = false; // system sound
|
||||||
return playSound(sound, options);
|
return playSound(sound, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -102,11 +102,9 @@ protected:
|
||||||
* @function Audio.playSystemSound
|
* @function Audio.playSystemSound
|
||||||
* @param {SoundObject} sound - The content of an audio file, loaded using {@link SoundCache.getSound}. See
|
* @param {SoundObject} sound - The content of an audio file, loaded using {@link SoundCache.getSound}. See
|
||||||
* {@link SoundObject} for supported formats.
|
* {@link SoundObject} for supported formats.
|
||||||
* @param {Vec3} position - The position in the domain to play the sound.
|
|
||||||
* @returns {AudioInjector} The audio injector that plays the audio file.
|
* @returns {AudioInjector} The audio injector that plays the audio file.
|
||||||
*/
|
*/
|
||||||
// FIXME: there is no way to play a positionless sound
|
Q_INVOKABLE ScriptAudioInjector* playSystemSound(SharedSoundPointer sound);
|
||||||
Q_INVOKABLE ScriptAudioInjector* playSystemSound(SharedSoundPointer sound, const QVector3D& position);
|
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Set whether or not the audio input should be used in stereo. If the audio input does not support stereo then setting a
|
* Set whether or not the audio input should be used in stereo. If the audio input does not support stereo then setting a
|
||||||
|
|
|
@ -210,6 +210,7 @@ void TabletScriptingInterface::playSound(TabletAudioEvents aEvent) {
|
||||||
options.stereo = sound->isStereo();
|
options.stereo = sound->isStereo();
|
||||||
options.ambisonic = sound->isAmbisonic();
|
options.ambisonic = sound->isAmbisonic();
|
||||||
options.localOnly = true;
|
options.localOnly = true;
|
||||||
|
options.positionSet = false; // system sound
|
||||||
|
|
||||||
AudioInjectorPointer injector = AudioInjector::playSoundAndDelete(sound, options);
|
AudioInjectorPointer injector = AudioInjector::playSoundAndDelete(sound, options);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue