From 5878b4af59d8ae5f1a26e1daa9e4431008aa2be4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Jun 2014 12:50:16 -0700 Subject: [PATCH 1/4] setup listener unattenuated zones for source ring buffers --- assignment-client/src/audio/AudioMixer.cpp | 25 ++++++- assignment-client/src/audio/AudioMixer.h | 4 +- .../src/audio/AudioMixerClientData.cpp | 12 +++- .../src/audio/AudioMixerClientData.h | 10 ++- libraries/octree/src/AABox.h | 69 ------------------ libraries/{octree => shared}/src/AABox.cpp | 0 libraries/shared/src/AABox.h | 71 +++++++++++++++++++ libraries/{octree => shared}/src/AACube.cpp | 0 libraries/{octree => shared}/src/AACube.h | 0 libraries/{octree => shared}/src/BoxBase.h | 0 10 files changed, 115 insertions(+), 76 deletions(-) delete mode 100644 libraries/octree/src/AABox.h rename libraries/{octree => shared}/src/AABox.cpp (100%) create mode 100644 libraries/shared/src/AABox.h rename libraries/{octree => shared}/src/AACube.cpp (100%) rename libraries/{octree => shared}/src/AACube.h (100%) rename libraries/{octree => shared}/src/BoxBase.h (100%) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index d96fce450a..a9c6b71388 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -33,7 +33,10 @@ #include #include +#include +#include #include +#include #include #include @@ -71,7 +74,9 @@ AudioMixer::AudioMixer(const QByteArray& packet) : _performanceThrottlingRatio(0.0f), _numStatFrames(0), _sumListeners(0), - _sumMixes(0) + _sumMixes(0), + _sourceUnattenuatedZone(), + _listenerUnattenuatedZone() { } @@ -412,6 +417,24 @@ void AudioMixer::run() { nodeList->addNodeTypeToInterestSet(NodeType::Agent); nodeList->linkedDataCreateCallback = attachNewBufferToNode; + + // check the payload to see if we have any unattenuated zones + const QString UNATTENUATED_ZONE_REGEX_STRING = "--unattenuated-zone ([\\d.,-]+)"; + QRegExp unattenuatedZoneMatch(UNATTENUATED_ZONE_REGEX_STRING); + + if (unattenuatedZoneMatch.indexIn(_payload) != -1) { + QString unattenuatedZoneString = unattenuatedZoneMatch.cap(1); + QStringList zoneStringList = unattenuatedZoneString.split(','); + + glm::vec3 sourceCorner(zoneStringList[0].toFloat(), zoneStringList[1].toFloat(), zoneStringList[2].toFloat()); + glm::vec3 sourceDimensions(zoneStringList[3].toFloat(), zoneStringList[4].toFloat(), zoneStringList[5].toFloat()); + + glm::vec3 listenerCorner(zoneStringList[6].toFloat(), zoneStringList[7].toFloat(), zoneStringList[8].toFloat()); + glm::vec3 listenerDimensions(zoneStringList[9].toFloat(), zoneStringList[10].toFloat(), zoneStringList[11].toFloat()); + + _sourceUnattenuatedZone = AABox(sourceCorner, sourceDimensions); + _listenerUnattenuatedZone = AABox(listenerCorner, listenerDimensions); + } int nextFrame = 0; QElapsedTimer timer; diff --git a/assignment-client/src/audio/AudioMixer.h b/assignment-client/src/audio/AudioMixer.h index 659227dffb..70eb8bb32d 100644 --- a/assignment-client/src/audio/AudioMixer.h +++ b/assignment-client/src/audio/AudioMixer.h @@ -12,8 +12,8 @@ #ifndef hifi_AudioMixer_h #define hifi_AudioMixer_h +#include #include - #include class PositionalAudioRingBuffer; @@ -51,6 +51,8 @@ private: int _numStatFrames; int _sumListeners; int _sumMixes; + AABox _sourceUnattenuatedZone; + AABox _listenerUnattenuatedZone; }; #endif // hifi_AudioMixer_h diff --git a/assignment-client/src/audio/AudioMixerClientData.cpp b/assignment-client/src/audio/AudioMixerClientData.cpp index 9494e927a9..483cff6018 100644 --- a/assignment-client/src/audio/AudioMixerClientData.cpp +++ b/assignment-client/src/audio/AudioMixerClientData.cpp @@ -19,7 +19,8 @@ #include "AudioMixerClientData.h" AudioMixerClientData::AudioMixerClientData() : - _ringBuffers() + _ringBuffers(), + _listenerUnattenuatedZone(NULL) { } @@ -98,7 +99,8 @@ int AudioMixerClientData::parseData(const QByteArray& packet) { return 0; } -void AudioMixerClientData::checkBuffersBeforeFrameSend(int jitterBufferLengthSamples) { +void AudioMixerClientData::checkBuffersBeforeFrameSend(int jitterBufferLengthSamples, + AABox* checkSourceZone, AABox* listenerZone) { for (int i = 0; i < _ringBuffers.size(); i++) { if (_ringBuffers[i]->shouldBeAddedToMix(jitterBufferLengthSamples)) { // this is a ring buffer that is ready to go @@ -108,6 +110,12 @@ void AudioMixerClientData::checkBuffersBeforeFrameSend(int jitterBufferLengthSam // calculate the average loudness for the next NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL // that would be mixed in _ringBuffers[i]->updateNextOutputTrailingLoudness(); + + if (checkSourceZone && checkSourceZone->contains(_ringBuffers[i]->getPosition())) { + _listenerUnattenuatedZone = listenerZone; + } else { + _listenerUnattenuatedZone = NULL; + } } } } diff --git a/assignment-client/src/audio/AudioMixerClientData.h b/assignment-client/src/audio/AudioMixerClientData.h index 70b653301b..8c3f980789 100644 --- a/assignment-client/src/audio/AudioMixerClientData.h +++ b/assignment-client/src/audio/AudioMixerClientData.h @@ -12,8 +12,7 @@ #ifndef hifi_AudioMixerClientData_h #define hifi_AudioMixerClientData_h -#include - +#include #include #include @@ -28,10 +27,15 @@ public: AvatarAudioRingBuffer* getAvatarAudioRingBuffer() const; int parseData(const QByteArray& packet); - void checkBuffersBeforeFrameSend(int jitterBufferLengthSamples); + void checkBuffersBeforeFrameSend(int jitterBufferLengthSamples, + AABox* checkSourceZone = NULL, AABox* listenerZone = NULL); void pushBuffersAfterFrameSend(); + + AABox* getListenerUnattenuatedZone() const { return _listenerUnattenuatedZone; } + void setListenerUnattenuatedZone(AABox* listenerUnattenuatedZone) { _listenerUnattenuatedZone = listenerUnattenuatedZone; } private: QList _ringBuffers; + AABox* _listenerUnattenuatedZone; }; #endif // hifi_AudioMixerClientData_h diff --git a/libraries/octree/src/AABox.h b/libraries/octree/src/AABox.h deleted file mode 100644 index ef0e535b38..0000000000 --- a/libraries/octree/src/AABox.h +++ /dev/null @@ -1,69 +0,0 @@ -// -// AABox.h -// libraries/octree/src -// -// Created by Brad Hefta-Gaub on 04/11/13. -// Copyright 2013 High Fidelity, Inc. -// -// Originally from lighthouse3d. Modified to utilize glm::vec3 and clean up to our coding standards -// Simple axis aligned box class. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_AABox_h -#define hifi_AABox_h - -#include - -#include "BoxBase.h" - -class AACube; - -class AABox { - -public: - AABox(const glm::vec3& corner, float size); - AABox(const glm::vec3& corner, const glm::vec3& dimensions); - AABox(); - ~AABox() {}; - - void setBox(const glm::vec3& corner, const glm::vec3& scale); - - void setBox(const glm::vec3& corner, float scale); - glm::vec3 getVertexP(const glm::vec3& normal) const; - glm::vec3 getVertexN(const glm::vec3& normal) const; - void scale(float scale); - const glm::vec3& getCorner() const { return _corner; } - const glm::vec3& getScale() const { return _scale; } - const glm::vec3& getDimensions() const { return _scale; } - - glm::vec3 calcCenter() const; - glm::vec3 calcTopFarLeft() const; - glm::vec3 getVertex(BoxVertex vertex) const; - bool contains(const glm::vec3& point) const; - bool contains(const AABox& otherBox) const; - bool touches(const AABox& otherBox) const; - - bool contains(const AACube& otherCube) const; - bool touches(const AACube& otherCube) const; - - bool expandedContains(const glm::vec3& point, float expansion) const; - bool expandedIntersectsSegment(const glm::vec3& start, const glm::vec3& end, float expansion) const; - bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const; - bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration) const; - bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration) const; - -private: - glm::vec3 getClosestPointOnFace(const glm::vec3& point, BoxFace face) const; - glm::vec3 getClosestPointOnFace(const glm::vec4& origin, const glm::vec4& direction, BoxFace face) const; - glm::vec4 getPlane(BoxFace face) const; - - static BoxFace getOppositeFace(BoxFace face); - - glm::vec3 _corner; - glm::vec3 _scale; -}; - -#endif // hifi_AABox_h diff --git a/libraries/octree/src/AABox.cpp b/libraries/shared/src/AABox.cpp similarity index 100% rename from libraries/octree/src/AABox.cpp rename to libraries/shared/src/AABox.cpp diff --git a/libraries/shared/src/AABox.h b/libraries/shared/src/AABox.h new file mode 100644 index 0000000000..71ee7c73d3 --- /dev/null +++ b/libraries/shared/src/AABox.h @@ -0,0 +1,71 @@ +// +// AABox.h +// libraries/octree/src +// +// Created by Brad Hefta-Gaub on 04/11/13. +// Copyright 2013 High Fidelity, Inc. +// +// Originally from lighthouse3d. Modified to utilize glm::vec3 and clean up to our coding standards +// Simple axis aligned box class. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_AABox_h +#define hifi_AABox_h + +#include + +#include "BoxBase.h" + +class AACube; + +class AABox { + +public: + AABox(const glm::vec3& corner, float size); + AABox(const glm::vec3& corner, const glm::vec3& dimensions); + AABox(); + ~AABox() {}; + + void setBox(const glm::vec3& corner, const glm::vec3& scale); + + void setBox(const glm::vec3& corner, float scale); + glm::vec3 getVertexP(const glm::vec3& normal) const; + glm::vec3 getVertexN(const glm::vec3& normal) const; + void scale(float scale); + const glm::vec3& getCorner() const { return _corner; } + const glm::vec3& getScale() const { return _scale; } + const glm::vec3& getDimensions() const { return _scale; } + + glm::vec3 calcCenter() const; + glm::vec3 calcTopFarLeft() const; + glm::vec3 getVertex(BoxVertex vertex) const; + bool contains(const glm::vec3& point) const; + bool contains(const AABox& otherBox) const; + bool touches(const AABox& otherBox) const; + + bool contains(const AACube& otherCube) const; + bool touches(const AACube& otherCube) const; + + bool expandedContains(const glm::vec3& point, float expansion) const; + bool expandedIntersectsSegment(const glm::vec3& start, const glm::vec3& end, float expansion) const; + bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const; + bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration) const; + bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration) const; + + bool isNull() const { return _scale == glm::vec3(0.0f, 0.0f, 0.0f); } + +private: + glm::vec3 getClosestPointOnFace(const glm::vec3& point, BoxFace face) const; + glm::vec3 getClosestPointOnFace(const glm::vec4& origin, const glm::vec4& direction, BoxFace face) const; + glm::vec4 getPlane(BoxFace face) const; + + static BoxFace getOppositeFace(BoxFace face); + + glm::vec3 _corner; + glm::vec3 _scale; +}; + +#endif // hifi_AABox_h diff --git a/libraries/octree/src/AACube.cpp b/libraries/shared/src/AACube.cpp similarity index 100% rename from libraries/octree/src/AACube.cpp rename to libraries/shared/src/AACube.cpp diff --git a/libraries/octree/src/AACube.h b/libraries/shared/src/AACube.h similarity index 100% rename from libraries/octree/src/AACube.h rename to libraries/shared/src/AACube.h diff --git a/libraries/octree/src/BoxBase.h b/libraries/shared/src/BoxBase.h similarity index 100% rename from libraries/octree/src/BoxBase.h rename to libraries/shared/src/BoxBase.h From db1031144b961c0bec7b68ef539a6b2a562e843c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Jun 2014 13:46:03 -0700 Subject: [PATCH 2/4] fix passing of unattenuated zones to buffers --- assignment-client/src/audio/AudioMixer.cpp | 25 +++++++++++++++---- assignment-client/src/audio/AudioMixer.h | 5 ++-- .../src/audio/AudioMixerClientData.cpp | 7 +++--- .../src/audio/AudioMixerClientData.h | 4 --- .../audio/src/PositionalAudioRingBuffer.cpp | 6 ++--- .../audio/src/PositionalAudioRingBuffer.h | 8 ++++-- 6 files changed, 34 insertions(+), 21 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index a9c6b71388..0a723ad6fb 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -75,12 +75,17 @@ AudioMixer::AudioMixer(const QByteArray& packet) : _numStatFrames(0), _sumListeners(0), _sumMixes(0), - _sourceUnattenuatedZone(), - _listenerUnattenuatedZone() + _sourceUnattenuatedZone(NULL), + _listenerUnattenuatedZone(NULL) { } +AudioMixer::~AudioMixer() { + delete _sourceUnattenuatedZone; + delete _listenerUnattenuatedZone; +} + void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuffer* bufferToAdd, AvatarAudioRingBuffer* listeningNodeBuffer) { float bearingRelativeAngleToSource = 0.0f; @@ -432,8 +437,16 @@ void AudioMixer::run() { glm::vec3 listenerCorner(zoneStringList[6].toFloat(), zoneStringList[7].toFloat(), zoneStringList[8].toFloat()); glm::vec3 listenerDimensions(zoneStringList[9].toFloat(), zoneStringList[10].toFloat(), zoneStringList[11].toFloat()); - _sourceUnattenuatedZone = AABox(sourceCorner, sourceDimensions); - _listenerUnattenuatedZone = AABox(listenerCorner, listenerDimensions); + _sourceUnattenuatedZone = new AABox(sourceCorner, sourceDimensions); + _listenerUnattenuatedZone = new AABox(listenerCorner, listenerDimensions); + + glm::vec3 sourceCenter = _sourceUnattenuatedZone->calcCenter(); + glm::vec3 destinationCenter = _listenerUnattenuatedZone->calcCenter(); + + qDebug() << "There is an unattenuated zone with source center at" + << QString("%1, %2, %3").arg(sourceCenter.x).arg(sourceCenter.y).arg(sourceCenter.z); + qDebug() << "Buffers inside this zone will not be attenuated inside a box with center at" + << QString("%1, %2, %3").arg(destinationCenter.x).arg(destinationCenter.y).arg(destinationCenter.z); } int nextFrame = 0; @@ -452,7 +465,9 @@ void AudioMixer::run() { foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { if (node->getLinkedData()) { - ((AudioMixerClientData*) node->getLinkedData())->checkBuffersBeforeFrameSend(JITTER_BUFFER_SAMPLES); + ((AudioMixerClientData*) node->getLinkedData())->checkBuffersBeforeFrameSend(JITTER_BUFFER_SAMPLES, + _sourceUnattenuatedZone, + _listenerUnattenuatedZone); } } diff --git a/assignment-client/src/audio/AudioMixer.h b/assignment-client/src/audio/AudioMixer.h index 70eb8bb32d..39f8cf63ae 100644 --- a/assignment-client/src/audio/AudioMixer.h +++ b/assignment-client/src/audio/AudioMixer.h @@ -26,6 +26,7 @@ class AudioMixer : public ThreadedAssignment { Q_OBJECT public: AudioMixer(const QByteArray& packet); + ~AudioMixer(); public slots: /// threaded run of assignment void run(); @@ -51,8 +52,8 @@ private: int _numStatFrames; int _sumListeners; int _sumMixes; - AABox _sourceUnattenuatedZone; - AABox _listenerUnattenuatedZone; + AABox* _sourceUnattenuatedZone; + AABox* _listenerUnattenuatedZone; }; #endif // hifi_AudioMixer_h diff --git a/assignment-client/src/audio/AudioMixerClientData.cpp b/assignment-client/src/audio/AudioMixerClientData.cpp index 483cff6018..2f78a4ac78 100644 --- a/assignment-client/src/audio/AudioMixerClientData.cpp +++ b/assignment-client/src/audio/AudioMixerClientData.cpp @@ -19,8 +19,7 @@ #include "AudioMixerClientData.h" AudioMixerClientData::AudioMixerClientData() : - _ringBuffers(), - _listenerUnattenuatedZone(NULL) + _ringBuffers() { } @@ -112,9 +111,9 @@ void AudioMixerClientData::checkBuffersBeforeFrameSend(int jitterBufferLengthSam _ringBuffers[i]->updateNextOutputTrailingLoudness(); if (checkSourceZone && checkSourceZone->contains(_ringBuffers[i]->getPosition())) { - _listenerUnattenuatedZone = listenerZone; + _ringBuffers[i]->setListenerUnattenuatedZone(listenerZone); } else { - _listenerUnattenuatedZone = NULL; + _ringBuffers[i]->setListenerUnattenuatedZone(NULL); } } } diff --git a/assignment-client/src/audio/AudioMixerClientData.h b/assignment-client/src/audio/AudioMixerClientData.h index 8c3f980789..e52b09e134 100644 --- a/assignment-client/src/audio/AudioMixerClientData.h +++ b/assignment-client/src/audio/AudioMixerClientData.h @@ -30,12 +30,8 @@ public: void checkBuffersBeforeFrameSend(int jitterBufferLengthSamples, AABox* checkSourceZone = NULL, AABox* listenerZone = NULL); void pushBuffersAfterFrameSend(); - - AABox* getListenerUnattenuatedZone() const { return _listenerUnattenuatedZone; } - void setListenerUnattenuatedZone(AABox* listenerUnattenuatedZone) { _listenerUnattenuatedZone = listenerUnattenuatedZone; } private: QList _ringBuffers; - AABox* _listenerUnattenuatedZone; }; #endif // hifi_AudioMixerClientData_h diff --git a/libraries/audio/src/PositionalAudioRingBuffer.cpp b/libraries/audio/src/PositionalAudioRingBuffer.cpp index bb47c6de9e..1cc4147175 100644 --- a/libraries/audio/src/PositionalAudioRingBuffer.cpp +++ b/libraries/audio/src/PositionalAudioRingBuffer.cpp @@ -28,14 +28,12 @@ PositionalAudioRingBuffer::PositionalAudioRingBuffer(PositionalAudioRingBuffer:: _willBeAddedToMix(false), _shouldLoopbackForNode(false), _shouldOutputStarveDebug(true), - _isStereo(isStereo) + _isStereo(isStereo), + _listenerUnattenuatedZone(NULL) { } -PositionalAudioRingBuffer::~PositionalAudioRingBuffer() { -} - int PositionalAudioRingBuffer::parseData(const QByteArray& packet) { // skip the packet header (includes the source UUID) diff --git a/libraries/audio/src/PositionalAudioRingBuffer.h b/libraries/audio/src/PositionalAudioRingBuffer.h index 17a663d5f6..00362c245a 100644 --- a/libraries/audio/src/PositionalAudioRingBuffer.h +++ b/libraries/audio/src/PositionalAudioRingBuffer.h @@ -12,9 +12,10 @@ #ifndef hifi_PositionalAudioRingBuffer_h #define hifi_PositionalAudioRingBuffer_h -#include #include +#include + #include "AudioRingBuffer.h" class PositionalAudioRingBuffer : public AudioRingBuffer { @@ -25,7 +26,6 @@ public: }; PositionalAudioRingBuffer(PositionalAudioRingBuffer::Type type, bool isStereo = false); - ~PositionalAudioRingBuffer(); int parseData(const QByteArray& packet); int parsePositionalData(const QByteArray& positionalByteArray); @@ -47,6 +47,9 @@ public: const glm::vec3& getPosition() const { return _position; } const glm::quat& getOrientation() const { return _orientation; } + AABox* getListenerUnattenuatedZone() const { return _listenerUnattenuatedZone; } + void setListenerUnattenuatedZone(AABox* listenerUnattenuatedZone) { _listenerUnattenuatedZone = listenerUnattenuatedZone; } + protected: // disallow copying of PositionalAudioRingBuffer objects PositionalAudioRingBuffer(const PositionalAudioRingBuffer&); @@ -61,6 +64,7 @@ protected: bool _isStereo; float _nextOutputTrailingLoudness; + AABox* _listenerUnattenuatedZone; }; #endif // hifi_PositionalAudioRingBuffer_h From 1228bd4a1efb1e1b3440c286398cf8c25319ec92 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Jun 2014 14:18:39 -0700 Subject: [PATCH 3/4] handle addition of samples for an unattenuated listener --- assignment-client/src/audio/AudioMixer.cpp | 172 ++++++++++++--------- 1 file changed, 95 insertions(+), 77 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 0a723ad6fb..0bba990463 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -93,6 +93,8 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf int numSamplesDelay = 0; float weakChannelAmplitudeRatio = 1.0f; + bool shouldAttenuate = false; + if (bufferToAdd != listeningNodeBuffer) { // if the two buffer pointers do not match then these are different buffers glm::vec3 relativePosition = bufferToAdd->getPosition() - listeningNodeBuffer->getPosition(); @@ -111,82 +113,87 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf ++_sumMixes; - glm::quat inverseOrientation = glm::inverse(listeningNodeBuffer->getOrientation()); - float distanceSquareToSource = glm::dot(relativePosition, relativePosition); - float radius = 0.0f; - - if (bufferToAdd->getType() == PositionalAudioRingBuffer::Injector) { - InjectedAudioRingBuffer* injectedBuffer = (InjectedAudioRingBuffer*) bufferToAdd; - radius = injectedBuffer->getRadius(); - attenuationCoefficient *= injectedBuffer->getAttenuationRatio(); - } - - if (radius == 0 || (distanceSquareToSource > radius * radius)) { - // this is either not a spherical source, or the listener is outside the sphere - - if (radius > 0) { - // this is a spherical source - the distance used for the coefficient - // needs to be the closest point on the boundary to the source - - // ovveride the distance to the node with the distance to the point on the - // boundary of the sphere - distanceSquareToSource -= (radius * radius); - - } else { - // calculate the angle delivery for off-axis attenuation - glm::vec3 rotatedListenerPosition = glm::inverse(bufferToAdd->getOrientation()) * relativePosition; - - float angleOfDelivery = glm::angle(glm::vec3(0.0f, 0.0f, -1.0f), - glm::normalize(rotatedListenerPosition)); - - const float MAX_OFF_AXIS_ATTENUATION = 0.2f; - const float OFF_AXIS_ATTENUATION_FORMULA_STEP = (1 - MAX_OFF_AXIS_ATTENUATION) / 2.0f; - - float offAxisCoefficient = MAX_OFF_AXIS_ATTENUATION + - (OFF_AXIS_ATTENUATION_FORMULA_STEP * (angleOfDelivery / PI_OVER_TWO)); - - // multiply the current attenuation coefficient by the calculated off axis coefficient - attenuationCoefficient *= offAxisCoefficient; + shouldAttenuate = !bufferToAdd->getListenerUnattenuatedZone()->contains(listeningNodeBuffer->getPosition()); + + if (shouldAttenuate) { + glm::quat inverseOrientation = glm::inverse(listeningNodeBuffer->getOrientation()); + + float distanceSquareToSource = glm::dot(relativePosition, relativePosition); + float radius = 0.0f; + + if (bufferToAdd->getType() == PositionalAudioRingBuffer::Injector) { + InjectedAudioRingBuffer* injectedBuffer = (InjectedAudioRingBuffer*) bufferToAdd; + radius = injectedBuffer->getRadius(); + attenuationCoefficient *= injectedBuffer->getAttenuationRatio(); + } + + if (radius == 0 || (distanceSquareToSource > radius * radius)) { + // this is either not a spherical source, or the listener is outside the sphere + + if (radius > 0) { + // this is a spherical source - the distance used for the coefficient + // needs to be the closest point on the boundary to the source + + // ovveride the distance to the node with the distance to the point on the + // boundary of the sphere + distanceSquareToSource -= (radius * radius); + + } else { + // calculate the angle delivery for off-axis attenuation + glm::vec3 rotatedListenerPosition = glm::inverse(bufferToAdd->getOrientation()) * relativePosition; + + float angleOfDelivery = glm::angle(glm::vec3(0.0f, 0.0f, -1.0f), + glm::normalize(rotatedListenerPosition)); + + const float MAX_OFF_AXIS_ATTENUATION = 0.2f; + const float OFF_AXIS_ATTENUATION_FORMULA_STEP = (1 - MAX_OFF_AXIS_ATTENUATION) / 2.0f; + + float offAxisCoefficient = MAX_OFF_AXIS_ATTENUATION + + (OFF_AXIS_ATTENUATION_FORMULA_STEP * (angleOfDelivery / PI_OVER_TWO)); + + // multiply the current attenuation coefficient by the calculated off axis coefficient + attenuationCoefficient *= offAxisCoefficient; + } + + glm::vec3 rotatedSourcePosition = inverseOrientation * relativePosition; + + 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 node + float distanceCoefficient = powf(GEOMETRIC_AMPLITUDE_SCALAR, + DISTANCE_SCALE_LOG + + (0.5f * logf(distanceSquareToSource) / logf(DISTANCE_LOG_BASE)) - 1); + distanceCoefficient = std::min(1.0f, distanceCoefficient); + + // multiply the current attenuation coefficient by the distance coefficient + attenuationCoefficient *= distanceCoefficient; + + // project the rotated source position vector onto the XZ plane + rotatedSourcePosition.y = 0.0f; + + // produce an oriented angle about the y-axis + bearingRelativeAngleToSource = glm::orientedAngle(glm::vec3(0.0f, 0.0f, -1.0f), + glm::normalize(rotatedSourcePosition), + glm::vec3(0.0f, 1.0f, 0.0f)); + + const float PHASE_AMPLITUDE_RATIO_AT_90 = 0.5; + + // figure out the number of samples of delay and the ratio of the amplitude + // in the weak channel for audio spatialization + float sinRatio = fabsf(sinf(bearingRelativeAngleToSource)); + numSamplesDelay = SAMPLE_PHASE_DELAY_AT_90 * sinRatio; + weakChannelAmplitudeRatio = 1 - (PHASE_AMPLITUDE_RATIO_AT_90 * sinRatio); } - - glm::vec3 rotatedSourcePosition = inverseOrientation * relativePosition; - - 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 node - float distanceCoefficient = powf(GEOMETRIC_AMPLITUDE_SCALAR, - DISTANCE_SCALE_LOG + - (0.5f * logf(distanceSquareToSource) / logf(DISTANCE_LOG_BASE)) - 1); - distanceCoefficient = std::min(1.0f, distanceCoefficient); - - // multiply the current attenuation coefficient by the distance coefficient - attenuationCoefficient *= distanceCoefficient; - - // project the rotated source position vector onto the XZ plane - rotatedSourcePosition.y = 0.0f; - - // produce an oriented angle about the y-axis - bearingRelativeAngleToSource = glm::orientedAngle(glm::vec3(0.0f, 0.0f, -1.0f), - glm::normalize(rotatedSourcePosition), - glm::vec3(0.0f, 1.0f, 0.0f)); - - const float PHASE_AMPLITUDE_RATIO_AT_90 = 0.5; - - // figure out the number of samples of delay and the ratio of the amplitude - // in the weak channel for audio spatialization - float sinRatio = fabsf(sinf(bearingRelativeAngleToSource)); - numSamplesDelay = SAMPLE_PHASE_DELAY_AT_90 * sinRatio; - weakChannelAmplitudeRatio = 1 - (PHASE_AMPLITUDE_RATIO_AT_90 * sinRatio); } } const int16_t* nextOutputStart = bufferToAdd->getNextOutput(); - if (!bufferToAdd->isStereo()) { + if (!bufferToAdd->isStereo() && shouldAttenuate) { // this is a mono buffer, which means it gets full attenuation and spatialization // if the bearing relative angle to source is > 0 then the delayed channel is the right one @@ -295,7 +302,8 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf } else if (i + 1 < numSamplesDelay) { // MMX add two delayed samples __m64 bufferSamples = _mm_set_pi16(_clientSamples[parentIndex + delayedChannelOffset], - _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset], 0, 0); + _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset], + 0, 0); __m64 addSamples = _mm_set_pi16(delayNextOutputStart[i] * attenuationAndWeakChannelRatio, delayNextOutputStart[i + 1] * attenuationAndWeakChannelRatio, 0, 0); @@ -317,16 +325,26 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf } } } else { - // stereo buffer - do attenuation but no sample delay for spatialization + // this is a stereo buffer or an unattenuated buffer, don't perform spatialization for (int s = 0; s < NETWORK_BUFFER_LENGTH_SAMPLES_STEREO; s += 4) { - // use MMX to clamp four additions at a time - _clientSamples[s] = glm::clamp(_clientSamples[s] + (int) (nextOutputStart[s] * attenuationCoefficient), - MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); - _clientSamples[s + 1] = glm::clamp(_clientSamples[s + 1] + (int) (nextOutputStart[s + 1] * attenuationCoefficient), + + int stereoDivider = bufferToAdd->isStereo() ? 1 : 2; + + if (!shouldAttenuate) { + attenuationCoefficient = 1.0f; + } + + _clientSamples[s] = glm::clamp(_clientSamples[s] + + (int) (nextOutputStart[s] * attenuationCoefficient), + MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); + _clientSamples[s + 1] = glm::clamp(_clientSamples[s + 1] + + (int) (nextOutputStart[s + (1 / stereoDivider)] * attenuationCoefficient), MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); - _clientSamples[s + 2] = glm::clamp(_clientSamples[s + 2] + (int) (nextOutputStart[s + 2] * attenuationCoefficient), + _clientSamples[s + 2] = glm::clamp(_clientSamples[s + 2] + + (int) (nextOutputStart[s + (2 / stereoDivider)] * attenuationCoefficient), MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); - _clientSamples[s + 3] = glm::clamp(_clientSamples[s + 3] + (int) (nextOutputStart[s + 3] * attenuationCoefficient), + _clientSamples[s + 3] = glm::clamp(_clientSamples[s + 3] + + (int) (nextOutputStart[s + (3 / stereoDivider)] * attenuationCoefficient), MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); } } From dd5d59208eae828407be0632dcd1c497e8e4b8c4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Jun 2014 15:05:38 -0700 Subject: [PATCH 4/4] fix a crash when grabbing AABox from buffer --- assignment-client/src/audio/AudioMixer.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 0bba990463..2dc51b44a0 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -93,9 +93,9 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf int numSamplesDelay = 0; float weakChannelAmplitudeRatio = 1.0f; - bool shouldAttenuate = false; + bool shouldAttenuate = (bufferToAdd != listeningNodeBuffer); - if (bufferToAdd != listeningNodeBuffer) { + if (shouldAttenuate) { // if the two buffer pointers do not match then these are different buffers glm::vec3 relativePosition = bufferToAdd->getPosition() - listeningNodeBuffer->getPosition(); @@ -113,8 +113,9 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf ++_sumMixes; - - shouldAttenuate = !bufferToAdd->getListenerUnattenuatedZone()->contains(listeningNodeBuffer->getPosition()); + if (bufferToAdd->getListenerUnattenuatedZone()) { + shouldAttenuate = !bufferToAdd->getListenerUnattenuatedZone()->contains(listeningNodeBuffer->getPosition()); + } if (shouldAttenuate) { glm::quat inverseOrientation = glm::inverse(listeningNodeBuffer->getOrientation()); @@ -335,16 +336,19 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf } _clientSamples[s] = glm::clamp(_clientSamples[s] - + (int) (nextOutputStart[s] * attenuationCoefficient), + + (int) (nextOutputStart[(s / stereoDivider)] * attenuationCoefficient), MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); _clientSamples[s + 1] = glm::clamp(_clientSamples[s + 1] - + (int) (nextOutputStart[s + (1 / stereoDivider)] * attenuationCoefficient), + + (int) (nextOutputStart[(s / stereoDivider) + (1 / stereoDivider)] + * attenuationCoefficient), MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); _clientSamples[s + 2] = glm::clamp(_clientSamples[s + 2] - + (int) (nextOutputStart[s + (2 / stereoDivider)] * attenuationCoefficient), + + (int) (nextOutputStart[(s / stereoDivider) + (2 / stereoDivider)] + * attenuationCoefficient), MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); _clientSamples[s + 3] = glm::clamp(_clientSamples[s + 3] - + (int) (nextOutputStart[s + (3 / stereoDivider)] * attenuationCoefficient), + + (int) (nextOutputStart[(s / stereoDivider) + (3 / stereoDivider)] + * attenuationCoefficient), MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); } }