Merge pull request #10831 from kencooke/audio-hrtf-optimize

More HRTF optimizations
This commit is contained in:
Andrew Meadows 2017-06-28 14:17:00 -07:00 committed by GitHub
commit e9edf01a34
3 changed files with 68 additions and 17 deletions

View file

@ -497,13 +497,14 @@ float computeGain(const AvatarAudioStream& listeningNodeStream, const Positional
// avatar: apply fixed off-axis attenuation to make them quieter as they turn away
} else if (!isEcho && (streamToAdd.getType() == PositionalAudioStream::Microphone)) {
glm::vec3 rotatedListenerPosition = glm::inverse(streamToAdd.getOrientation()) * relativePosition;
float angleOfDelivery = glm::angle(glm::vec3(0.0f, 0.0f, -1.0f),
glm::normalize(rotatedListenerPosition));
// source directivity is based on angle of emission, in local coordinates
glm::vec3 direction = glm::normalize(rotatedListenerPosition);
float angleOfDelivery = fastAcosf(glm::clamp(-direction.z, -1.0f, 1.0f)); // UNIT_NEG_Z is "forward"
const float MAX_OFF_AXIS_ATTENUATION = 0.2f;
const float OFF_AXIS_ATTENUATION_STEP = (1 - MAX_OFF_AXIS_ATTENUATION) / 2.0f;
float offAxisCoefficient = MAX_OFF_AXIS_ATTENUATION +
(angleOfDelivery * (OFF_AXIS_ATTENUATION_STEP / PI_OVER_TWO));
float offAxisCoefficient = MAX_OFF_AXIS_ATTENUATION + (angleOfDelivery * (OFF_AXIS_ATTENUATION_STEP / PI_OVER_TWO));
gain *= offAxisCoefficient;
}
@ -545,7 +546,6 @@ float computeAzimuth(const AvatarAudioStream& listeningNodeStream, const Positio
const glm::vec3& relativePosition) {
glm::quat inverseOrientation = glm::inverse(listeningNodeStream.getOrientation());
// Compute sample delay for the two ears to create phase panning
glm::vec3 rotatedSourcePosition = inverseOrientation * relativePosition;
// project the rotated source position vector onto the XZ plane
@ -553,11 +553,16 @@ float computeAzimuth(const AvatarAudioStream& listeningNodeStream, const Positio
const float SOURCE_DISTANCE_THRESHOLD = 1e-30f;
if (glm::length2(rotatedSourcePosition) > SOURCE_DISTANCE_THRESHOLD) {
float rotatedSourcePositionLength2 = glm::length2(rotatedSourcePosition);
if (rotatedSourcePositionLength2 > SOURCE_DISTANCE_THRESHOLD) {
// produce an oriented angle about the y-axis
return glm::orientedAngle(glm::vec3(0.0f, 0.0f, -1.0f), glm::normalize(rotatedSourcePosition), glm::vec3(0.0f, -1.0f, 0.0f));
} else {
// there is no distance between listener and source - return no azimuth
return 0;
glm::vec3 direction = rotatedSourcePosition * (1.0f / fastSqrtf(rotatedSourcePositionLength2));
float angle = fastAcosf(glm::clamp(-direction.z, -1.0f, 1.0f)); // UNIT_NEG_Z is "forward"
return (direction.x < 0.0f) ? -angle : angle;
} else {
// no azimuth if they are in same spot
return 0.0f;
}
}

View file

@ -48,6 +48,7 @@
#include "AudioClientLogging.h"
#include "AudioLogging.h"
#include "AudioHelpers.h"
#include "AudioClient.h"
@ -1688,23 +1689,24 @@ int AudioClient::calculateNumberOfFrameSamples(int numBytes) const {
}
float AudioClient::azimuthForSource(const glm::vec3& relativePosition) {
// copied from AudioMixer, more or less
glm::quat inverseOrientation = glm::inverse(_orientationGetter());
// compute sample delay for the 2 ears to create phase panning
glm::vec3 rotatedSourcePosition = inverseOrientation * relativePosition;
// project the rotated source position vector onto x-y plane
// project the rotated source position vector onto the XZ plane
rotatedSourcePosition.y = 0.0f;
static const float SOURCE_DISTANCE_THRESHOLD = 1e-30f;
if (glm::length2(rotatedSourcePosition) > SOURCE_DISTANCE_THRESHOLD) {
float rotatedSourcePositionLength2 = glm::length2(rotatedSourcePosition);
if (rotatedSourcePositionLength2 > SOURCE_DISTANCE_THRESHOLD) {
// produce an oriented angle about the y-axis
return glm::orientedAngle(glm::vec3(0.0f, 0.0f, -1.0f), glm::normalize(rotatedSourcePosition), glm::vec3(0.0f, -1.0f, 0.0f));
} else {
glm::vec3 direction = rotatedSourcePosition * (1.0f / fastSqrtf(rotatedSourcePositionLength2));
float angle = fastAcosf(glm::clamp(-direction.z, -1.0f, 1.0f)); // UNIT_NEG_Z is "forward"
return (direction.x < 0.0f) ? -angle : angle;
} else {
// no azimuth if they are in same spot
return 0.0f;
}

View file

@ -14,6 +14,8 @@
#include <stdint.h>
#include <NumericalConstants.h>
const int IEEE754_MANT_BITS = 23;
const int IEEE754_EXPN_BIAS = 127;
@ -66,6 +68,48 @@ static inline float fastExp2f(float x) {
return x * xi.f;
}
//
// on x86 architecture, assume that SSE2 is present
//
#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__x86_64__)
#include <xmmintrin.h>
// inline sqrtss, without requiring /fp:fast
static inline float fastSqrtf(float x) {
return _mm_cvtss_f32(_mm_sqrt_ss(_mm_set_ss(x)));
}
#else
static inline float fastSqrtf(float x) {
return sqrtf(x);
}
#endif
//
// for -1 <= x <= 1, returns acos(x)
// otherwise, returns NaN
//
// abs |error| < 7e-5, smooth
//
static inline float fastAcosf(float x) {
union { float f; int32_t i; } xi = { x };
int32_t sign = xi.i & 0x80000000;
xi.i ^= sign; // fabs(x)
// compute sqrt(1-x) in parallel
float r = fastSqrtf(1.0f - xi.f);
// polynomial for acos(x)/sqrt(1-x) over x=[0,1]
xi.f = ((-0.0198439236f * xi.f + 0.0762021306f) * xi.f + -0.212940971f) * xi.f + 1.57079633f;
xi.f *= r;
return (sign ? PI - xi.f : xi.f);
}
//
// Quantize a non-negative gain value to the nearest 0.5dB, and pack to a byte.
//