From eaaeedab68f04da5af5323f1f1bfa88aebbb3b75 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 4 Jun 2013 11:24:07 -0700 Subject: [PATCH] refactor calculations for audio --- audio-mixer/src/main.cpp | 109 ++++++++++++++++++--------------------- injector/src/main.cpp | 2 +- 2 files changed, 50 insertions(+), 61 deletions(-) diff --git a/audio-mixer/src/main.cpp b/audio-mixer/src/main.cpp index d94a1d59d6..bc75ac5698 100644 --- a/audio-mixer/src/main.cpp +++ b/audio-mixer/src/main.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -55,7 +56,6 @@ const float BUFFER_SEND_INTERVAL_USECS = (BUFFER_LENGTH_SAMPLES_PER_CHANNEL / SA const long MAX_SAMPLE_VALUE = std::numeric_limits::max(); const long MIN_SAMPLE_VALUE = std::numeric_limits::min(); -const float DISTANCE_SCALE = 2.5f; const float PHASE_AMPLITUDE_RATIO_AT_90 = 0.5; 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++) { if (agent->getType() == AGENT_TYPE_AVATAR) { AudioRingBuffer* agentRingBuffer = (AudioRingBuffer*) agent->getLinkedData(); @@ -146,69 +142,60 @@ int main(int argc, const char* argv[]) { if (otherAgentBuffer->shouldBeAddedToMix()) { float bearingRelativeAngleToSource = 0.f; - float attenuationCoefficient = 1.f; + float attenuationCoefficient = 1.0f; int numSamplesDelay = 0; - float weakChannelAmplitudeRatio = 1.f; + float weakChannelAmplitudeRatio = 1.0f; if (otherAgent != agent) { glm::vec3 agentPosition = agentRingBuffer->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 - int lowAgentIndex = std::min(agent.getAgentIndex(), otherAgent.getAgentIndex()); - int highAgentIndex = std::max(agent.getAgentIndex(), otherAgent.getAgentIndex()); + float distanceCoefficient = 1.0f; + float offAxisCoefficient = 1.0f; - bool insideSphericalInjector = false; - - if (distanceCoefficients[lowAgentIndex][highAgentIndex] == 0) { - float distanceToAgent = glm::distance(agentPosition, otherAgentPosition); + if (otherAgentBuffer->getRadius() == 0 + || (distanceSquareToSource > (otherAgentBuffer->getRadius() + * otherAgentBuffer->getRadius()))) { + // this is either not a spherical source, or the listener is outside the sphere - float minCoefficient = 1.0f; - - if (otherAgentBuffer->getRadius() == 0 || distanceToAgent > otherAgentBuffer->getRadius()) { - // this is either not a spherical source, or the listener is outside the sphere + if (otherAgentBuffer->getRadius() > 0) { + // this is a spherical source - the distance used for the coefficient + // needs to be the closest point on the boundary to the source - if (otherAgentBuffer->getRadius() > 0) { - // this is a spherical source - the distance used for the coefficient - // needs to be the closest point on the boundary to the source - - // multiply the normalized vector between the center of the sphere - // 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); - } + // multiply the normalized vector between the center of the sphere + // 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(); - // calculate the distance coefficient using the distance to this agent - minCoefficient = std::min(1.0f, - powf(0.3, (logf(DISTANCE_SCALE * distanceToAgent) / - logf(2.5)) - 1)); - } else { - insideSphericalInjector = true; + // 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 + 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); - - distanceCoefficients[lowAgentIndex][highAgentIndex] = minCoefficient; - } - - if (!insideSphericalInjector) { - // off-axis attenuation and spatialization of audio is not performed - // if the listener is inside a spherical injector + // calculate the distance coefficient using the distance to this agent + distanceCoefficient = powf(GEOMETRIC_AMPLITUDE_SCALAR, + DISTANCE_SCALE_LOG + + (logf(distanceSquareToSource) / logf(DISTANCE_LOG_BASE)) - 1); + distanceCoefficient = std::min(1.0f, distanceCoefficient); + + // off-axis attenuation and spatialization of audio + // not performed if listener is inside spherical injector // get the angle from the right-angle triangle float triangleAngle = atan2f(fabsf(agentPosition.z - otherAgentPosition.z), fabsf(agentPosition.x - otherAgentPosition.x)) * (180 / M_PI); float absoluteAngleToSource = 0; - bearingRelativeAngleToSource = 0; // find the angle we need for calculation based on the orientation of the triangle 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(); if (bearingRelativeAngleToSource > 180) { @@ -241,19 +230,19 @@ int main(int argc, const char* argv[]) { angleOfDelivery += 360; } - float offAxisCoefficient = MAX_OFF_AXIS_ATTENUATION + - (OFF_AXIS_ATTENUATION_FORMULA_STEP * (fabsf(angleOfDelivery) / 90.0f)); - - attenuationCoefficient = distanceCoefficients[lowAgentIndex][highAgentIndex] - * otherAgentBuffer->getAttenuationRatio() - * offAxisCoefficient; + offAxisCoefficient = MAX_OFF_AXIS_ATTENUATION + + (OFF_AXIS_ATTENUATION_FORMULA_STEP * (fabsf(angleOfDelivery) / 90.0f)); 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 diff --git a/injector/src/main.cpp b/injector/src/main.cpp index 18fa1f27df..8d4ec11859 100644 --- a/injector/src/main.cpp +++ b/injector/src/main.cpp @@ -32,7 +32,7 @@ bool loopAudio = true; float sleepIntervalMin = 1.00; float sleepIntervalMax = 2.00; 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}; unsigned char volume = DEFAULT_INJECTOR_VOLUME; float triggerDistance = 0.0f;