mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-07-23 13:44:36 +02:00
rework audio-mixer to use orientations sent by clients
This commit is contained in:
parent
0f70c9c06b
commit
cd79339670
3 changed files with 41 additions and 70 deletions
|
@ -18,6 +18,7 @@
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
#include <glm/gtx/norm.hpp>
|
#include <glm/gtx/norm.hpp>
|
||||||
|
#include <glm/gtx/vector_angle.hpp>
|
||||||
#include <AgentList.h>
|
#include <AgentList.h>
|
||||||
#include <Agent.h>
|
#include <Agent.h>
|
||||||
#include <AgentTypes.h>
|
#include <AgentTypes.h>
|
||||||
|
@ -147,14 +148,16 @@ int main(int argc, const char* argv[]) {
|
||||||
float weakChannelAmplitudeRatio = 1.0f;
|
float weakChannelAmplitudeRatio = 1.0f;
|
||||||
|
|
||||||
if (otherAgent != agent) {
|
if (otherAgent != agent) {
|
||||||
glm::vec3 agentPosition = agentRingBuffer->getPosition();
|
glm::vec3 listenerPosition = agentRingBuffer->getPosition();
|
||||||
glm::vec3 otherAgentPosition = otherAgentBuffer->getPosition();
|
glm::vec3 relativePosition = otherAgentBuffer->getPosition() - agentRingBuffer->getPosition();
|
||||||
|
glm::vec3 rotatedSourcePosition = glm::inverse(agentRingBuffer->getOrientation())
|
||||||
float distanceSquareToSource = glm::distance2(agentPosition, otherAgentPosition);
|
* relativePosition;
|
||||||
|
|
||||||
|
float distanceSquareToSource = glm::dot(relativePosition, relativePosition);
|
||||||
|
|
||||||
float distanceCoefficient = 1.0f;
|
float distanceCoefficient = 1.0f;
|
||||||
float offAxisCoefficient = 1.0f;
|
float offAxisCoefficient = 1.0f;
|
||||||
|
|
||||||
if (otherAgentBuffer->getRadius() == 0
|
if (otherAgentBuffer->getRadius() == 0
|
||||||
|| (distanceSquareToSource > (otherAgentBuffer->getRadius()
|
|| (distanceSquareToSource > (otherAgentBuffer->getRadius()
|
||||||
* otherAgentBuffer->getRadius()))) {
|
* otherAgentBuffer->getRadius()))) {
|
||||||
|
@ -167,17 +170,17 @@ int main(int argc, const char* argv[]) {
|
||||||
// multiply the normalized vector between the center of the sphere
|
// multiply the normalized vector between the center of the sphere
|
||||||
// and the position of the source by the radius to get the
|
// and the position of the source by the radius to get the
|
||||||
// closest point on the boundary of the sphere to the source
|
// closest point on the boundary of the sphere to the source
|
||||||
glm::vec3 difference = agentPosition - otherAgentPosition;
|
|
||||||
glm::vec3 closestPoint = glm::normalize(difference) * otherAgentBuffer->getRadius();
|
|
||||||
|
|
||||||
|
glm::vec3 closestPoint = glm::normalize(relativePosition) * otherAgentBuffer->getRadius();
|
||||||
|
|
||||||
// for the other calculations the agent position is the closest point on the sphere
|
// for the other calculations the agent position is the closest point on the sphere
|
||||||
otherAgentPosition = closestPoint;
|
rotatedSourcePosition = closestPoint;
|
||||||
|
|
||||||
// ovveride the distance to the agent with the distance to the point on the
|
// ovveride the distance to the agent with the distance to the point on the
|
||||||
// boundary of the sphere
|
// boundary of the sphere
|
||||||
distanceSquareToSource = glm::distance2(agentPosition, closestPoint);
|
distanceSquareToSource = glm::distance2(listenerPosition, closestPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
const float DISTANCE_SCALE = 2.5f;
|
const float DISTANCE_SCALE = 2.5f;
|
||||||
const float GEOMETRIC_AMPLITUDE_SCALAR = 0.3f;
|
const float GEOMETRIC_AMPLITUDE_SCALAR = 0.3f;
|
||||||
const float DISTANCE_LOG_BASE = 2.5f;
|
const float DISTANCE_LOG_BASE = 2.5f;
|
||||||
|
@ -188,67 +191,40 @@ int main(int argc, const char* argv[]) {
|
||||||
DISTANCE_SCALE_LOG +
|
DISTANCE_SCALE_LOG +
|
||||||
(logf(distanceSquareToSource) / logf(DISTANCE_LOG_BASE)) - 1);
|
(logf(distanceSquareToSource) / logf(DISTANCE_LOG_BASE)) - 1);
|
||||||
distanceCoefficient = std::min(1.0f, distanceCoefficient);
|
distanceCoefficient = std::min(1.0f, distanceCoefficient);
|
||||||
|
|
||||||
// off-axis attenuation and spatialization of audio
|
// off-axis attenuation and spatialization of audio
|
||||||
// not performed if listener is inside spherical injector
|
// not performed if listener is inside spherical injector
|
||||||
|
|
||||||
// get the angle from the right-angle triangle
|
// calculate the angle from the source to the listener
|
||||||
float triangleAngle = atan2f(fabsf(agentPosition.z - otherAgentPosition.z),
|
bearingRelativeAngleToSource = glm::orientedAngle(glm::vec3(0.0f, 0.0f, -1.0f),
|
||||||
fabsf(agentPosition.x - otherAgentPosition.x)) * (180 / M_PI);
|
glm::normalize(rotatedSourcePosition),
|
||||||
float absoluteAngleToSource = 0;
|
glm::vec3(0.0f, 1.0f, 0.0f));
|
||||||
|
|
||||||
// find the angle we need for calculation based on the orientation of the triangle
|
// calculate the angle delivery
|
||||||
if (otherAgentPosition.x > agentPosition.x) {
|
glm::vec3 rotatedListenerPosition = glm::inverse(otherAgentBuffer->getOrientation())
|
||||||
if (otherAgentPosition.z > agentPosition.z) {
|
* relativePosition;
|
||||||
absoluteAngleToSource = -90 + triangleAngle;
|
float angleOfDelivery = glm::angle(glm::vec3(0.0f, 0.0f, 1.0f),
|
||||||
} else {
|
glm::normalize(rotatedListenerPosition));
|
||||||
absoluteAngleToSource = -90 - triangleAngle;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (otherAgentPosition.z > agentPosition.z) {
|
|
||||||
absoluteAngleToSource = 90 - triangleAngle;
|
|
||||||
} else {
|
|
||||||
absoluteAngleToSource = 90 + triangleAngle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bearingRelativeAngleToSource = absoluteAngleToSource - agentRingBuffer->getBearing();
|
|
||||||
|
|
||||||
if (bearingRelativeAngleToSource > 180) {
|
|
||||||
bearingRelativeAngleToSource -= 360;
|
|
||||||
} else if (bearingRelativeAngleToSource < -180) {
|
|
||||||
bearingRelativeAngleToSource += 360;
|
|
||||||
}
|
|
||||||
|
|
||||||
float angleOfDelivery = absoluteAngleToSource - otherAgentBuffer->getBearing();
|
|
||||||
|
|
||||||
if (angleOfDelivery > 180) {
|
|
||||||
angleOfDelivery -= 360;
|
|
||||||
} else if (angleOfDelivery < -180) {
|
|
||||||
angleOfDelivery += 360;
|
|
||||||
}
|
|
||||||
|
|
||||||
offAxisCoefficient = MAX_OFF_AXIS_ATTENUATION
|
offAxisCoefficient = MAX_OFF_AXIS_ATTENUATION
|
||||||
+ (OFF_AXIS_ATTENUATION_FORMULA_STEP * (fabsf(angleOfDelivery) / 90.0f));
|
+ (OFF_AXIS_ATTENUATION_FORMULA_STEP * (fabsf(angleOfDelivery) / 90.0f));
|
||||||
|
|
||||||
bearingRelativeAngleToSource *= (M_PI / 180);
|
float sinRatio = fabsf(sinf(glm::radians(bearingRelativeAngleToSource)));
|
||||||
|
numSamplesDelay = PHASE_DELAY_AT_90 * sinRatio;
|
||||||
|
weakChannelAmplitudeRatio = 1 - (PHASE_AMPLITUDE_RATIO_AT_90 * sinRatio);
|
||||||
}
|
}
|
||||||
|
|
||||||
attenuationCoefficient = distanceCoefficient
|
attenuationCoefficient = distanceCoefficient
|
||||||
* otherAgentBuffer->getAttenuationRatio()
|
* otherAgentBuffer->getAttenuationRatio()
|
||||||
* offAxisCoefficient;
|
* offAxisCoefficient;
|
||||||
|
|
||||||
float sinRatio = fabsf(sinf(bearingRelativeAngleToSource));
|
|
||||||
numSamplesDelay = PHASE_DELAY_AT_90 * sinRatio;
|
|
||||||
weakChannelAmplitudeRatio = 1 - (PHASE_AMPLITUDE_RATIO_AT_90 * sinRatio);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t* goodChannel = bearingRelativeAngleToSource > 0.0f
|
int16_t* goodChannel = bearingRelativeAngleToSource > 0.0f
|
||||||
? clientSamples + BUFFER_LENGTH_SAMPLES_PER_CHANNEL
|
|
||||||
: clientSamples;
|
|
||||||
int16_t* delayedChannel = bearingRelativeAngleToSource > 0.0f
|
|
||||||
? clientSamples
|
? clientSamples
|
||||||
: clientSamples + BUFFER_LENGTH_SAMPLES_PER_CHANNEL;
|
: clientSamples + BUFFER_LENGTH_SAMPLES_PER_CHANNEL;
|
||||||
|
int16_t* delayedChannel = bearingRelativeAngleToSource > 0.0f
|
||||||
|
? clientSamples + BUFFER_LENGTH_SAMPLES_PER_CHANNEL
|
||||||
|
: clientSamples;
|
||||||
|
|
||||||
int16_t* delaySamplePointer = otherAgentBuffer->getNextOutput() == otherAgentBuffer->getBuffer()
|
int16_t* delaySamplePointer = otherAgentBuffer->getNextOutput() == otherAgentBuffer->getBuffer()
|
||||||
? otherAgentBuffer->getBuffer() + RING_BUFFER_SAMPLES - numSamplesDelay
|
? otherAgentBuffer->getBuffer() + RING_BUFFER_SAMPLES - numSamplesDelay
|
||||||
|
@ -307,7 +283,7 @@ int main(int argc, const char* argv[]) {
|
||||||
|
|
||||||
agentList->updateAgentWithData(agentAddress, packetData, receivedBytes);
|
agentList->updateAgentWithData(agentAddress, packetData, receivedBytes);
|
||||||
|
|
||||||
if (std::isnan(((AudioRingBuffer *)avatarAgent->getLinkedData())->getBearing())) {
|
if (std::isnan(((AudioRingBuffer *)avatarAgent->getLinkedData())->getOrientation().x)) {
|
||||||
// kill off this agent - temporary solution to mixer crash on mac sleep
|
// kill off this agent - temporary solution to mixer crash on mac sleep
|
||||||
avatarAgent->setAlive(false);
|
avatarAgent->setAlive(false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,23 +65,16 @@ int AudioRingBuffer::parseData(unsigned char* sourceBuffer, int numBytes) {
|
||||||
unsigned int attenuationByte = *(dataBuffer++);
|
unsigned int attenuationByte = *(dataBuffer++);
|
||||||
_attenuationRatio = attenuationByte / 255.0f;
|
_attenuationRatio = attenuationByte / 255.0f;
|
||||||
|
|
||||||
memcpy(&_bearing, dataBuffer, sizeof(float));
|
memcpy(&_orientation, dataBuffer, sizeof(_orientation));
|
||||||
dataBuffer += sizeof(_bearing);
|
dataBuffer += sizeof(_orientation);
|
||||||
|
|
||||||
// if this agent sent us a NaN bearing then don't consider this good audio and bail
|
// if this agent sent us a NaN for first float in orientation then don't consider this good audio and bail
|
||||||
if (std::isnan(_bearing)) {
|
if (std::isnan(_orientation.x)) {
|
||||||
_endOfLastWrite = _nextOutput = _buffer;
|
_endOfLastWrite = _nextOutput = _buffer;
|
||||||
_started = false;
|
_started = false;
|
||||||
return 0;
|
return 0;
|
||||||
} else if (_bearing > 180 || _bearing < -180) {
|
|
||||||
// we were passed an invalid bearing because this agent wants loopback (pressed the H key)
|
|
||||||
_shouldLoopbackForAgent = true;
|
|
||||||
|
|
||||||
// correct the bearing
|
|
||||||
_bearing = _bearing > 0
|
|
||||||
? _bearing - AGENT_LOOPBACK_MODIFIER
|
|
||||||
: _bearing + AGENT_LOOPBACK_MODIFIER;
|
|
||||||
} else {
|
} else {
|
||||||
|
// currently no possiblity for loopback, need to add once quaternion audio is working again
|
||||||
_shouldLoopbackForAgent = false;
|
_shouldLoopbackForAgent = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtx/quaternion.hpp>
|
||||||
|
|
||||||
#include "AgentData.h"
|
#include "AgentData.h"
|
||||||
|
|
||||||
|
@ -44,8 +45,9 @@ public:
|
||||||
void setShouldBeAddedToMix(bool shouldBeAddedToMix) { _shouldBeAddedToMix = shouldBeAddedToMix; }
|
void setShouldBeAddedToMix(bool shouldBeAddedToMix) { _shouldBeAddedToMix = shouldBeAddedToMix; }
|
||||||
|
|
||||||
const glm::vec3& getPosition() const { return _position; }
|
const glm::vec3& getPosition() const { return _position; }
|
||||||
|
const glm::quat& getOrientation() const { return _orientation; }
|
||||||
float getAttenuationRatio() const { return _attenuationRatio; }
|
float getAttenuationRatio() const { return _attenuationRatio; }
|
||||||
float getBearing() const { return _bearing; }
|
|
||||||
bool shouldLoopbackForAgent() const { return _shouldLoopbackForAgent; }
|
bool shouldLoopbackForAgent() const { return _shouldLoopbackForAgent; }
|
||||||
const unsigned char* getStreamIdentifier() const { return _streamIdentifier; }
|
const unsigned char* getStreamIdentifier() const { return _streamIdentifier; }
|
||||||
|
|
||||||
|
@ -58,9 +60,9 @@ private:
|
||||||
int _ringBufferLengthSamples;
|
int _ringBufferLengthSamples;
|
||||||
int _bufferLengthSamples;
|
int _bufferLengthSamples;
|
||||||
glm::vec3 _position;
|
glm::vec3 _position;
|
||||||
|
glm::quat _orientation;
|
||||||
float _radius;
|
float _radius;
|
||||||
float _attenuationRatio;
|
float _attenuationRatio;
|
||||||
float _bearing;
|
|
||||||
int16_t* _nextOutput;
|
int16_t* _nextOutput;
|
||||||
int16_t* _endOfLastWrite;
|
int16_t* _endOfLastWrite;
|
||||||
int16_t* _buffer;
|
int16_t* _buffer;
|
||||||
|
|
Loading…
Reference in a new issue