mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 19:59:28 +02:00
refactor calculations for audio
This commit is contained in:
parent
3f7fbb5c1e
commit
eaaeedab68
2 changed files with 50 additions and 61 deletions
|
@ -17,6 +17,7 @@
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
|
#include <glm/gtx/norm.hpp>
|
||||||
#include <AgentList.h>
|
#include <AgentList.h>
|
||||||
#include <Agent.h>
|
#include <Agent.h>
|
||||||
#include <AgentTypes.h>
|
#include <AgentTypes.h>
|
||||||
|
@ -55,7 +56,6 @@ const float BUFFER_SEND_INTERVAL_USECS = (BUFFER_LENGTH_SAMPLES_PER_CHANNEL / SA
|
||||||
const long MAX_SAMPLE_VALUE = std::numeric_limits<int16_t>::max();
|
const long MAX_SAMPLE_VALUE = std::numeric_limits<int16_t>::max();
|
||||||
const long MIN_SAMPLE_VALUE = std::numeric_limits<int16_t>::min();
|
const long MIN_SAMPLE_VALUE = std::numeric_limits<int16_t>::min();
|
||||||
|
|
||||||
const float DISTANCE_SCALE = 2.5f;
|
|
||||||
const float PHASE_AMPLITUDE_RATIO_AT_90 = 0.5;
|
const float PHASE_AMPLITUDE_RATIO_AT_90 = 0.5;
|
||||||
const int PHASE_DELAY_AT_90 = 20;
|
const int PHASE_DELAY_AT_90 = 20;
|
||||||
|
|
||||||
|
@ -128,10 +128,6 @@ int main(int argc, const char* argv[]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int numAgents = agentList->size();
|
|
||||||
float distanceCoefficients[numAgents][numAgents];
|
|
||||||
memset(distanceCoefficients, 0, sizeof(distanceCoefficients));
|
|
||||||
|
|
||||||
for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
|
for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
|
||||||
if (agent->getType() == AGENT_TYPE_AVATAR) {
|
if (agent->getType() == AGENT_TYPE_AVATAR) {
|
||||||
AudioRingBuffer* agentRingBuffer = (AudioRingBuffer*) agent->getLinkedData();
|
AudioRingBuffer* agentRingBuffer = (AudioRingBuffer*) agent->getLinkedData();
|
||||||
|
@ -146,69 +142,60 @@ int main(int argc, const char* argv[]) {
|
||||||
if (otherAgentBuffer->shouldBeAddedToMix()) {
|
if (otherAgentBuffer->shouldBeAddedToMix()) {
|
||||||
|
|
||||||
float bearingRelativeAngleToSource = 0.f;
|
float bearingRelativeAngleToSource = 0.f;
|
||||||
float attenuationCoefficient = 1.f;
|
float attenuationCoefficient = 1.0f;
|
||||||
int numSamplesDelay = 0;
|
int numSamplesDelay = 0;
|
||||||
float weakChannelAmplitudeRatio = 1.f;
|
float weakChannelAmplitudeRatio = 1.0f;
|
||||||
|
|
||||||
if (otherAgent != agent) {
|
if (otherAgent != agent) {
|
||||||
glm::vec3 agentPosition = agentRingBuffer->getPosition();
|
glm::vec3 agentPosition = agentRingBuffer->getPosition();
|
||||||
glm::vec3 otherAgentPosition = otherAgentBuffer->getPosition();
|
glm::vec3 otherAgentPosition = otherAgentBuffer->getPosition();
|
||||||
|
|
||||||
// calculate the distance to the other agent
|
float distanceSquareToSource = glm::distance2(agentPosition, otherAgentPosition);
|
||||||
|
|
||||||
// use the distance to the other agent to calculate the change in volume for this frame
|
float distanceCoefficient = 1.0f;
|
||||||
int lowAgentIndex = std::min(agent.getAgentIndex(), otherAgent.getAgentIndex());
|
float offAxisCoefficient = 1.0f;
|
||||||
int highAgentIndex = std::max(agent.getAgentIndex(), otherAgent.getAgentIndex());
|
|
||||||
|
|
||||||
bool insideSphericalInjector = false;
|
if (otherAgentBuffer->getRadius() == 0
|
||||||
|
|| (distanceSquareToSource > (otherAgentBuffer->getRadius()
|
||||||
if (distanceCoefficients[lowAgentIndex][highAgentIndex] == 0) {
|
* otherAgentBuffer->getRadius()))) {
|
||||||
float distanceToAgent = glm::distance(agentPosition, otherAgentPosition);
|
// this is either not a spherical source, or the listener is outside the sphere
|
||||||
|
|
||||||
float minCoefficient = 1.0f;
|
if (otherAgentBuffer->getRadius() > 0) {
|
||||||
|
// this is a spherical source - the distance used for the coefficient
|
||||||
if (otherAgentBuffer->getRadius() == 0 || distanceToAgent > otherAgentBuffer->getRadius()) {
|
// needs to be the closest point on the boundary to the source
|
||||||
// this is either not a spherical source, or the listener is outside the sphere
|
|
||||||
|
|
||||||
if (otherAgentBuffer->getRadius() > 0) {
|
// multiply the normalized vector between the center of the sphere
|
||||||
// this is a spherical source - the distance used for the coefficient
|
// and the position of the source by the radius to get the
|
||||||
// needs to be the closest point on the boundary to the source
|
// closest point on the boundary of the sphere to the source
|
||||||
|
glm::vec3 difference = agentPosition - otherAgentPosition;
|
||||||
// multiply the normalized vector between the center of the sphere
|
glm::vec3 closestPoint = glm::normalize(difference) * otherAgentBuffer->getRadius();
|
||||||
// and the position of the source by the radius to get the
|
|
||||||
// closest point on the boundary of the sphere to the source
|
|
||||||
glm::vec3 difference = agentPosition - otherAgentPosition;
|
|
||||||
glm::vec3 closestPoint = glm::normalize(difference) * otherAgentBuffer->getRadius();
|
|
||||||
|
|
||||||
// for the other calculations the agent position is the closest point on the sphere
|
|
||||||
otherAgentPosition = closestPoint;
|
|
||||||
|
|
||||||
// ovveride the distance to the agent with the distance to the point on the
|
|
||||||
// boundary of the sphere
|
|
||||||
distanceToAgent = glm::distance(agentPosition, closestPoint);
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculate the distance coefficient using the distance to this agent
|
// for the other calculations the agent position is the closest point on the sphere
|
||||||
minCoefficient = std::min(1.0f,
|
otherAgentPosition = closestPoint;
|
||||||
powf(0.3, (logf(DISTANCE_SCALE * distanceToAgent) /
|
|
||||||
logf(2.5)) - 1));
|
// ovveride the distance to the agent with the distance to the point on the
|
||||||
} else {
|
// boundary of the sphere
|
||||||
insideSphericalInjector = true;
|
distanceSquareToSource = glm::distance2(agentPosition, closestPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const float DISTANCE_SCALE = 2.5f;
|
||||||
|
const float GEOMETRIC_AMPLITUDE_SCALAR = 0.3f;
|
||||||
|
const float DISTANCE_LOG_BASE = 2.5f;
|
||||||
|
const float DISTANCE_SCALE_LOG = logf(DISTANCE_SCALE) / logf(DISTANCE_LOG_BASE);
|
||||||
|
|
||||||
|
// calculate the distance coefficient using the distance to this agent
|
||||||
distanceCoefficients[lowAgentIndex][highAgentIndex] = minCoefficient;
|
distanceCoefficient = powf(GEOMETRIC_AMPLITUDE_SCALAR,
|
||||||
}
|
DISTANCE_SCALE_LOG +
|
||||||
|
(logf(distanceSquareToSource) / logf(DISTANCE_LOG_BASE)) - 1);
|
||||||
if (!insideSphericalInjector) {
|
distanceCoefficient = std::min(1.0f, distanceCoefficient);
|
||||||
// off-axis attenuation and spatialization of audio is not performed
|
|
||||||
// if the listener is inside a spherical injector
|
// off-axis attenuation and spatialization of audio
|
||||||
|
// not performed if listener is inside spherical injector
|
||||||
|
|
||||||
// get the angle from the right-angle triangle
|
// get the angle from the right-angle triangle
|
||||||
float triangleAngle = atan2f(fabsf(agentPosition.z - otherAgentPosition.z),
|
float triangleAngle = atan2f(fabsf(agentPosition.z - otherAgentPosition.z),
|
||||||
fabsf(agentPosition.x - otherAgentPosition.x)) * (180 / M_PI);
|
fabsf(agentPosition.x - otherAgentPosition.x)) * (180 / M_PI);
|
||||||
float absoluteAngleToSource = 0;
|
float absoluteAngleToSource = 0;
|
||||||
bearingRelativeAngleToSource = 0;
|
|
||||||
|
|
||||||
// find the angle we need for calculation based on the orientation of the triangle
|
// find the angle we need for calculation based on the orientation of the triangle
|
||||||
if (otherAgentPosition.x > agentPosition.x) {
|
if (otherAgentPosition.x > agentPosition.x) {
|
||||||
|
@ -225,6 +212,8 @@ int main(int argc, const char* argv[]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("AAS: %f, AB: %f\n", absoluteAngleToSource, agentRingBuffer->getBearing());
|
||||||
|
|
||||||
bearingRelativeAngleToSource = absoluteAngleToSource - agentRingBuffer->getBearing();
|
bearingRelativeAngleToSource = absoluteAngleToSource - agentRingBuffer->getBearing();
|
||||||
|
|
||||||
if (bearingRelativeAngleToSource > 180) {
|
if (bearingRelativeAngleToSource > 180) {
|
||||||
|
@ -241,19 +230,19 @@ int main(int argc, const char* argv[]) {
|
||||||
angleOfDelivery += 360;
|
angleOfDelivery += 360;
|
||||||
}
|
}
|
||||||
|
|
||||||
float 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));
|
||||||
|
|
||||||
attenuationCoefficient = distanceCoefficients[lowAgentIndex][highAgentIndex]
|
|
||||||
* otherAgentBuffer->getAttenuationRatio()
|
|
||||||
* offAxisCoefficient;
|
|
||||||
|
|
||||||
bearingRelativeAngleToSource *= (M_PI / 180);
|
bearingRelativeAngleToSource *= (M_PI / 180);
|
||||||
|
|
||||||
float sinRatio = fabsf(sinf(bearingRelativeAngleToSource));
|
|
||||||
numSamplesDelay = PHASE_DELAY_AT_90 * sinRatio;
|
|
||||||
weakChannelAmplitudeRatio = 1 - (PHASE_AMPLITUDE_RATIO_AT_90 * sinRatio);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
attenuationCoefficient = distanceCoefficient
|
||||||
|
* otherAgentBuffer->getAttenuationRatio()
|
||||||
|
* 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
|
||||||
|
|
|
@ -32,7 +32,7 @@ bool loopAudio = true;
|
||||||
float sleepIntervalMin = 1.00;
|
float sleepIntervalMin = 1.00;
|
||||||
float sleepIntervalMax = 2.00;
|
float sleepIntervalMax = 2.00;
|
||||||
char *sourceAudioFile = NULL;
|
char *sourceAudioFile = NULL;
|
||||||
const char *allowedParameters = ":rb::t::c::a::f::d::s:";
|
const char *allowedParameters = ":sb::t::c::a::f::d::r:";
|
||||||
float floatArguments[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
float floatArguments[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||||
unsigned char volume = DEFAULT_INJECTOR_VOLUME;
|
unsigned char volume = DEFAULT_INJECTOR_VOLUME;
|
||||||
float triggerDistance = 0.0f;
|
float triggerDistance = 0.0f;
|
||||||
|
|
Loading…
Reference in a new issue