From a92571bdeea3dafba76adb65cca10c60526d97f1 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 9 May 2013 11:45:59 -0700 Subject: [PATCH 1/2] initialize the _shouldLoopbackForAgent variable --- libraries/shared/src/AudioRingBuffer.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/libraries/shared/src/AudioRingBuffer.cpp b/libraries/shared/src/AudioRingBuffer.cpp index 5079582544..a399852950 100644 --- a/libraries/shared/src/AudioRingBuffer.cpp +++ b/libraries/shared/src/AudioRingBuffer.cpp @@ -9,15 +9,13 @@ #include #include "AudioRingBuffer.h" -AudioRingBuffer::AudioRingBuffer(int ringSamples, int bufferSamples) { - ringBufferLengthSamples = ringSamples; - bufferLengthSamples = bufferSamples; - - started = false; - _shouldBeAddedToMix = false; - - endOfLastWrite = NULL; - +AudioRingBuffer::AudioRingBuffer(int ringSamples, int bufferSamples) : + ringBufferLengthSamples(ringSamples), + bufferLengthSamples(bufferSamples), + endOfLastWrite(NULL), + started(false), + _shouldBeAddedToMix(false), + _shouldLoopbackForAgent(false) { buffer = new int16_t[ringBufferLengthSamples]; nextOutput = buffer; }; @@ -27,6 +25,7 @@ AudioRingBuffer::AudioRingBuffer(const AudioRingBuffer &otherRingBuffer) { bufferLengthSamples = otherRingBuffer.bufferLengthSamples; started = otherRingBuffer.started; _shouldBeAddedToMix = otherRingBuffer._shouldBeAddedToMix; + _shouldLoopbackForAgent = otherRingBuffer._shouldLoopbackForAgent; buffer = new int16_t[ringBufferLengthSamples]; memcpy(buffer, otherRingBuffer.buffer, sizeof(int16_t) * ringBufferLengthSamples); @@ -149,8 +148,7 @@ int AudioRingBuffer::parseData(unsigned char* sourceBuffer, int numBytes) { return numBytes; } -short AudioRingBuffer::diffLastWriteNextOutput() -{ +short AudioRingBuffer::diffLastWriteNextOutput() { if (endOfLastWrite == NULL) { return 0; } else { From 42a50e9bab6b12e703808411bd23b23ebae76843 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 9 May 2013 12:05:48 -0700 Subject: [PATCH 2/2] make sure that the AudioRingBuffer exists before trying to use it --- audio-mixer/src/main.cpp | 203 ++++++++++++++++++++------------------- 1 file changed, 105 insertions(+), 98 deletions(-) diff --git a/audio-mixer/src/main.cpp b/audio-mixer/src/main.cpp index c47fbb2170..5c6781b46e 100644 --- a/audio-mixer/src/main.cpp +++ b/audio-mixer/src/main.cpp @@ -87,7 +87,7 @@ void *sendBuffer(void *args) { for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) { AudioRingBuffer* agentBuffer = (AudioRingBuffer*) agent->getLinkedData(); - if (agentBuffer != NULL && agentBuffer->getEndOfLastWrite() != NULL) { + if (agentBuffer && agentBuffer->getEndOfLastWrite() != NULL) { if (!agentBuffer->isStarted() && agentBuffer->diffLastWriteNextOutput() <= BUFFER_LENGTH_SAMPLES_PER_CHANNEL + JITTER_BUFFER_SAMPLES) { @@ -112,124 +112,131 @@ void *sendBuffer(void *args) { for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) { AudioRingBuffer* agentRingBuffer = (AudioRingBuffer*) agent->getLinkedData(); - int16_t clientMix[BUFFER_LENGTH_SAMPLES_PER_CHANNEL * 2] = {}; - - for (AgentList::iterator otherAgent = agentList->begin(); otherAgent != agentList->end(); otherAgent++) { - if (otherAgent != agent || (otherAgent == agent && agentRingBuffer->shouldLoopbackForAgent())) { - AudioRingBuffer* otherAgentBuffer = (AudioRingBuffer*) otherAgent->getLinkedData(); - - if (otherAgentBuffer->shouldBeAddedToMix()) { - - float bearingRelativeAngleToSource = 0.f; - float attenuationCoefficient = 1.f; - int numSamplesDelay = 0; - float weakChannelAmplitudeRatio = 1.f; + if (agentRingBuffer) { + int16_t clientMix[BUFFER_LENGTH_SAMPLES_PER_CHANNEL * 2] = {}; + + for (AgentList::iterator otherAgent = agentList->begin(); otherAgent != agentList->end(); otherAgent++) { + if (otherAgent != agent || (otherAgent == agent && agentRingBuffer->shouldLoopbackForAgent())) { + AudioRingBuffer* otherAgentBuffer = (AudioRingBuffer*) otherAgent->getLinkedData(); - if (otherAgent != agent) { - float *agentPosition = agentRingBuffer->getPosition(); - float *otherAgentPosition = otherAgentBuffer->getPosition(); + if (otherAgentBuffer->shouldBeAddedToMix()) { - // calculate the distance to the other agent + float bearingRelativeAngleToSource = 0.f; + float attenuationCoefficient = 1.f; + int numSamplesDelay = 0; + float weakChannelAmplitudeRatio = 1.f; - // 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()); - - if (distanceCoefficients[lowAgentIndex][highAgentIndex] == 0) { - float distanceToAgent = sqrtf(powf(agentPosition[0] - otherAgentPosition[0], 2) + - powf(agentPosition[1] - otherAgentPosition[1], 2) + - powf(agentPosition[2] - otherAgentPosition[2], 2)); + if (otherAgent != agent) { + float *agentPosition = agentRingBuffer->getPosition(); + float *otherAgentPosition = otherAgentBuffer->getPosition(); - float minCoefficient = std::min(1.0f, - powf(0.5, (logf(DISTANCE_RATIO * distanceToAgent) / logf(3)) - 1)); - distanceCoefficients[lowAgentIndex][highAgentIndex] = minCoefficient; - } - - - // get the angle from the right-angle triangle - float triangleAngle = atan2f(fabsf(agentPosition[2] - otherAgentPosition[2]), - fabsf(agentPosition[0] - otherAgentPosition[0])) * (180 / M_PI); - float absoluteAngleToSource = 0; - bearingRelativeAngleToSource = 0; - - // find the angle we need for calculation based on the orientation of the triangle - if (otherAgentPosition[0] > agentPosition[0]) { - if (otherAgentPosition[2] > agentPosition[2]) { - absoluteAngleToSource = -90 + triangleAngle; - } else { - absoluteAngleToSource = -90 - triangleAngle; + // calculate the distance to the other agent + + // 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()); + + if (distanceCoefficients[lowAgentIndex][highAgentIndex] == 0) { + float distanceToAgent = sqrtf(powf(agentPosition[0] - otherAgentPosition[0], 2) + + powf(agentPosition[1] - otherAgentPosition[1], 2) + + powf(agentPosition[2] - otherAgentPosition[2], 2)); + + float minCoefficient = std::min(1.0f, + powf(0.5, + (logf(DISTANCE_RATIO * distanceToAgent) / logf(3)) - 1)); + distanceCoefficients[lowAgentIndex][highAgentIndex] = minCoefficient; } - } else { - if (otherAgentPosition[2] > agentPosition[2]) { - absoluteAngleToSource = 90 - triangleAngle; + + + // get the angle from the right-angle triangle + float triangleAngle = atan2f(fabsf(agentPosition[2] - otherAgentPosition[2]), + fabsf(agentPosition[0] - otherAgentPosition[0])) * (180 / M_PI); + float absoluteAngleToSource = 0; + bearingRelativeAngleToSource = 0; + + // find the angle we need for calculation based on the orientation of the triangle + if (otherAgentPosition[0] > agentPosition[0]) { + if (otherAgentPosition[2] > agentPosition[2]) { + absoluteAngleToSource = -90 + triangleAngle; + } else { + absoluteAngleToSource = -90 - triangleAngle; + } } else { - absoluteAngleToSource = 90 + triangleAngle; + if (otherAgentPosition[2] > agentPosition[2]) { + 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; - } - - float offAxisCoefficient = MAX_OFF_AXIS_ATTENUATION + + + 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; + } + + float offAxisCoefficient = MAX_OFF_AXIS_ATTENUATION + (OFF_AXIS_ATTENUATION_FORMULA_STEP * (fabsf(angleOfDelivery) / 90.0f)); - - attenuationCoefficient = distanceCoefficients[lowAgentIndex][highAgentIndex] + + attenuationCoefficient = distanceCoefficients[lowAgentIndex][highAgentIndex] * otherAgentBuffer->getAttenuationRatio() * offAxisCoefficient; - - bearingRelativeAngleToSource *= (M_PI / 180); - - 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 ? clientMix + BUFFER_LENGTH_SAMPLES_PER_CHANNEL : clientMix; - int16_t* delayedChannel = bearingRelativeAngleToSource > 0.0f ? clientMix : clientMix + BUFFER_LENGTH_SAMPLES_PER_CHANNEL; - - int16_t* delaySamplePointer = otherAgentBuffer->getNextOutput() == otherAgentBuffer->getBuffer() - ? otherAgentBuffer->getBuffer() + RING_BUFFER_SAMPLES - numSamplesDelay - : otherAgentBuffer->getNextOutput() - numSamplesDelay; - - for (int s = 0; s < BUFFER_LENGTH_SAMPLES_PER_CHANNEL; s++) { - - if (s < numSamplesDelay) { - // pull the earlier sample for the delayed channel - int earlierSample = delaySamplePointer[s] * attenuationCoefficient; - plateauAdditionOfSamples(delayedChannel[s], earlierSample * weakChannelAmplitudeRatio); + + bearingRelativeAngleToSource *= (M_PI / 180); + + float sinRatio = fabsf(sinf(bearingRelativeAngleToSource)); + numSamplesDelay = PHASE_DELAY_AT_90 * sinRatio; + weakChannelAmplitudeRatio = 1 - (PHASE_AMPLITUDE_RATIO_AT_90 * sinRatio); } - int16_t currentSample = (otherAgentBuffer->getNextOutput()[s] * attenuationCoefficient); - plateauAdditionOfSamples(goodChannel[s], currentSample); + int16_t* goodChannel = bearingRelativeAngleToSource > 0.0f + ? clientMix + BUFFER_LENGTH_SAMPLES_PER_CHANNEL + : clientMix; + int16_t* delayedChannel = bearingRelativeAngleToSource > 0.0f + ? clientMix + : clientMix + BUFFER_LENGTH_SAMPLES_PER_CHANNEL; - if (s + numSamplesDelay < BUFFER_LENGTH_SAMPLES_PER_CHANNEL) { - plateauAdditionOfSamples(delayedChannel[s + numSamplesDelay], - currentSample * weakChannelAmplitudeRatio); + int16_t* delaySamplePointer = otherAgentBuffer->getNextOutput() == otherAgentBuffer->getBuffer() + ? otherAgentBuffer->getBuffer() + RING_BUFFER_SAMPLES - numSamplesDelay + : otherAgentBuffer->getNextOutput() - numSamplesDelay; + + for (int s = 0; s < BUFFER_LENGTH_SAMPLES_PER_CHANNEL; s++) { + + if (s < numSamplesDelay) { + // pull the earlier sample for the delayed channel + int earlierSample = delaySamplePointer[s] * attenuationCoefficient; + plateauAdditionOfSamples(delayedChannel[s], earlierSample * weakChannelAmplitudeRatio); + } + + int16_t currentSample = (otherAgentBuffer->getNextOutput()[s] * attenuationCoefficient); + plateauAdditionOfSamples(goodChannel[s], currentSample); + + if (s + numSamplesDelay < BUFFER_LENGTH_SAMPLES_PER_CHANNEL) { + plateauAdditionOfSamples(delayedChannel[s + numSamplesDelay], + currentSample * weakChannelAmplitudeRatio); + } } } } } - } - - agentList->getAgentSocket().send(agent->getPublicSocket(), clientMix, BUFFER_LENGTH_BYTES); + + agentList->getAgentSocket().send(agent->getPublicSocket(), clientMix, BUFFER_LENGTH_BYTES); + } } for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) { AudioRingBuffer* agentBuffer = (AudioRingBuffer*) agent->getLinkedData(); - if (agentBuffer->shouldBeAddedToMix()) { + if (agentBuffer && agentBuffer->shouldBeAddedToMix()) { agentBuffer->setNextOutput(agentBuffer->getNextOutput() + BUFFER_LENGTH_SAMPLES_PER_CHANNEL); if (agentBuffer->getNextOutput() >= agentBuffer->getBuffer() + RING_BUFFER_SAMPLES) {