diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index e00d8eb44d..9131c99c6d 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -141,11 +141,6 @@ int AudioMixer::addStreamToMixForListeningNodeWithStream(AudioMixerClientData* l return 0; } - // if the stream should be muted, bail - if (shouldMute(streamToAdd->getQuietestFrameLoudness())) { - return 0; - } - float bearingRelativeAngleToSource = 0.0f; float attenuationCoefficient = 1.0f; int numSamplesDelay = 0; @@ -722,6 +717,29 @@ void AudioMixer::run() { // That's how the popped audio data will be read for mixing (but only if the pop was successful) nodeData->checkBuffersBeforeFrameSend(); + // if the stream should be muted, send mute packet + if (shouldMute(nodeData->getAvatarAudioStream()->getQuietestFrameLoudness())) { + static const int TIME_BETWEEN_MUTES = 5; // in secs + if (usecTimestampNow() - nodeData->getAvatarAudioStream()->getLastMuted() > + TIME_BETWEEN_MUTES * USECS_PER_SECOND) { + int headerSize = numBytesForPacketHeaderGivenPacketType(PacketTypeMuteEnvironment); + int packetSize = headerSize + sizeof(glm::vec3) + sizeof(float); + + // Fake data to force mute + glm::vec3 position = nodeData->getAvatarAudioStream()->getPosition(); + float radius = 1.0f; + + char* packet = (char*)malloc(packetSize); + populatePacketHeader(packet, PacketTypeMuteEnvironment); + memcpy(packet + headerSize, &position, sizeof(glm::vec3)); + memcpy(packet + headerSize + sizeof(glm::vec3), &radius, sizeof(float)); + + nodeList->writeDatagram(packet, packetSize, node); + nodeData->getAvatarAudioStream()->setLastMutedNow(); + free(packet); + } + } + if (node->getType() == NodeType::Agent && node->getActiveSocket() && nodeData->getAvatarAudioStream()) { diff --git a/assignment-client/src/audio/AvatarAudioStream.cpp b/assignment-client/src/audio/AvatarAudioStream.cpp index 90dcefa09d..cd67722a2e 100644 --- a/assignment-client/src/audio/AvatarAudioStream.cpp +++ b/assignment-client/src/audio/AvatarAudioStream.cpp @@ -14,7 +14,8 @@ #include "AvatarAudioStream.h" AvatarAudioStream::AvatarAudioStream(bool isStereo, const InboundAudioStream::Settings& settings) : - PositionalAudioStream(PositionalAudioStream::Microphone, isStereo, settings) + PositionalAudioStream(PositionalAudioStream::Microphone, isStereo, settings), + _lastMuted(usecTimestampNow()) { } diff --git a/assignment-client/src/audio/AvatarAudioStream.h b/assignment-client/src/audio/AvatarAudioStream.h index cc2ff1aca7..e1fb6dd486 100644 --- a/assignment-client/src/audio/AvatarAudioStream.h +++ b/assignment-client/src/audio/AvatarAudioStream.h @@ -19,13 +19,18 @@ class AvatarAudioStream : public PositionalAudioStream { public: AvatarAudioStream(bool isStereo, const InboundAudioStream::Settings& settings); - + + qint64 getLastMuted() const { return _lastMuted; } + void setLastMutedNow() { _lastMuted = usecTimestampNow(); } + private: // disallow copying of AvatarAudioStream objects AvatarAudioStream(const AvatarAudioStream&); AvatarAudioStream& operator= (const AvatarAudioStream&); int parseStreamProperties(PacketType type, const QByteArray& packetAfterSeqNum, int& numAudioSamples); + + qint64 _lastMuted; }; #endif // hifi_AvatarAudioStream_h diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 4a488bb296..726d1e609a 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -97,6 +97,9 @@ Audio::Audio(QObject* parent) : _muted(false), _reverb(false), _reverbOptions(&_scriptReverbOptions), + _gverb(NULL), + _iconColor(1.0f), + _iconPulseTimeReference(usecTimestampNow()), _processSpatialAudio(false), _spatialAudioStart(0), _spatialAudioFinish(0), @@ -1390,23 +1393,37 @@ void Audio::renderToolBox(int x, int y, bool boxed) { _iconBounds = QRect(x, y, MUTE_ICON_SIZE, MUTE_ICON_SIZE); if (!_muted) { glBindTexture(GL_TEXTURE_2D, _micTextureId); + _iconColor = 1.0f; } else { glBindTexture(GL_TEXTURE_2D, _muteTextureId); + + // Make muted icon pulsate + static const float PULSE_MIN = 0.4f; + static const float PULSE_MAX = 1.0f; + static const float PULSE_FREQUENCY = 1.0f; // in Hz + qint64 now = usecTimestampNow(); + if (now - _iconPulseTimeReference > USECS_PER_SECOND) { + // Prevents t from getting too big, which would diminish glm::cos precision + _iconPulseTimeReference = now - ((now - _iconPulseTimeReference) % USECS_PER_SECOND); + } + float t = (float)(now - _iconPulseTimeReference) / (float)USECS_PER_SECOND; + float pulseFactor = (glm::cos(t * PULSE_FREQUENCY * 2.0f * PI) + 1.0f) / 2.0f; + _iconColor = PULSE_MIN + (PULSE_MAX - PULSE_MIN) * pulseFactor; } - glColor3f(1,1,1); + glColor3f(_iconColor, _iconColor, _iconColor); glBegin(GL_QUADS); - glTexCoord2f(1, 1); + glTexCoord2f(1.0f, 1.0f); glVertex2f(_iconBounds.left(), _iconBounds.top()); - glTexCoord2f(0, 1); + glTexCoord2f(0.0f, 1.0f); glVertex2f(_iconBounds.right(), _iconBounds.top()); - glTexCoord2f(0, 0); + glTexCoord2f(0.0f, 0.0f); glVertex2f(_iconBounds.right(), _iconBounds.bottom()); - glTexCoord2f(1, 0); + glTexCoord2f(1.0f, 0.0f); glVertex2f(_iconBounds.left(), _iconBounds.bottom()); glEnd(); diff --git a/interface/src/Audio.h b/interface/src/Audio.h index 6de7cf8d91..ecbef026c4 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -248,11 +248,13 @@ private: AudioEffectOptions _scriptReverbOptions; AudioEffectOptions _zoneReverbOptions; AudioEffectOptions* _reverbOptions; - ty_gverb *_gverb; + ty_gverb* _gverb; GLuint _micTextureId; GLuint _muteTextureId; GLuint _boxTextureId; QRect _iconBounds; + float _iconColor; + qint64 _iconPulseTimeReference; /// Audio callback in class context. inline void performIO(int16_t* inputLeft, int16_t* outputLeft, int16_t* outputRight);