rework audio-mixer to use orientations sent by clients

This commit is contained in:
Stephen Birarda 2013-06-04 15:18:05 -07:00
parent 0f70c9c06b
commit cd79339670
3 changed files with 41 additions and 70 deletions

View file

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

View file

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

View file

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