diff --git a/audio-mixer/src/main.cpp b/audio-mixer/src/main.cpp index 982ebc526c..43c6b3ac50 100644 --- a/audio-mixer/src/main.cpp +++ b/audio-mixer/src/main.cpp @@ -17,6 +17,8 @@ #include #include +#include +#include #include #include #include @@ -55,13 +57,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; - -const float MAX_OFF_AXIS_ATTENUATION = 0.2f; -const float OFF_AXIS_ATTENUATION_FORMULA_STEP = (1 - MAX_OFF_AXIS_ATTENUATION) / 2.0f; - void plateauAdditionOfSamples(int16_t &mixSample, int16_t sampleToAdd) { long sumSample = sampleToAdd + mixSample; @@ -128,10 +123,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,90 +137,101 @@ 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 - - // 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.x - otherAgentPosition.x, 2) + - powf(agentPosition.y - otherAgentPosition.y, 2) + - powf(agentPosition.z - otherAgentPosition.z, 2)); + glm::vec3 listenerPosition = agentRingBuffer->getPosition(); + glm::vec3 relativePosition = otherAgentBuffer->getPosition() - agentRingBuffer->getPosition(); + glm::quat inverseOrientation = glm::inverse(agentRingBuffer->getOrientation()); + glm::vec3 rotatedSourcePosition = inverseOrientation * relativePosition; + + float distanceSquareToSource = glm::dot(relativePosition, relativePosition); + + float distanceCoefficient = 1.0f; + float offAxisCoefficient = 1.0f; + + 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 = std::min(1.0f, - powf(0.3, - (logf(DISTANCE_SCALE * distanceToAgent) / logf(2.5)) - - 1)); - distanceCoefficients[lowAgentIndex][highAgentIndex] = minCoefficient; - } - - - // 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) { - if (otherAgentPosition.z > agentPosition.z) { - absoluteAngleToSource = -90 + triangleAngle; + 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 closestPoint = glm::normalize(relativePosition) * otherAgentBuffer->getRadius(); + + // for the other calculations the agent position is the closest point on the sphere + rotatedSourcePosition = inverseOrientation * closestPoint; + + // ovveride the distance to the agent with the distance to the point on the + // boundary of the sphere + distanceSquareToSource = glm::distance2(listenerPosition, -closestPoint); + } else { - absoluteAngleToSource = -90 - triangleAngle; - } - } else { - if (otherAgentPosition.z > agentPosition.z) { - absoluteAngleToSource = 90 - triangleAngle; - } else { - absoluteAngleToSource = 90 + triangleAngle; + // calculate the angle delivery + glm::vec3 rotatedListenerPosition = glm::inverse(otherAgentBuffer->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; + + offAxisCoefficient = MAX_OFF_AXIS_ATTENUATION + + (OFF_AXIS_ATTENUATION_FORMULA_STEP * (angleOfDelivery / 90.0f)); } + + 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 + 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 + + // calculate the angle from the source to the listener + + // 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; + const int PHASE_DELAY_AT_90 = 20; + + float sinRatio = fabsf(sinf(glm::radians(bearingRelativeAngleToSource))); + numSamplesDelay = PHASE_DELAY_AT_90 * sinRatio; + weakChannelAmplitudeRatio = 1 - (PHASE_AMPLITUDE_RATIO_AT_90 * sinRatio); } - 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 = distanceCoefficient * 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 - ? clientSamples + BUFFER_LENGTH_SAMPLES_PER_CHANNEL - : clientSamples; - int16_t* delayedChannel = bearingRelativeAngleToSource > 0.0f ? clientSamples : 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() ? otherAgentBuffer->getBuffer() + RING_BUFFER_SAMPLES - numSamplesDelay @@ -288,7 +290,7 @@ int main(int argc, const char* argv[]) { 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 avatarAgent->setAlive(false); } diff --git a/injector/src/main.cpp b/injector/src/main.cpp index 32a8442d8f..41e2bc0bbd 100644 --- a/injector/src/main.cpp +++ b/injector/src/main.cpp @@ -27,32 +27,41 @@ const int AVATAR_MIXER_DATA_SEND_INTERVAL_MSECS = 15; const int DEFAULT_INJECTOR_VOLUME = 0xFF; +enum { + INJECTOR_POSITION_X, + INJECTOR_POSITION_Y, + INJECTOR_POSITION_Z, + INJECTOR_YAW +}; + // Command line parameter defaults bool loopAudio = true; float sleepIntervalMin = 1.00; float sleepIntervalMax = 2.00; char *sourceAudioFile = NULL; -const char *allowedParameters = ":rb::t::c::a::f::d:"; +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; +float triggerDistance = 0.0f; +float radius = 0.0f; void usage(void) { std::cout << "High Fidelity - Interface audio injector" << std::endl; - std::cout << " -r Random sleep mode. If not specified will default to constant loop." << std::endl; + std::cout << " -s Random sleep mode. If not specified will default to constant loop." << std::endl; std::cout << " -b FLOAT Min. number of seconds to sleep. Only valid in random sleep mode. Default 1.0" << std::endl; std::cout << " -t FLOAT Max. number of seconds to sleep. Only valid in random sleep mode. Default 2.0" << std::endl; std::cout << " -c FLOAT,FLOAT,FLOAT,FLOAT X,Y,Z,YAW position in universe where audio will be originating from and direction. Defaults to 0,0,0,0" << std::endl; std::cout << " -a 0-255 Attenuation curve modifier, defaults to 255" << std::endl; std::cout << " -f FILENAME Name of audio source file. Required - RAW format, 22050hz 16bit signed mono" << std::endl; std::cout << " -d FLOAT Trigger distance for injection. If not specified will loop constantly" << std::endl; + std::cout << " -r FLOAT Radius for spherical source. If not specified injected audio is point source" << std::endl; } bool processParameters(int parameterCount, char* parameterData[]) { int p; while ((p = getopt(parameterCount, parameterData, allowedParameters)) != -1) { switch (p) { - case 'r': + case 's': ::loopAudio = false; std::cout << "[DEBUG] Random sleep mode enabled" << std::endl; break; @@ -92,6 +101,10 @@ bool processParameters(int parameterCount, char* parameterData[]) { ::triggerDistance = atof(optarg); std::cout << "[DEBUG] Trigger distance: " << optarg << std::endl; break; + case 'r': + ::radius = atof(optarg); + std::cout << "[DEBUG] Injector radius: " << optarg << std::endl; + break; default: usage(); return false; @@ -160,9 +173,16 @@ int main(int argc, char* argv[]) { // start the agent list thread that will kill off agents when they stop talking agentList->startSilentAgentRemovalThread(); - injector.setPosition(glm::vec3(::floatArguments[0], ::floatArguments[1], ::floatArguments[2])); - injector.setBearing(*(::floatArguments + 3)); + injector.setPosition(glm::vec3(::floatArguments[INJECTOR_POSITION_X], + ::floatArguments[INJECTOR_POSITION_Y], + ::floatArguments[INJECTOR_POSITION_Z])); + injector.setOrientation(glm::quat(glm::vec3(0.0f, ::floatArguments[INJECTOR_YAW], 0.0f))); injector.setVolume(::volume); + + if (::radius > 0) { + // if we were passed a cube side length, give that to the injector + injector.setRadius(::radius); + } // register the callback for agent data creation agentList->linkedDataCreateCallback = createAvatarDataForAgent; diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ae233e8d8c..b39d8c54e1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2232,7 +2232,7 @@ void Application::maybeEditVoxelUnderCursor() { AudioInjector* voxelInjector = AudioInjectionManager::injectorWithCapacity(11025); voxelInjector->setPosition(glm::vec3(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z)); //_myAvatar.getPosition() - voxelInjector->setBearing(-1 * _myAvatar.getAbsoluteHeadYaw()); +// voxelInjector->setBearing(-1 * _myAvatar.getAbsoluteHeadYaw()); voxelInjector->setVolume (16 * pow (_mouseVoxel.s, 2) / .0000001); //255 is max, and also default value /* for (int i = 0; i @@ -2295,7 +2295,7 @@ void Application::deleteVoxelUnderCursor() { sendVoxelEditMessage(PACKET_HEADER_ERASE_VOXEL, _mouseVoxel); AudioInjector* voxelInjector = AudioInjectionManager::injectorWithCapacity(5000); voxelInjector->setPosition(glm::vec3(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z)); - voxelInjector->setBearing(0); //straight down the z axis +// voxelInjector->setBearing(0); //straight down the z axis voxelInjector->setVolume (255); //255 is max, and also default value diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index bf100d733b..16ac7fa4f7 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -133,7 +133,10 @@ int audioCallback (const void* inputBuffer, Agent* audioMixer = agentList->soloAgentOfType(AGENT_TYPE_AUDIO_MIXER); if (audioMixer) { - int leadingBytes = 2 + (sizeof(float) * 4); + glm::vec3 headPosition = interfaceAvatar->getHeadJointPosition(); + glm::quat headOrientation = interfaceAvatar->getHead().getOrientation(); + + int leadingBytes = 1 + sizeof(headPosition) + sizeof(headOrientation) + sizeof(unsigned char); // we need the amount of bytes in the buffer + 1 for type // + 12 for 3 floats for position + float for bearing + 1 attenuation byte @@ -143,29 +146,15 @@ int audioCallback (const void* inputBuffer, unsigned char *currentPacketPtr = dataPacket + 1; // memcpy the three float positions - memcpy(currentPacketPtr, &interfaceAvatar->getHeadJointPosition(), sizeof(float) * 3); - currentPacketPtr += (sizeof(float) * 3); + memcpy(currentPacketPtr, &headPosition, sizeof(headPosition)); + currentPacketPtr += (sizeof(headPosition)); // tell the mixer not to add additional attenuation to our source *(currentPacketPtr++) = 255; - // memcpy the corrected render yaw - float correctedYaw = fmodf(-1 * interfaceAvatar->getAbsoluteHeadYaw(), 360); - - if (correctedYaw > 180) { - correctedYaw -= 360; - } else if (correctedYaw < -180) { - correctedYaw += 360; - } - - if (Application::getInstance()->shouldEchoAudio()) { - correctedYaw = correctedYaw > 0 - ? correctedYaw + AGENT_LOOPBACK_MODIFIER - : correctedYaw - AGENT_LOOPBACK_MODIFIER; - } - - memcpy(currentPacketPtr, &correctedYaw, sizeof(float)); - currentPacketPtr += sizeof(float); + // memcpy our orientation + memcpy(currentPacketPtr, &headOrientation, sizeof(headOrientation)); + currentPacketPtr += sizeof(headOrientation); // copy the audio data to the last BUFFER_LENGTH_BYTES bytes of the data packet memcpy(currentPacketPtr, inputLeft, BUFFER_LENGTH_BYTES); diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 8e540c9735..11dec28dfc 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -18,8 +18,9 @@ const int MAX_INJECTOR_VOLUME = 0xFF; AudioInjector::AudioInjector(const char* filename) : - _position(), - _bearing(0), + _position(0.0f, 0.0f, 0.0f), + _orientation(0.0f, 0.0f, 0.0f, 0.0f), + _radius(0.0f), _volume(MAX_INJECTOR_VOLUME), _indexOfNextSlot(0), _isInjectingAudio(false) @@ -47,8 +48,9 @@ AudioInjector::AudioInjector(const char* filename) : AudioInjector::AudioInjector(int maxNumSamples) : _numTotalSamples(maxNumSamples), - _position(), - _bearing(0), + _position(0.0f, 0.0f, 0.0f), + _orientation(0.0f, 0.0f, 0.0f, 0.0f), + _radius(0.0f), _volume(MAX_INJECTOR_VOLUME), _indexOfNextSlot(0), _isInjectingAudio(false) @@ -70,12 +72,20 @@ void AudioInjector::injectAudio(UDPSocket* injectorSocket, sockaddr* destination timeval startTime; // calculate the number of bytes required for additional data - int leadingBytes = sizeof(PACKET_HEADER) + sizeof(_streamIdentifier) - + sizeof(_position) + sizeof(_bearing) + sizeof(_volume); + int leadingBytes = sizeof(PACKET_HEADER) + sizeof(INJECT_AUDIO_AT_POINT_COMMAND) + sizeof(_streamIdentifier) + + sizeof(_position) + sizeof(_orientation) + sizeof(_volume); + + if (_radius > 0) { + // we'll need 4 extra bytes if the cube side length is being sent as well + leadingBytes += sizeof(_radius); + } + unsigned char dataPacket[BUFFER_LENGTH_BYTES + leadingBytes]; dataPacket[0] = PACKET_HEADER_INJECT_AUDIO; - unsigned char *currentPacketPtr = dataPacket + 1; + // add the correct command for point source or cube of sound + dataPacket[1] = (_radius > 0) ? INJECT_AUDIO_AT_CUBE_COMMAND : INJECT_AUDIO_AT_POINT_COMMAND; + unsigned char *currentPacketPtr = dataPacket + sizeof(PACKET_HEADER) + sizeof(INJECT_AUDIO_AT_POINT_COMMAND); // copy the identifier for this injector memcpy(currentPacketPtr, &_streamIdentifier, sizeof(_streamIdentifier)); @@ -84,11 +94,18 @@ void AudioInjector::injectAudio(UDPSocket* injectorSocket, sockaddr* destination memcpy(currentPacketPtr, &_position, sizeof(_position)); currentPacketPtr += sizeof(_position); + if (_radius > 0) { + // if we have a cube half height we need to send it here + // this tells the mixer how much volume the injected audio will occupy + memcpy(currentPacketPtr, &_radius, sizeof(_radius)); + currentPacketPtr += sizeof(_radius); + } + *currentPacketPtr = _volume; currentPacketPtr++; - memcpy(currentPacketPtr, &_bearing, sizeof(_bearing)); - currentPacketPtr += sizeof(_bearing); + memcpy(currentPacketPtr, &_orientation, sizeof(_orientation)); + currentPacketPtr += sizeof(_orientation); gettimeofday(&startTime, NULL); int nextFrame = 0; diff --git a/libraries/audio/src/AudioInjector.h b/libraries/audio/src/AudioInjector.h index 7db9398fc9..42bc1f1a2c 100644 --- a/libraries/audio/src/AudioInjector.h +++ b/libraries/audio/src/AudioInjector.h @@ -36,8 +36,11 @@ public: const glm::vec3& getPosition() const { return _position; } void setPosition(const glm::vec3& position) { _position = position; } - float getBearing() const { return _bearing; } - void setBearing(float bearing) { _bearing = bearing; } + const glm::quat& getOrientation() const { return _orientation; } + void setOrientation(const glm::quat& orientation) { _orientation = orientation; } + + float getRadius() const { return _radius; } + void setRadius(float radius) { _radius = radius; } void addSample(const int16_t sample); void addSamples(int16_t* sampleBuffer, int numSamples); @@ -46,7 +49,8 @@ private: int16_t* _audioSampleArray; int _numTotalSamples; glm::vec3 _position; - float _bearing; + glm::quat _orientation; + float _radius; unsigned char _volume; int _indexOfNextSlot; bool _isInjectingAudio; diff --git a/libraries/audio/src/AudioRingBuffer.cpp b/libraries/audio/src/AudioRingBuffer.cpp index 006dd825bf..6bdb7f9aae 100644 --- a/libraries/audio/src/AudioRingBuffer.cpp +++ b/libraries/audio/src/AudioRingBuffer.cpp @@ -17,6 +17,7 @@ AudioRingBuffer::AudioRingBuffer(int ringSamples, int bufferSamples) : AgentData(NULL), _ringBufferLengthSamples(ringSamples), _bufferLengthSamples(bufferSamples), + _radius(0.0f), _endOfLastWrite(NULL), _started(false), _shouldBeAddedToMix(false), @@ -46,31 +47,34 @@ int AudioRingBuffer::parseData(unsigned char* sourceBuffer, int numBytes) { // we've got a stream identifier to pull from the packet memcpy(&_streamIdentifier, dataBuffer, sizeof(_streamIdentifier)); dataBuffer += sizeof(_streamIdentifier); + + // push past the injection command + dataBuffer += sizeof(INJECT_AUDIO_AT_POINT_COMMAND); } memcpy(&_position, dataBuffer, sizeof(_position)); - dataBuffer += (sizeof(_position)); + dataBuffer += sizeof(_position); + + if (sourceBuffer[0] == PACKET_HEADER_INJECT_AUDIO && sourceBuffer[1] == INJECT_AUDIO_AT_CUBE_COMMAND) { + // this is audio that needs to be injected as a volume (cube) + // parse out the cubeHalfHeight sent by the client + memcpy(&_radius, dataBuffer, sizeof(_radius)); + dataBuffer += sizeof(_radius); + } unsigned int attenuationByte = *(dataBuffer++); _attenuationRatio = attenuationByte / 255.0f; - memcpy(&_bearing, dataBuffer, sizeof(float)); - dataBuffer += sizeof(_bearing); + memcpy(&_orientation, dataBuffer, sizeof(_orientation)); + dataBuffer += sizeof(_orientation); - // if this agent sent us a NaN bearing then don't consider this good audio and bail - if (std::isnan(_bearing)) { + // if this agent sent us a NaN for first float in orientation then don't consider this good audio and bail + if (std::isnan(_orientation.x)) { _endOfLastWrite = _nextOutput = _buffer; _started = false; 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 { + // currently no possiblity for loopback, need to add once quaternion audio is working again _shouldLoopbackForAgent = false; } } diff --git a/libraries/audio/src/AudioRingBuffer.h b/libraries/audio/src/AudioRingBuffer.h index b448f93cee..a280be0a7c 100644 --- a/libraries/audio/src/AudioRingBuffer.h +++ b/libraries/audio/src/AudioRingBuffer.h @@ -12,17 +12,23 @@ #include #include +#include #include "AgentData.h" const int STREAM_IDENTIFIER_NUM_BYTES = 8; +const char INJECT_AUDIO_AT_POINT_COMMAND = 'P'; +const char INJECT_AUDIO_AT_CUBE_COMMAND = 'C'; + class AudioRingBuffer : public AgentData { public: AudioRingBuffer(int ringSamples, int bufferSamples); ~AudioRingBuffer(); int parseData(unsigned char* sourceBuffer, int numBytes); + + float getRadius() const { return _radius; } int16_t* getNextOutput() const { return _nextOutput; } void setNextOutput(int16_t* nextOutput) { _nextOutput = nextOutput; } @@ -39,8 +45,9 @@ public: void setShouldBeAddedToMix(bool shouldBeAddedToMix) { _shouldBeAddedToMix = shouldBeAddedToMix; } const glm::vec3& getPosition() const { return _position; } + const glm::quat& getOrientation() const { return _orientation; } float getAttenuationRatio() const { return _attenuationRatio; } - float getBearing() const { return _bearing; } + bool shouldLoopbackForAgent() const { return _shouldLoopbackForAgent; } const unsigned char* getStreamIdentifier() const { return _streamIdentifier; } @@ -53,8 +60,9 @@ private: int _ringBufferLengthSamples; int _bufferLengthSamples; glm::vec3 _position; + glm::quat _orientation; + float _radius; float _attenuationRatio; - float _bearing; int16_t* _nextOutput; int16_t* _endOfLastWrite; int16_t* _buffer; diff --git a/libraries/shared/src/AgentList.cpp b/libraries/shared/src/AgentList.cpp index 2b28ac620d..51ef88794b 100644 --- a/libraries/shared/src/AgentList.cpp +++ b/libraries/shared/src/AgentList.cpp @@ -40,7 +40,7 @@ bool pingUnknownAgentThreadStopFlag = false; AgentList* AgentList::_sharedInstance = NULL; AgentList* AgentList::createInstance(char ownerType, unsigned int socketListenPort) { - if (_sharedInstance == NULL) { + if (!_sharedInstance) { _sharedInstance = new AgentList(ownerType, socketListenPort); } else { printLog("AgentList createInstance called with existing instance.\n"); @@ -50,7 +50,7 @@ AgentList* AgentList::createInstance(char ownerType, unsigned int socketListenPo } AgentList* AgentList::getInstance() { - if (_sharedInstance == NULL) { + if (!_sharedInstance) { printLog("AgentList getInstance called before call to createInstance. Returning NULL pointer.\n"); } @@ -150,14 +150,12 @@ int AgentList::updateAgentWithData(sockaddr *senderAddress, unsigned char *packe int AgentList::updateAgentWithData(Agent *agent, unsigned char *packetData, int dataBytes) { agent->setLastHeardMicrostamp(usecTimestampNow()); - if (agent->getActiveSocket() != NULL) { + if (agent->getActiveSocket()) { agent->recordBytesReceived(dataBytes); } - if (agent->getLinkedData() == NULL) { - if (linkedDataCreateCallback != NULL) { - linkedDataCreateCallback(agent); - } + if (!agent->getLinkedData() && linkedDataCreateCallback) { + linkedDataCreateCallback(agent); } return agent->getLinkedData()->parseData(packetData, dataBytes); @@ -165,7 +163,7 @@ int AgentList::updateAgentWithData(Agent *agent, unsigned char *packetData, int Agent* AgentList::agentWithAddress(sockaddr *senderAddress) { for(AgentList::iterator agent = begin(); agent != end(); agent++) { - if (agent->getActiveSocket() != NULL && socketMatch(agent->getActiveSocket(), senderAddress)) { + if (agent->getActiveSocket() && socketMatch(agent->getActiveSocket(), senderAddress)) { return &(*agent); } } @@ -216,7 +214,7 @@ int AgentList::processDomainServerList(unsigned char *packetData, size_t dataByt Agent* AgentList::addOrUpdateAgent(sockaddr* publicSocket, sockaddr* localSocket, char agentType, uint16_t agentId) { AgentList::iterator agent = end(); - if (publicSocket != NULL) { + if (publicSocket) { for (agent = begin(); agent != end(); agent++) { if (agent->matches(publicSocket, localSocket, agentType)) { // we already have this agent, stop checking @@ -327,8 +325,7 @@ void *pingUnknownAgents(void *args) { for(AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) { - if (agent->getActiveSocket() == NULL - && (agent->getPublicSocket() != NULL && agent->getLocalSocket() != NULL)) { + if (!agent->getActiveSocket() && agent->getPublicSocket() && agent->getLocalSocket()) { // ping both of the sockets for the agent so we can figure out // which socket we can use agentList->getAgentSocket()->send(agent->getPublicSocket(), &PACKET_HEADER_PING, 1); diff --git a/libraries/shared/src/PacketHeaders.h b/libraries/shared/src/PacketHeaders.h index 850eced59b..ea9f5f9fcf 100644 --- a/libraries/shared/src/PacketHeaders.h +++ b/libraries/shared/src/PacketHeaders.h @@ -1,4 +1,3 @@ - // // PacketHeaders.h // hifi