From 6fc5c74c0b6a0d68f014aa5d86caea48cb1ee40e Mon Sep 17 00:00:00 2001 From: wangyix Date: Mon, 28 Jul 2014 13:08:53 -0700 Subject: [PATCH] renamed ringbuffer variables to audiostream --- assignment-client/src/Agent.cpp | 8 +- assignment-client/src/Agent.h | 4 +- assignment-client/src/audio/AudioMixer.cpp | 89 +++++++++--------- assignment-client/src/audio/AudioMixer.h | 6 +- .../src/audio/AudioMixerClientData.cpp | 90 +++++++++---------- .../src/audio/AudioMixerClientData.h | 6 +- .../src/audio/AvatarAudioStream.h | 6 +- interface/src/Application.cpp | 10 +-- interface/src/Audio.cpp | 78 ++++++++-------- interface/src/Audio.h | 18 ++-- libraries/audio/src/AudioStreamStats.h | 28 +++--- libraries/audio/src/InboundAudioStream.cpp | 19 ++-- libraries/audio/src/InboundAudioStream.h | 11 ++- .../audio/src/InboundMixedAudioStream.cpp | 17 ---- libraries/audio/src/InboundMixedAudioStream.h | 14 --- libraries/audio/src/InjectedAudioStream.h | 6 +- libraries/audio/src/MixedAudioStream.cpp | 17 ++++ libraries/audio/src/MixedAudioStream.h | 29 ++++++ libraries/audio/src/PositionalAudioStream.h | 6 +- 19 files changed, 237 insertions(+), 225 deletions(-) delete mode 100644 libraries/audio/src/InboundMixedAudioStream.cpp delete mode 100644 libraries/audio/src/InboundMixedAudioStream.h create mode 100644 libraries/audio/src/MixedAudioStream.cpp create mode 100644 libraries/audio/src/MixedAudioStream.h diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index c82f35ff7f..d4da989198 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -36,7 +36,7 @@ Agent::Agent(const QByteArray& packet) : _voxelEditSender(), _particleEditSender(), _modelEditSender(), - _receivedAudioBuffer(NETWORK_BUFFER_LENGTH_SAMPLES_STEREO, 1, false), + _receivedAudioStream(NETWORK_BUFFER_LENGTH_SAMPLES_STEREO, 1, false), _avatarHashMap() { // be the parent of the script engine so it gets moved when we do @@ -148,11 +148,11 @@ void Agent::readPendingDatagrams() { } else if (datagramPacketType == PacketTypeMixedAudio) { - _receivedAudioBuffer.parseData(receivedPacket); + _receivedAudioStream.parseData(receivedPacket); - _lastReceivedAudioLoudness = _receivedAudioBuffer.getNextOutputFrameLoudness(); + _lastReceivedAudioLoudness = _receivedAudioStream.getNextOutputFrameLoudness(); - _receivedAudioBuffer.clearBuffer(); + _receivedAudioStream.clearBuffer(); // let this continue through to the NodeList so it updates last heard timestamp // for the sending audio mixer diff --git a/assignment-client/src/Agent.h b/assignment-client/src/Agent.h index b713062840..cd2476fe02 100644 --- a/assignment-client/src/Agent.h +++ b/assignment-client/src/Agent.h @@ -30,7 +30,7 @@ #include #include -#include "InboundMixedAudioStream.h" +#include "MixedAudioStream.h" class Agent : public ThreadedAssignment { @@ -71,7 +71,7 @@ private: VoxelTreeHeadlessViewer _voxelViewer; ModelTreeHeadlessViewer _modelViewer; - InboundMixedAudioStream _receivedAudioBuffer; + MixedAudioStream _receivedAudioStream; float _lastReceivedAudioLoudness; AvatarHashMap _avatarHashMap; diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 48789c6415..d3ec39ace1 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -61,7 +61,7 @@ const float LOUDNESS_TO_DISTANCE_RATIO = 0.00001f; const QString AUDIO_MIXER_LOGGING_TARGET_NAME = "audio-mixer"; -void attachNewBufferToNode(Node *newNode) { +void attachNewNodeDataToNode(Node *newNode) { if (!newNode->getLinkedData()) { newNode->setLinkedData(new AudioMixerClientData()); } @@ -93,19 +93,19 @@ const float ATTENUATION_BEGINS_AT_DISTANCE = 1.0f; const float ATTENUATION_AMOUNT_PER_DOUBLING_IN_DISTANCE = 0.18f; const float ATTENUATION_EPSILON_DISTANCE = 0.1f; -void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioStream* bufferToAdd, - AvatarAudioStream* listeningNodeBuffer) { +void AudioMixer::addStreamToMixForListeningNodeWithStream(PositionalAudioStream* streamToAdd, + AvatarAudioStream* listeningNodeStream) { float bearingRelativeAngleToSource = 0.0f; float attenuationCoefficient = 1.0f; int numSamplesDelay = 0; float weakChannelAmplitudeRatio = 1.0f; - bool shouldAttenuate = (bufferToAdd != listeningNodeBuffer); + bool shouldAttenuate = (streamToAdd != listeningNodeStream); if (shouldAttenuate) { - // if the two buffer pointers do not match then these are different buffers - glm::vec3 relativePosition = bufferToAdd->getPosition() - listeningNodeBuffer->getPosition(); + // if the two stream pointers do not match then these are different streams + glm::vec3 relativePosition = streamToAdd->getPosition() - listeningNodeStream->getPosition(); float distanceBetween = glm::length(relativePosition); @@ -113,7 +113,7 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioStream* distanceBetween = EPSILON; } - if (bufferToAdd->getNextOutputTrailingLoudness() / distanceBetween <= _minAudibilityThreshold) { + if (streamToAdd->getNextOutputTrailingLoudness() / distanceBetween <= _minAudibilityThreshold) { // according to mixer performance we have decided this does not get to be mixed in // bail out return; @@ -121,24 +121,24 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioStream* ++_sumMixes; - if (bufferToAdd->getListenerUnattenuatedZone()) { - shouldAttenuate = !bufferToAdd->getListenerUnattenuatedZone()->contains(listeningNodeBuffer->getPosition()); + if (streamToAdd->getListenerUnattenuatedZone()) { + shouldAttenuate = !streamToAdd->getListenerUnattenuatedZone()->contains(listeningNodeStream->getPosition()); } - if (bufferToAdd->getType() == PositionalAudioStream::Injector) { - attenuationCoefficient *= reinterpret_cast(bufferToAdd)->getAttenuationRatio(); + if (streamToAdd->getType() == PositionalAudioStream::Injector) { + attenuationCoefficient *= reinterpret_cast(streamToAdd)->getAttenuationRatio(); } shouldAttenuate = shouldAttenuate && distanceBetween > ATTENUATION_EPSILON_DISTANCE; if (shouldAttenuate) { - glm::quat inverseOrientation = glm::inverse(listeningNodeBuffer->getOrientation()); + glm::quat inverseOrientation = glm::inverse(listeningNodeStream->getOrientation()); float distanceSquareToSource = glm::dot(relativePosition, relativePosition); float radius = 0.0f; - if (bufferToAdd->getType() == PositionalAudioStream::Injector) { - radius = reinterpret_cast(bufferToAdd)->getRadius(); + if (streamToAdd->getType() == PositionalAudioStream::Injector) { + radius = reinterpret_cast(streamToAdd)->getRadius(); } if (radius == 0 || (distanceSquareToSource > radius * radius)) { @@ -154,7 +154,7 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioStream* } else { // calculate the angle delivery for off-axis attenuation - glm::vec3 rotatedListenerPosition = glm::inverse(bufferToAdd->getOrientation()) * relativePosition; + glm::vec3 rotatedListenerPosition = glm::inverse(streamToAdd->getOrientation()) * relativePosition; float angleOfDelivery = glm::angle(glm::vec3(0.0f, 0.0f, -1.0f), glm::normalize(rotatedListenerPosition)); @@ -203,16 +203,16 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioStream* } } - AudioRingBuffer::ConstIterator bufferPopOutput = bufferToAdd->getLastPopOutput(); + AudioRingBuffer::ConstIterator streamPopOutput = streamToAdd->getLastPopOutput(); - if (!bufferToAdd->isStereo() && shouldAttenuate) { - // this is a mono buffer, which means it gets full attenuation and spatialization + if (!streamToAdd->isStereo() && shouldAttenuate) { + // this is a mono stream, 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 int delayedChannelOffset = (bearingRelativeAngleToSource > 0.0f) ? 1 : 0; int goodChannelOffset = delayedChannelOffset == 0 ? 1 : 0; - int16_t correctBufferSample[2], delayBufferSample[2]; + int16_t correctStreamSample[2], delayStreamSample[2]; int delayedChannelIndex = 0; const int SINGLE_STEREO_OFFSET = 2; @@ -220,52 +220,51 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioStream* for (int s = 0; s < NETWORK_BUFFER_LENGTH_SAMPLES_STEREO; s += 4) { // setup the int16_t variables for the two sample sets - correctBufferSample[0] = bufferPopOutput[s / 2] * attenuationCoefficient; - correctBufferSample[1] = bufferPopOutput[(s / 2) + 1] * attenuationCoefficient; + correctStreamSample[0] = streamPopOutput[s / 2] * attenuationCoefficient; + correctStreamSample[1] = streamPopOutput[(s / 2) + 1] * attenuationCoefficient; delayedChannelIndex = s + (numSamplesDelay * 2) + delayedChannelOffset; - delayBufferSample[0] = correctBufferSample[0] * weakChannelAmplitudeRatio; - delayBufferSample[1] = correctBufferSample[1] * weakChannelAmplitudeRatio; + delayStreamSample[0] = correctStreamSample[0] * weakChannelAmplitudeRatio; + delayStreamSample[1] = correctStreamSample[1] * weakChannelAmplitudeRatio; - _clientSamples[s + goodChannelOffset] += correctBufferSample[0]; - _clientSamples[s + goodChannelOffset + SINGLE_STEREO_OFFSET] += correctBufferSample[1]; - _clientSamples[delayedChannelIndex] += delayBufferSample[0]; - _clientSamples[delayedChannelIndex + SINGLE_STEREO_OFFSET] += delayBufferSample[1]; + _clientSamples[s + goodChannelOffset] += correctStreamSample[0]; + _clientSamples[s + goodChannelOffset + SINGLE_STEREO_OFFSET] += correctStreamSample[1]; + _clientSamples[delayedChannelIndex] += delayStreamSample[0]; + _clientSamples[delayedChannelIndex + SINGLE_STEREO_OFFSET] += delayStreamSample[1]; } if (numSamplesDelay > 0) { - // if there was a sample delay for this buffer, we need to pull samples prior to the nextOutput + // if there was a sample delay for this stream, we need to pull samples prior to the popped output // to stick at the beginning float attenuationAndWeakChannelRatio = attenuationCoefficient * weakChannelAmplitudeRatio; - AudioRingBuffer::ConstIterator delayBufferPopOutput = bufferPopOutput - numSamplesDelay; + AudioRingBuffer::ConstIterator delayStreamPopOutput = streamPopOutput - numSamplesDelay; - // TODO: delayBufferPopOutput may be inside the last frame written if the ringbuffer is completely full + // TODO: delayStreamPopOutput may be inside the last frame written if the ringbuffer is completely full // maybe make AudioRingBuffer have 1 extra frame in its buffer for (int i = 0; i < numSamplesDelay; i++) { int parentIndex = i * 2; - _clientSamples[parentIndex + delayedChannelOffset] += *delayBufferPopOutput * attenuationAndWeakChannelRatio; - ++delayBufferPopOutput; + _clientSamples[parentIndex + delayedChannelOffset] += *delayStreamPopOutput * attenuationAndWeakChannelRatio; + ++delayStreamPopOutput; } } } else { - - int stereoDivider = bufferToAdd->isStereo() ? 1 : 2; + int stereoDivider = streamToAdd->isStereo() ? 1 : 2; if (!shouldAttenuate) { attenuationCoefficient = 1.0f; } for (int s = 0; s < NETWORK_BUFFER_LENGTH_SAMPLES_STEREO; s++) { - _clientSamples[s] = glm::clamp(_clientSamples[s] + (int)(bufferPopOutput[s / stereoDivider] * attenuationCoefficient), + _clientSamples[s] = glm::clamp(_clientSamples[s] + (int)(streamPopOutput[s / stereoDivider] * attenuationCoefficient), MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); } } } void AudioMixer::prepareMixForListeningNode(Node* node) { - AvatarAudioStream* nodeRingBuffer = ((AudioMixerClientData*) node->getLinkedData())->getAvatarAudioRingBuffer(); + AvatarAudioStream* nodeAudioStream = ((AudioMixerClientData*) node->getLinkedData())->getAvatarAudioStream(); // zero out the client mix for this node memset(_clientSamples, 0, NETWORK_BUFFER_LENGTH_BYTES_STEREO); @@ -278,16 +277,16 @@ void AudioMixer::prepareMixForListeningNode(Node* node) { // enumerate the ARBs attached to the otherNode and add all that should be added to mix - const QHash& otherNodeRingBuffers = otherNodeClientData->getRingBuffers(); + const QHash& otherNodeAudioStreams = otherNodeClientData->getAudioStreams(); QHash::ConstIterator i; - for (i = otherNodeRingBuffers.begin(); i != otherNodeRingBuffers.constEnd(); i++) { - PositionalAudioStream* otherNodeBuffer = i.value(); + for (i = otherNodeAudioStreams.begin(); i != otherNodeAudioStreams.constEnd(); i++) { + PositionalAudioStream* otherNodeStream = i.value(); - if ((*otherNode != *node || otherNodeBuffer->shouldLoopbackForNode()) - && otherNodeBuffer->lastPopSucceeded() - && otherNodeBuffer->getNextOutputTrailingLoudness() > 0.0f) { + if ((*otherNode != *node || otherNodeStream->shouldLoopbackForNode()) + && otherNodeStream->lastPopSucceeded() + && otherNodeStream->getNextOutputTrailingLoudness() > 0.0f) { - addBufferToMixForListeningNodeWithBuffer(otherNodeBuffer, nodeRingBuffer); + addStreamToMixForListeningNodeWithStream(otherNodeStream, nodeAudioStream); } } } @@ -392,7 +391,7 @@ void AudioMixer::run() { nodeList->addNodeTypeToInterestSet(NodeType::Agent); - nodeList->linkedDataCreateCallback = attachNewBufferToNode; + nodeList->linkedDataCreateCallback = attachNewNodeDataToNode; // setup a NetworkAccessManager to ask the domain-server for our settings NetworkAccessManager& networkManager = NetworkAccessManager::getInstance(); @@ -554,7 +553,7 @@ void AudioMixer::run() { nodeData->audioStreamsPopFrameForMixing(); if (node->getType() == NodeType::Agent - && ((AudioMixerClientData*)node->getLinkedData())->getAvatarAudioRingBuffer()) { + && ((AudioMixerClientData*)node->getLinkedData())->getAvatarAudioStream()) { prepareMixForListeningNode(node.data()); diff --git a/assignment-client/src/audio/AudioMixer.h b/assignment-client/src/audio/AudioMixer.h index 73b3e0ff94..bfdb49f393 100644 --- a/assignment-client/src/audio/AudioMixer.h +++ b/assignment-client/src/audio/AudioMixer.h @@ -40,9 +40,9 @@ public slots: static bool getUseDynamicJitterBuffers() { return _useDynamicJitterBuffers; } private: - /// adds one buffer to the mix for a listening node - void addBufferToMixForListeningNodeWithBuffer(PositionalAudioStream* bufferToAdd, - AvatarAudioStream* listeningNodeBuffer); + /// adds one stream to the mix for a listening node + void addStreamToMixForListeningNodeWithStream(PositionalAudioStream* streamToAdd, + AvatarAudioStream* listeningNodeStream); /// prepares and sends a mix to one Node void prepareMixForListeningNode(Node* node); diff --git a/assignment-client/src/audio/AudioMixerClientData.cpp b/assignment-client/src/audio/AudioMixerClientData.cpp index d436870a71..17e46f3692 100644 --- a/assignment-client/src/audio/AudioMixerClientData.cpp +++ b/assignment-client/src/audio/AudioMixerClientData.cpp @@ -21,22 +21,22 @@ AudioMixerClientData::AudioMixerClientData() : - _ringBuffers(), + _audioStreams(), _outgoingMixedAudioSequenceNumber(0) { } AudioMixerClientData::~AudioMixerClientData() { QHash::ConstIterator i; - for (i = _ringBuffers.constBegin(); i != _ringBuffers.constEnd(); i++) { + for (i = _audioStreams.constBegin(); i != _audioStreams.constEnd(); i++) { // delete this attached InboundAudioStream delete i.value(); } } -AvatarAudioStream* AudioMixerClientData::getAvatarAudioRingBuffer() const { - if (_ringBuffers.contains(QUuid())) { - return (AvatarAudioStream*)_ringBuffers.value(QUuid()); +AvatarAudioStream* AudioMixerClientData::getAvatarAudioStream() const { + if (_audioStreams.contains(QUuid())) { + return (AvatarAudioStream*)_audioStreams.value(QUuid()); } // no mic stream found - return NULL return NULL; @@ -65,7 +65,7 @@ int AudioMixerClientData::parseData(const QByteArray& packet) { || packetType == PacketTypeSilentAudioFrame) { QUuid nullUUID = QUuid(); - if (!_ringBuffers.contains(nullUUID)) { + if (!_audioStreams.contains(nullUUID)) { // we don't have a mic stream yet, so add it // read the channel flag to see if our stream is stereo or not @@ -73,10 +73,10 @@ int AudioMixerClientData::parseData(const QByteArray& packet) { quint8 channelFlag = *(reinterpret_cast(channelFlagAt)); bool isStereo = channelFlag == 1; - _ringBuffers.insert(nullUUID, + _audioStreams.insert(nullUUID, matchingStream = new AvatarAudioStream(isStereo, AudioMixer::getUseDynamicJitterBuffers())); } else { - matchingStream = _ringBuffers.value(nullUUID); + matchingStream = _audioStreams.value(nullUUID); } } else if (packetType == PacketTypeInjectAudio) { // this is injected audio @@ -85,11 +85,11 @@ int AudioMixerClientData::parseData(const QByteArray& packet) { int bytesBeforeStreamIdentifier = numBytesForPacketHeader(packet) + sizeof(quint16); QUuid streamIdentifier = QUuid::fromRfc4122(packet.mid(bytesBeforeStreamIdentifier, NUM_BYTES_RFC4122_UUID)); - if (!_ringBuffers.contains(streamIdentifier)) { - _ringBuffers.insert(streamIdentifier, + if (!_audioStreams.contains(streamIdentifier)) { + _audioStreams.insert(streamIdentifier, matchingStream = new InjectedAudioStream(streamIdentifier, AudioMixer::getUseDynamicJitterBuffers())); } else { - matchingStream = _ringBuffers.value(streamIdentifier); + matchingStream = _audioStreams.value(streamIdentifier); } } @@ -100,7 +100,7 @@ int AudioMixerClientData::parseData(const QByteArray& packet) { void AudioMixerClientData::audioStreamsPopFrameForMixing() { QHash::ConstIterator i; - for (i = _ringBuffers.constBegin(); i != _ringBuffers.constEnd(); i++) { + for (i = _audioStreams.constBegin(); i != _audioStreams.constEnd(); i++) { i.value()->popFrames(1); } } @@ -109,11 +109,11 @@ void AudioMixerClientData::removeDeadInjectedStreams() { const int INJECTOR_CONSECUTIVE_NOT_MIXED_AFTER_STARTED_THRESHOLD = 100; - // we have this second threshold in case the injected audio is so short that the ringbuffer + // we have this second threshold in case the injected audio is so short that the injected stream // never even reaches its desired size, which means it will never start. const int INJECTOR_CONSECUTIVE_NOT_MIXED_THRESHOLD = 1000; - QHash::Iterator i = _ringBuffers.begin(), end = _ringBuffers.end(); + QHash::Iterator i = _audioStreams.begin(), end = _audioStreams.end(); while (i != end) { PositionalAudioStream* audioStream = i.value(); if (audioStream->getType() == PositionalAudioStream::Injector && audioStream->isStarved()) { @@ -121,7 +121,7 @@ void AudioMixerClientData::removeDeadInjectedStreams() { : INJECTOR_CONSECUTIVE_NOT_MIXED_THRESHOLD; if (audioStream->getConsecutiveNotMixedCount() >= notMixedThreshold) { delete audioStream; - i = _ringBuffers.erase(i); + i = _audioStreams.erase(i); continue; } } @@ -150,9 +150,9 @@ void AudioMixerClientData::sendAudioStreamStatsPackets(const SharedNodePointer& // calculate how many stream stat structs we can fit in each packet const int numStreamStatsRoomFor = (MAX_PACKET_SIZE - numBytesPacketHeader - sizeof(quint8) - sizeof(quint16)) / sizeof(AudioStreamStats); - // pack and send stream stats packets until all ring buffers' stats are sent - int numStreamStatsRemaining = _ringBuffers.size(); - QHash::ConstIterator ringBuffersIterator = _ringBuffers.constBegin(); + // pack and send stream stats packets until all audio streams' stats are sent + int numStreamStatsRemaining = _audioStreams.size(); + QHash::ConstIterator audioStreamsIterator = _audioStreams.constBegin(); while (numStreamStatsRemaining > 0) { char* dataAt = headerEndAt; @@ -169,11 +169,11 @@ void AudioMixerClientData::sendAudioStreamStatsPackets(const SharedNodePointer& // pack the calculated number of stream stats for (int i = 0; i < numStreamStatsToPack; i++) { - AudioStreamStats streamStats = ringBuffersIterator.value()->updateSeqHistoryAndGetAudioStreamStats(); + AudioStreamStats streamStats = audioStreamsIterator.value()->updateSeqHistoryAndGetAudioStreamStats(); memcpy(dataAt, &streamStats, sizeof(AudioStreamStats)); dataAt += sizeof(AudioStreamStats); - ringBuffersIterator++; + audioStreamsIterator++; } numStreamStatsRemaining -= numStreamStatsToPack; @@ -185,12 +185,12 @@ void AudioMixerClientData::sendAudioStreamStatsPackets(const SharedNodePointer& QString AudioMixerClientData::getAudioStreamStatsString() const { QString result; AudioStreamStats streamStats = _downstreamAudioStreamStats; - result += "DOWNSTREAM.desired:" + QString::number(streamStats._ringBufferDesiredJitterBufferFrames) - + " available_avg_10s:" + QString::number(streamStats._ringBufferFramesAvailableAverage) - + " available:" + QString::number(streamStats._ringBufferFramesAvailable) - + " starves:" + QString::number(streamStats._ringBufferStarveCount) - + " not_mixed:" + QString::number(streamStats._ringBufferConsecutiveNotMixedCount) - + " overflows:" + QString::number(streamStats._ringBufferOverflowCount) + result += "DOWNSTREAM.desired:" + QString::number(streamStats._desiredJitterBufferFrames) + + " available_avg_10s:" + QString::number(streamStats._framesAvailableAverage) + + " available:" + QString::number(streamStats._framesAvailable) + + " starves:" + QString::number(streamStats._starveCount) + + " not_mixed:" + QString::number(streamStats._consecutiveNotMixedCount) + + " overflows:" + QString::number(streamStats._overflowCount) + " silents_dropped: ?" + " lost%:" + QString::number(streamStats._packetStreamStats.getLostRate() * 100.0f, 'f', 2) + " lost%_30s:" + QString::number(streamStats._packetStreamWindowStats.getLostRate() * 100.0f, 'f', 2) @@ -201,17 +201,17 @@ QString AudioMixerClientData::getAudioStreamStatsString() const { + " max_gap_30s:" + formatUsecTime(streamStats._timeGapWindowMax) + " avg_gap_30s:" + formatUsecTime(streamStats._timeGapWindowAverage); - AvatarAudioStream* avatarRingBuffer = getAvatarAudioRingBuffer(); - if (avatarRingBuffer) { - AudioStreamStats streamStats = avatarRingBuffer->getAudioStreamStats(); - result += " UPSTREAM.mic.desired:" + QString::number(streamStats._ringBufferDesiredJitterBufferFrames) - + " desired_calc:" + QString::number(avatarRingBuffer->getCalculatedJitterBufferFrames()) - + " available_avg_10s:" + QString::number(streamStats._ringBufferFramesAvailableAverage) - + " available:" + QString::number(streamStats._ringBufferFramesAvailable) - + " starves:" + QString::number(streamStats._ringBufferStarveCount) - + " not_mixed:" + QString::number(streamStats._ringBufferConsecutiveNotMixedCount) - + " overflows:" + QString::number(streamStats._ringBufferOverflowCount) - + " silents_dropped:" + QString::number(streamStats._ringBufferSilentFramesDropped) + AvatarAudioStream* avatarAudioStream = getAvatarAudioStream(); + if (avatarAudioStream) { + AudioStreamStats streamStats = avatarAudioStream->getAudioStreamStats(); + result += " UPSTREAM.mic.desired:" + QString::number(streamStats._desiredJitterBufferFrames) + + " desired_calc:" + QString::number(avatarAudioStream->getCalculatedJitterBufferFrames()) + + " available_avg_10s:" + QString::number(streamStats._framesAvailableAverage) + + " available:" + QString::number(streamStats._framesAvailable) + + " starves:" + QString::number(streamStats._starveCount) + + " not_mixed:" + QString::number(streamStats._consecutiveNotMixedCount) + + " overflows:" + QString::number(streamStats._overflowCount) + + " silents_dropped:" + QString::number(streamStats._silentFramesDropped) + " lost%:" + QString::number(streamStats._packetStreamStats.getLostRate() * 100.0f, 'f', 2) + " lost%_30s:" + QString::number(streamStats._packetStreamWindowStats.getLostRate() * 100.0f, 'f', 2) + " min_gap:" + formatUsecTime(streamStats._timeGapMin) @@ -225,17 +225,17 @@ QString AudioMixerClientData::getAudioStreamStatsString() const { } QHash::ConstIterator i; - for (i = _ringBuffers.constBegin(); i != _ringBuffers.constEnd(); i++) { + for (i = _audioStreams.constBegin(); i != _audioStreams.constEnd(); i++) { if (i.value()->getType() == PositionalAudioStream::Injector) { AudioStreamStats streamStats = i.value()->getAudioStreamStats(); - result += " UPSTREAM.inj.desired:" + QString::number(streamStats._ringBufferDesiredJitterBufferFrames) + result += " UPSTREAM.inj.desired:" + QString::number(streamStats._desiredJitterBufferFrames) + " desired_calc:" + QString::number(i.value()->getCalculatedJitterBufferFrames()) - + " available_avg_10s:" + QString::number(streamStats._ringBufferFramesAvailableAverage) - + " available:" + QString::number(streamStats._ringBufferFramesAvailable) - + " starves:" + QString::number(streamStats._ringBufferStarveCount) - + " not_mixed:" + QString::number(streamStats._ringBufferConsecutiveNotMixedCount) - + " overflows:" + QString::number(streamStats._ringBufferOverflowCount) - + " silents_dropped:" + QString::number(streamStats._ringBufferSilentFramesDropped) + + " available_avg_10s:" + QString::number(streamStats._framesAvailableAverage) + + " available:" + QString::number(streamStats._framesAvailable) + + " starves:" + QString::number(streamStats._starveCount) + + " not_mixed:" + QString::number(streamStats._consecutiveNotMixedCount) + + " overflows:" + QString::number(streamStats._overflowCount) + + " silents_dropped:" + QString::number(streamStats._silentFramesDropped) + " lost%:" + QString::number(streamStats._packetStreamStats.getLostRate() * 100.0f, 'f', 2) + " lost%_30s:" + QString::number(streamStats._packetStreamWindowStats.getLostRate() * 100.0f, 'f', 2) + " min_gap:" + formatUsecTime(streamStats._timeGapMin) diff --git a/assignment-client/src/audio/AudioMixerClientData.h b/assignment-client/src/audio/AudioMixerClientData.h index 55fb1355e5..287f4f7b65 100644 --- a/assignment-client/src/audio/AudioMixerClientData.h +++ b/assignment-client/src/audio/AudioMixerClientData.h @@ -22,8 +22,8 @@ public: AudioMixerClientData(); ~AudioMixerClientData(); - const QHash& getRingBuffers() const { return _ringBuffers; } - AvatarAudioStream* getAvatarAudioRingBuffer() const; + const QHash& getAudioStreams() const { return _audioStreams; } + AvatarAudioStream* getAvatarAudioStream() const; int parseData(const QByteArray& packet); @@ -39,7 +39,7 @@ public: quint16 getOutgoingSequenceNumber() const { return _outgoingMixedAudioSequenceNumber; } private: - QHash _ringBuffers; // mic stream stored under key of null UUID + QHash _audioStreams; // mic stream stored under key of null UUID quint16 _outgoingMixedAudioSequenceNumber; diff --git a/assignment-client/src/audio/AvatarAudioStream.h b/assignment-client/src/audio/AvatarAudioStream.h index 2b5f921299..de7920c278 100644 --- a/assignment-client/src/audio/AvatarAudioStream.h +++ b/assignment-client/src/audio/AvatarAudioStream.h @@ -9,8 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_AvatarAudioRingBuffer_h -#define hifi_AvatarAudioRingBuffer_h +#ifndef hifi_AvatarAudioStream_h +#define hifi_AvatarAudioStream_h #include @@ -29,4 +29,4 @@ private: int parseAudioData(PacketType type, const QByteArray& packetAfterStreamProperties, int numAudioSamples); }; -#endif // hifi_AvatarAudioRingBuffer_h +#endif // hifi_AvatarAudioStream_h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index cab8e6691f..3ef4334fa5 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -103,10 +103,6 @@ const int IDLE_SIMULATE_MSECS = 16; // How often should call simul // in the idle loop? (60 FPS is default) static QTimer* idleTimer = NULL; -const int STARTUP_JITTER_SAMPLES = NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL / 2; - // Startup optimistically with small jitter buffer that - // will start playback on the second received audio packet. - const QString CHECK_VERSION_URL = "https://highfidelity.io/latestVersion.xml"; const QString SKIP_FILENAME = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/hifi.skipversion"; @@ -162,7 +158,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _touchAvgY(0.0f), _isTouchPressed(false), _mousePressed(false), - _audio(STARTUP_JITTER_SAMPLES), + _audio(), _enableProcessVoxelsThread(true), _octreeProcessor(), _voxelHideShowThread(&_voxels), @@ -1712,8 +1708,8 @@ void Application::init() { _lastTimeUpdated.start(); Menu::getInstance()->loadSettings(); - if (Menu::getInstance()->getAudioJitterBufferSamples() != 0) { - _audio.setJitterBufferSamples(Menu::getInstance()->getAudioJitterBufferSamples()); + if (Menu::getInstance()->getAudioJitterBufferFrames() != 0) { + _audio.overrideDesiredJitterBufferFramesTo(Menu::getInstance()->getAudioJitterBufferFrames()); } qDebug("Loaded settings"); diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 0ec74de0b1..e830e5f6d4 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -54,7 +54,7 @@ static const int FRAMES_AVAILABLE_STATS_WINDOW_SECONDS = 10; static const int MUTE_ICON_SIZE = 24; -Audio::Audio(int16_t initialJitterBufferSamples, QObject* parent) : +Audio::Audio(QObject* parent) : AbstractAudioInterface(parent), _audioInput(NULL), _desiredInputFormat(), @@ -76,14 +76,12 @@ Audio::Audio(int16_t initialJitterBufferSamples, QObject* parent) : // this delay will slowly add up and the longer someone runs, they more delayed their audio will be. _inputRingBuffer(0), #ifdef _WIN32 - _ringBuffer(NETWORK_BUFFER_LENGTH_SAMPLES_STEREO, 100, true, true), + _receivedAudioStream(NETWORK_BUFFER_LENGTH_SAMPLES_STEREO, 100, true, true), #else - _ringBuffer(NETWORK_BUFFER_LENGTH_SAMPLES_STEREO, 10, true, true), // DO NOT CHANGE THIS UNLESS YOU SOLVE THE AUDIO DEVICE DRIFT PROBLEM!!! + _receivedAudioStream(NETWORK_BUFFER_LENGTH_SAMPLES_STEREO, 10, true, true), // DO NOT CHANGE THIS UNLESS YOU SOLVE THE AUDIO DEVICE DRIFT PROBLEM!!! #endif _isStereoInput(false), _averagedLatency(0.0), - _measuredJitter(0), - _jitterBufferSamples(initialJitterBufferSamples), _lastInputLoudness(0), _timeSinceLastClip(-1.0), _dcOffset(0), @@ -132,13 +130,13 @@ void Audio::init(QGLWidget *parent) { } void Audio::reset() { - _ringBuffer.reset(); + _receivedAudioStream.reset(); resetStats(); } void Audio::resetStats() { - _ringBuffer.resetStats(); + _receivedAudioStream.resetStats(); _audioMixerAvatarStreamAudioStats = AudioStreamStats(); _audioMixerInjectedStreamAudioStatsMap.clear(); @@ -715,7 +713,7 @@ void Audio::handleAudioInput() { } } -void Audio::addReceivedAudioToBuffer(const QByteArray& audioByteArray) { +void Audio::addReceivedAudioToStream(const QByteArray& audioByteArray) { if (_audioOutput) { // Audio output must exist and be correctly set up if we're going to process received audio processReceivedAudio(audioByteArray); @@ -755,7 +753,7 @@ void Audio::parseAudioStreamStatsPacket(const QByteArray& packet) { } AudioStreamStats Audio::getDownstreamAudioStreamStats() const { - return _ringBuffer.getAudioStreamStats(); + return _receivedAudioStream.getAudioStreamStats(); } void Audio::sendDownstreamAudioStatsPacket() { @@ -783,7 +781,7 @@ void Audio::sendDownstreamAudioStatsPacket() { dataAt += sizeof(quint16); // pack downstream audio stream stats - AudioStreamStats stats = _ringBuffer.updateSeqHistoryAndGetAudioStreamStats(); + AudioStreamStats stats = _receivedAudioStream.updateSeqHistoryAndGetAudioStreamStats(); memcpy(dataAt, &stats, sizeof(AudioStreamStats)); dataAt += sizeof(AudioStreamStats); @@ -894,7 +892,7 @@ void Audio::toggleStereoInput() { void Audio::processReceivedAudio(const QByteArray& audioByteArray) { // parse audio data - _ringBuffer.parseData(audioByteArray); + _receivedAudioStream.parseData(audioByteArray); pushAudioToOutput(); } @@ -904,7 +902,7 @@ void Audio::pushAudioToOutput() { if (_audioOutput->bytesFree() == _audioOutput->bufferSize()) { // the audio output has no samples to play. set the downstream audio to starved so that it // refills to its desired size before pushing frames - _ringBuffer.setToStarved(); + _receivedAudioStream.setToStarved(); } float networkOutputToOutputRatio = (_desiredOutputFormat.sampleRate() / (float)_outputFormat.sampleRate()) @@ -912,16 +910,16 @@ void Audio::pushAudioToOutput() { int numFramesToPush; if (Menu::getInstance()->isOptionChecked(MenuOption::DisableQAudioOutputOverflowCheck)) { - numFramesToPush = _ringBuffer.getFramesAvailable(); + numFramesToPush = _receivedAudioStream.getFramesAvailable(); } else { // make sure to push a whole number of frames to the audio output - int numFramesAudioOutputRoomFor = (int)(_audioOutput->bytesFree() / sizeof(int16_t) * networkOutputToOutputRatio) / _ringBuffer.getNumFrameSamples(); - numFramesToPush = std::min(_ringBuffer.getFramesAvailable(), numFramesAudioOutputRoomFor); + int numFramesAudioOutputRoomFor = (int)(_audioOutput->bytesFree() / sizeof(int16_t) * networkOutputToOutputRatio) / _receivedAudioStream.getNumFrameSamples(); + numFramesToPush = std::min(_receivedAudioStream.getFramesAvailable(), numFramesAudioOutputRoomFor); } - // if there is data in the ring buffer and room in the audio output, decide what to do + // if there is data in the received stream and room in the audio output, decide what to do - if (numFramesToPush > 0 && _ringBuffer.popFrames(numFramesToPush, false)) { + if (numFramesToPush > 0 && _receivedAudioStream.popFrames(numFramesToPush, false)) { int numNetworkOutputSamples = numFramesToPush * NETWORK_BUFFER_LENGTH_SAMPLES_STEREO; int numDeviceOutputSamples = numNetworkOutputSamples / networkOutputToOutputRatio; @@ -929,15 +927,15 @@ void Audio::pushAudioToOutput() { QByteArray outputBuffer; outputBuffer.resize(numDeviceOutputSamples * sizeof(int16_t)); - AudioRingBuffer::ConstIterator ringBufferPopOutput = _ringBuffer.getLastPopOutput(); + AudioRingBuffer::ConstIterator receivedAudioStreamPopOutput = _receivedAudioStream.getLastPopOutput(); - int16_t* ringBufferSamples = new int16_t[numNetworkOutputSamples]; + int16_t* receivedSamples = new int16_t[numNetworkOutputSamples]; if (_processSpatialAudio) { unsigned int sampleTime = _spatialAudioStart; QByteArray buffer; buffer.resize(numNetworkOutputSamples * sizeof(int16_t)); - ringBufferPopOutput.readSamples((int16_t*)buffer.data(), numNetworkOutputSamples); + receivedAudioStreamPopOutput.readSamples((int16_t*)buffer.data(), numNetworkOutputSamples); // Accumulate direct transmission of audio from sender to receiver if (Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingIncludeOriginal)) { @@ -950,18 +948,18 @@ void Audio::pushAudioToOutput() { // copy the samples we'll resample from the spatial audio ring buffer - this also // pushes the read pointer of the spatial audio ring buffer forwards - _spatialAudioRingBuffer.readSamples(ringBufferSamples, numNetworkOutputSamples); + _spatialAudioRingBuffer.readSamples(receivedSamples, numNetworkOutputSamples); // Advance the start point for the next packet of audio to arrive _spatialAudioStart += numNetworkOutputSamples / _desiredOutputFormat.channelCount(); } else { // copy the samples we'll resample from the ring buffer - this also // pushes the read pointer of the ring buffer forwards - ringBufferPopOutput.readSamples(ringBufferSamples, numNetworkOutputSamples); + receivedAudioStreamPopOutput.readSamples(receivedSamples, numNetworkOutputSamples); } // copy the packet from the RB to the output - linearResampling(ringBufferSamples, + linearResampling(receivedSamples, (int16_t*)outputBuffer.data(), numNetworkOutputSamples, numDeviceOutputSamples, @@ -973,7 +971,7 @@ void Audio::pushAudioToOutput() { if (_scopeEnabled && !_scopeEnabledPause) { unsigned int numAudioChannels = _desiredOutputFormat.channelCount(); - int16_t* samples = ringBufferSamples; + int16_t* samples = receivedSamples; for (int numSamples = numNetworkOutputSamples / numAudioChannels; numSamples > 0; numSamples -= NETWORK_SAMPLES_PER_FRAME) { unsigned int audioChannel = 0; @@ -994,7 +992,7 @@ void Audio::pushAudioToOutput() { } } - delete[] ringBufferSamples; + delete[] receivedSamples; } } @@ -1332,14 +1330,14 @@ void Audio::renderStats(const float* color, int width, int height) { float audioInputBufferLatency = 0.0f, inputRingBufferLatency = 0.0f, networkRoundtripLatency = 0.0f, mixerRingBufferLatency = 0.0f, outputRingBufferLatency = 0.0f, audioOutputBufferLatency = 0.0f; - AudioStreamStats downstreamAudioStreamStats = _ringBuffer.getAudioStreamStats(); + AudioStreamStats downstreamAudioStreamStats = _receivedAudioStream.getAudioStreamStats(); SharedNodePointer audioMixerNodePointer = NodeList::getInstance()->soloNodeOfType(NodeType::AudioMixer); if (!audioMixerNodePointer.isNull()) { audioInputBufferLatency = _audioInputMsecsReadStats.getWindowAverage(); inputRingBufferLatency = getInputRingBufferAverageMsecsAvailable(); networkRoundtripLatency = audioMixerNodePointer->getPingMs(); - mixerRingBufferLatency = _audioMixerAvatarStreamAudioStats._ringBufferFramesAvailableAverage * BUFFER_SEND_INTERVAL_MSECS; - outputRingBufferLatency = downstreamAudioStreamStats._ringBufferFramesAvailableAverage * BUFFER_SEND_INTERVAL_MSECS; + mixerRingBufferLatency = _audioMixerAvatarStreamAudioStats._framesAvailableAverage * BUFFER_SEND_INTERVAL_MSECS; + outputRingBufferLatency = downstreamAudioStreamStats._framesAvailableAverage * BUFFER_SEND_INTERVAL_MSECS; audioOutputBufferLatency = _audioOutputMsecsUnplayedStats.getWindowAverage(); } float totalLatency = audioInputBufferLatency + inputRingBufferLatency + networkRoundtripLatency + mixerRingBufferLatency + outputRingBufferLatency + audioOutputBufferLatency; @@ -1427,26 +1425,26 @@ void Audio::renderAudioStreamStats(const AudioStreamStats& streamStats, int hori const float BUFFER_SEND_INTERVAL_MSECS = BUFFER_SEND_INTERVAL_USECS / (float)USECS_PER_MSEC; sprintf(stringBuffer, " Ringbuffer frames | desired: %u, avg_available(10s): %u+%d, available: %u+%d", - streamStats._ringBufferDesiredJitterBufferFrames, - streamStats._ringBufferFramesAvailableAverage, + streamStats._desiredJitterBufferFrames, + streamStats._framesAvailableAverage, (int)(getAudioOutputAverageMsecsUnplayed() / BUFFER_SEND_INTERVAL_MSECS), - streamStats._ringBufferFramesAvailable, + streamStats._framesAvailable, (int)(getAudioOutputMsecsUnplayed() / BUFFER_SEND_INTERVAL_MSECS)); } else { sprintf(stringBuffer, " Ringbuffer frames | desired: %u, avg_available(10s): %u, available: %u", - streamStats._ringBufferDesiredJitterBufferFrames, - streamStats._ringBufferFramesAvailableAverage, - streamStats._ringBufferFramesAvailable); + streamStats._desiredJitterBufferFrames, + streamStats._framesAvailableAverage, + streamStats._framesAvailable); } verticalOffset += STATS_HEIGHT_PER_LINE; drawText(horizontalOffset, verticalOffset, scale, rotation, font, stringBuffer, color); sprintf(stringBuffer, " Ringbuffer stats | starves: %u, prev_starve_lasted: %u, frames_dropped: %u, overflows: %u", - streamStats._ringBufferStarveCount, - streamStats._ringBufferConsecutiveNotMixedCount, - streamStats._ringBufferSilentFramesDropped, - streamStats._ringBufferOverflowCount); + streamStats._starveCount, + streamStats._consecutiveNotMixedCount, + streamStats._silentFramesDropped, + streamStats._overflowCount); verticalOffset += STATS_HEIGHT_PER_LINE; drawText(horizontalOffset, verticalOffset, scale, rotation, font, stringBuffer, color); @@ -1662,8 +1660,8 @@ bool Audio::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDeviceInfo) // setup our general output device for audio-mixer audio _audioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this); - _audioOutput->setBufferSize(_ringBuffer.getFrameCapacity() * _outputFormat.bytesForDuration(BUFFER_SEND_INTERVAL_USECS)); - qDebug() << "Ring Buffer capacity in frames: " << _ringBuffer.getFrameCapacity(); + _audioOutput->setBufferSize(_receivedAudioStream.getFrameCapacity() * _outputFormat.bytesForDuration(BUFFER_SEND_INTERVAL_USECS)); + qDebug() << "Ring Buffer capacity in frames: " << _receivedAudioStream.getFrameCapacity(); _outputDevice = _audioOutput->start(); // setup a loopback audio output device diff --git a/interface/src/Audio.h b/interface/src/Audio.h index d2bdc748ea..3efdb1d3b1 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -33,7 +33,7 @@ #include #include -#include "InboundMixedAudioStream.h" +#include "MixedAudioStream.h" static const int NUM_AUDIO_CHANNELS = 2; @@ -46,19 +46,19 @@ class Audio : public AbstractAudioInterface { Q_OBJECT public: // setup for audio I/O - Audio(int16_t initialJitterBufferSamples, QObject* parent = 0); + Audio(QObject* parent = 0); float getLastInputLoudness() const { return glm::max(_lastInputLoudness - _noiseGateMeasuredFloor, 0.f); } float getTimeSinceLastClip() const { return _timeSinceLastClip; } float getAudioAverageInputLoudness() const { return _lastInputLoudness; } void setNoiseGateEnabled(bool noiseGateEnabled) { _noiseGateEnabled = noiseGateEnabled; } - - void setJitterBufferSamples(int samples) { _jitterBufferSamples = samples; } - int getJitterBufferSamples() { return _jitterBufferSamples; } virtual void startCollisionSound(float magnitude, float frequency, float noise, float duration, bool flashScreen); virtual void startDrumSound(float volume, float frequency, float duration, float decay); + + void overrideDesiredJitterBufferFramesTo(int desired) { _receivedAudioStream.overrideDesiredJitterBufferFramesTo(desired); } + int getDesiredJitterBufferFrames() const { return _receivedAudioStream.getDesiredJitterBufferFrames(); } float getCollisionSoundMagnitude() { return _collisionSoundMagnitude; } @@ -87,7 +87,7 @@ public: public slots: void start(); void stop(); - void addReceivedAudioToBuffer(const QByteArray& audioByteArray); + void addReceivedAudioToStream(const QByteArray& audioByteArray); void parseAudioStreamStatsPacket(const QByteArray& packet); void addSpatialAudioToBuffer(unsigned int sampleTime, const QByteArray& spatialAudio, unsigned int numSamples); void handleAudioInput(); @@ -120,8 +120,6 @@ public slots: float getInputVolume() const { return (_audioInput) ? _audioInput->volume() : 0.0f; } void setInputVolume(float volume) { if (_audioInput) _audioInput->setVolume(volume); } - - int getDesiredJitterBufferFrames() const { return _jitterBufferSamples / _ringBuffer.getNumFrameSamples(); } const AudioStreamStats& getAudioMixerAvatarStreamAudioStats() const { return _audioMixerAvatarStreamAudioStats; } const QHash& getAudioMixerInjectedStreamAudioStatsMap() const { return _audioMixerInjectedStreamAudioStatsMap; } @@ -151,7 +149,7 @@ private: QAudioOutput* _proceduralAudioOutput; QIODevice* _proceduralOutputDevice; AudioRingBuffer _inputRingBuffer; - InboundMixedAudioStream _ringBuffer; + MixedAudioStream _receivedAudioStream; bool _isStereoInput; QString _inputAudioDeviceName; @@ -160,8 +158,6 @@ private: StDev _stdev; QElapsedTimer _timeSinceLastReceived; float _averagedLatency; - float _measuredJitter; - int16_t _jitterBufferSamples; float _lastInputLoudness; float _timeSinceLastClip; float _dcOffset; diff --git a/libraries/audio/src/AudioStreamStats.h b/libraries/audio/src/AudioStreamStats.h index 4dd537afc0..784e163b3b 100644 --- a/libraries/audio/src/AudioStreamStats.h +++ b/libraries/audio/src/AudioStreamStats.h @@ -25,13 +25,13 @@ public: _timeGapWindowMin(0), _timeGapWindowMax(0), _timeGapWindowAverage(0.0f), - _ringBufferFramesAvailable(0), - _ringBufferFramesAvailableAverage(0), - _ringBufferDesiredJitterBufferFrames(0), - _ringBufferStarveCount(0), - _ringBufferConsecutiveNotMixedCount(0), - _ringBufferOverflowCount(0), - _ringBufferSilentFramesDropped(0), + _framesAvailable(0), + _framesAvailableAverage(0), + _desiredJitterBufferFrames(0), + _starveCount(0), + _consecutiveNotMixedCount(0), + _overflowCount(0), + _silentFramesDropped(0), _packetStreamStats(), _packetStreamWindowStats() {} @@ -46,13 +46,13 @@ public: quint64 _timeGapWindowMax; float _timeGapWindowAverage; - quint32 _ringBufferFramesAvailable; - quint16 _ringBufferFramesAvailableAverage; - quint16 _ringBufferDesiredJitterBufferFrames; - quint32 _ringBufferStarveCount; - quint32 _ringBufferConsecutiveNotMixedCount; - quint32 _ringBufferOverflowCount; - quint32 _ringBufferSilentFramesDropped; + quint32 _framesAvailable; + quint16 _framesAvailableAverage; + quint16 _desiredJitterBufferFrames; + quint32 _starveCount; + quint32 _consecutiveNotMixedCount; + quint32 _overflowCount; + quint32 _silentFramesDropped; PacketStreamStats _packetStreamStats; PacketStreamStats _packetStreamWindowStats; diff --git a/libraries/audio/src/InboundAudioStream.cpp b/libraries/audio/src/InboundAudioStream.cpp index f260fd83d1..a22a002548 100644 --- a/libraries/audio/src/InboundAudioStream.cpp +++ b/libraries/audio/src/InboundAudioStream.cpp @@ -146,6 +146,11 @@ void InboundAudioStream::starved() { _starveCount++; } +void InboundAudioStream::overrideDesiredJitterBufferFramesTo(int desired) { + _dynamicJitterBuffers = false; + _desiredJitterBufferFrames = desired; +} + int InboundAudioStream::clampDesiredJitterBufferFramesValue(int desired) const { const int MIN_FRAMES_DESIRED = 0; const int MAX_FRAMES_DESIRED = _ringBuffer.getFrameCapacity(); @@ -244,13 +249,13 @@ AudioStreamStats InboundAudioStream::getAudioStreamStats() const { streamStats._timeGapWindowMax = _interframeTimeGapStatsForStatsPacket.getWindowMax(); streamStats._timeGapWindowAverage = _interframeTimeGapStatsForStatsPacket.getWindowAverage(); - streamStats._ringBufferFramesAvailable = _ringBuffer.framesAvailable(); - streamStats._ringBufferFramesAvailableAverage = _framesAvailableStats.getWindowAverage(); - streamStats._ringBufferDesiredJitterBufferFrames = _desiredJitterBufferFrames; - streamStats._ringBufferStarveCount = _starveCount; - streamStats._ringBufferConsecutiveNotMixedCount = _consecutiveNotMixedCount; - streamStats._ringBufferOverflowCount = _ringBuffer.getOverflowCount(); - streamStats._ringBufferSilentFramesDropped = _silentFramesDropped; + streamStats._framesAvailable = _ringBuffer.framesAvailable(); + streamStats._framesAvailableAverage = _framesAvailableStats.getWindowAverage(); + streamStats._desiredJitterBufferFrames = _desiredJitterBufferFrames; + streamStats._starveCount = _starveCount; + streamStats._consecutiveNotMixedCount = _consecutiveNotMixedCount; + streamStats._overflowCount = _ringBuffer.getOverflowCount(); + streamStats._silentFramesDropped = _silentFramesDropped; streamStats._packetStreamStats = _incomingSequenceNumberStats.getStats(); streamStats._packetStreamWindowStats = _incomingSequenceNumberStats.getStatsForHistoryWindow(); diff --git a/libraries/audio/src/InboundAudioStream.h b/libraries/audio/src/InboundAudioStream.h index 76b4ce18e8..82ebbc5ab0 100644 --- a/libraries/audio/src/InboundAudioStream.h +++ b/libraries/audio/src/InboundAudioStream.h @@ -62,6 +62,8 @@ public: void setToStarved(); + /// turns off dyanmic jitter buffers and sets the desired jitter buffer frames to specified value + void overrideDesiredJitterBufferFramesTo(int desired); /// this function should be called once per second to ensure the seq num stats history spans ~30 seconds AudioStreamStats updateSeqHistoryAndGetAudioStreamStats(); @@ -95,8 +97,11 @@ public: private: void starved(); + SequenceNumberStats::ArrivalInfo frameReceivedUpdateNetworkStats(quint16 sequenceNumber, const QUuid& senderUUID); int clampDesiredJitterBufferFramesValue(int desired) const; + int writeSamplesForDroppedPackets(int numSamples); + protected: // disallow copying of InboundAudioStream objects InboundAudioStream(const InboundAudioStream&); @@ -110,9 +115,7 @@ protected: virtual int parseAudioData(PacketType type, const QByteArray& packetAfterStreamProperties, int numAudioSamples) = 0; int writeDroppableSilentSamples(int numSilentSamples); - int writeSamplesForDroppedPackets(int numSamples); - SequenceNumberStats::ArrivalInfo frameReceivedUpdateNetworkStats(quint16 sequenceNumber, const QUuid& senderUUID); - + protected: AudioRingBuffer _ringBuffer; @@ -120,7 +123,7 @@ protected: bool _lastPopSucceeded; AudioRingBuffer::ConstIterator _lastPopOutput; - const bool _dynamicJitterBuffers; + bool _dynamicJitterBuffers; bool _useStDevForJitterCalc; int _calculatedJitterBufferFramesUsingMaxGap; diff --git a/libraries/audio/src/InboundMixedAudioStream.cpp b/libraries/audio/src/InboundMixedAudioStream.cpp deleted file mode 100644 index 208e5d8dcc..0000000000 --- a/libraries/audio/src/InboundMixedAudioStream.cpp +++ /dev/null @@ -1,17 +0,0 @@ - -#include "InboundMixedAudioStream.h" - -InboundMixedAudioStream::InboundMixedAudioStream(int numFrameSamples, int numFramesCapacity, bool dynamicJitterBuffers, bool useStDevForJitterCalc) - : InboundAudioStream(numFrameSamples, numFramesCapacity, dynamicJitterBuffers, useStDevForJitterCalc) -{ -} - -int InboundMixedAudioStream::parseStreamProperties(PacketType type, const QByteArray& packetAfterSeqNum, int& numAudioSamples) { - // mixed audio packets do not have any info between the seq num and the audio data. - numAudioSamples = packetAfterSeqNum.size() / sizeof(int16_t); - return 0; -} - -int InboundMixedAudioStream::parseAudioData(PacketType type, const QByteArray& packetAfterStreamProperties, int numAudioSamples) { - return _ringBuffer.writeData(packetAfterStreamProperties.data(), numAudioSamples * sizeof(int16_t)); -} diff --git a/libraries/audio/src/InboundMixedAudioStream.h b/libraries/audio/src/InboundMixedAudioStream.h deleted file mode 100644 index d6a8d493ca..0000000000 --- a/libraries/audio/src/InboundMixedAudioStream.h +++ /dev/null @@ -1,14 +0,0 @@ - -#include "InboundAudioStream.h" -#include "PacketHeaders.h" - -class InboundMixedAudioStream : public InboundAudioStream { -public: - InboundMixedAudioStream(int numFrameSamples, int numFramesCapacity, bool dynamicJitterBuffers, bool useStDevForJitterCalc = false); - - float getNextOutputFrameLoudness() const { return _ringBuffer.getNextOutputFrameLoudness(); } - -protected: - int parseStreamProperties(PacketType type, const QByteArray& packetAfterSeqNum, int& numAudioSamples); - int parseAudioData(PacketType type, const QByteArray& packetAfterStreamProperties, int numAudioSamples); -}; diff --git a/libraries/audio/src/InjectedAudioStream.h b/libraries/audio/src/InjectedAudioStream.h index 81659c4836..b92736b0ba 100644 --- a/libraries/audio/src/InjectedAudioStream.h +++ b/libraries/audio/src/InjectedAudioStream.h @@ -9,8 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_InjectedAudioRingBuffer_h -#define hifi_InjectedAudioRingBuffer_h +#ifndef hifi_InjectedAudioStream_h +#define hifi_InjectedAudioStream_h #include @@ -39,4 +39,4 @@ private: float _attenuationRatio; }; -#endif // hifi_InjectedAudioRingBuffer_h +#endif // hifi_InjectedAudioStream_h diff --git a/libraries/audio/src/MixedAudioStream.cpp b/libraries/audio/src/MixedAudioStream.cpp new file mode 100644 index 0000000000..b2c57c46d6 --- /dev/null +++ b/libraries/audio/src/MixedAudioStream.cpp @@ -0,0 +1,17 @@ + +#include "MixedAudioStream.h" + +MixedAudioStream::MixedAudioStream(int numFrameSamples, int numFramesCapacity, bool dynamicJitterBuffers, bool useStDevForJitterCalc) + : InboundAudioStream(numFrameSamples, numFramesCapacity, dynamicJitterBuffers, useStDevForJitterCalc) +{ +} + +int MixedAudioStream::parseStreamProperties(PacketType type, const QByteArray& packetAfterSeqNum, int& numAudioSamples) { + // mixed audio packets do not have any info between the seq num and the audio data. + numAudioSamples = packetAfterSeqNum.size() / sizeof(int16_t); + return 0; +} + +int MixedAudioStream::parseAudioData(PacketType type, const QByteArray& packetAfterStreamProperties, int numAudioSamples) { + return _ringBuffer.writeData(packetAfterStreamProperties.data(), numAudioSamples * sizeof(int16_t)); +} diff --git a/libraries/audio/src/MixedAudioStream.h b/libraries/audio/src/MixedAudioStream.h new file mode 100644 index 0000000000..3f52a3c979 --- /dev/null +++ b/libraries/audio/src/MixedAudioStream.h @@ -0,0 +1,29 @@ +// +// MixedAudioStream.h +// libraries/audio/src +// +// Created by Stephen Birarda on 6/5/13. +// Copyright 2013 High Fidelity, Inc. +// +// 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_MixedAudioStream_h +#define hifi_MixedAudioStream + +#include "InboundAudioStream.h" +#include "PacketHeaders.h" + +class MixedAudioStream : public InboundAudioStream { +public: + MixedAudioStream(int numFrameSamples, int numFramesCapacity, bool dynamicJitterBuffers, bool useStDevForJitterCalc = false); + + float getNextOutputFrameLoudness() const { return _ringBuffer.getNextOutputFrameLoudness(); } + +protected: + int parseStreamProperties(PacketType type, const QByteArray& packetAfterSeqNum, int& numAudioSamples); + int parseAudioData(PacketType type, const QByteArray& packetAfterStreamProperties, int numAudioSamples); +}; + +#endif // hifi_MixedAudioStream_h diff --git a/libraries/audio/src/PositionalAudioStream.h b/libraries/audio/src/PositionalAudioStream.h index de76edaa63..06835b93a8 100644 --- a/libraries/audio/src/PositionalAudioStream.h +++ b/libraries/audio/src/PositionalAudioStream.h @@ -9,8 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_PositionalAudioRingBuffer_h -#define hifi_PositionalAudioRingBuffer_h +#ifndef hifi_PositionalAudioStream_h +#define hifi_PositionalAudioStream_h #include #include @@ -71,4 +71,4 @@ protected: AABox* _listenerUnattenuatedZone; }; -#endif // hifi_PositionalAudioRingBuffer_h +#endif // hifi_PositionalAudioStream_h