mirror of
https://github.com/Armored-Dragon/overte.git
synced 2025-03-11 16:13:16 +01:00
reinstate a cutoff when the audio-mixer is struggling
This commit is contained in:
parent
1580896ec4
commit
2575b33662
4 changed files with 63 additions and 23 deletions
|
@ -53,6 +53,8 @@
|
|||
const short JITTER_BUFFER_MSECS = 12;
|
||||
const short JITTER_BUFFER_SAMPLES = JITTER_BUFFER_MSECS * (SAMPLE_RATE / 1000.0);
|
||||
|
||||
const float LOUDNESS_TO_DISTANCE_RATIO = 0.00305f;
|
||||
|
||||
const QString AUDIO_MIXER_LOGGING_TARGET_NAME = "audio-mixer";
|
||||
|
||||
void attachNewBufferToNode(Node *newNode) {
|
||||
|
@ -64,10 +66,7 @@ void attachNewBufferToNode(Node *newNode) {
|
|||
AudioMixer::AudioMixer(const QByteArray& packet) :
|
||||
ThreadedAssignment(packet),
|
||||
_trailingSleepRatio(1.0f),
|
||||
_minSourceLoudnessInFrame(1.0f),
|
||||
_maxSourceLoudnessInFrame(0.0f),
|
||||
_loudnessCutoffRatio(0.0f),
|
||||
_minRequiredLoudness(0.0f)
|
||||
_minAudabilityThreshold(LOUDNESS_TO_DISTANCE_RATIO / 2)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -83,8 +82,15 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf
|
|||
// if the two buffer pointers do not match then these are different buffers
|
||||
|
||||
glm::vec3 relativePosition = bufferToAdd->getPosition() - listeningNodeBuffer->getPosition();
|
||||
|
||||
if (bufferToAdd->getAverageLoudness() / glm::length(relativePosition) <= _minAudabilityThreshold) {
|
||||
// according to mixer performance we have decided this does not get to be mixed in
|
||||
// bail out
|
||||
return;
|
||||
}
|
||||
|
||||
glm::quat inverseOrientation = glm::inverse(listeningNodeBuffer->getOrientation());
|
||||
|
||||
|
||||
float distanceSquareToSource = glm::dot(relativePosition, relativePosition);
|
||||
float radius = 0.0f;
|
||||
|
||||
|
@ -305,8 +311,7 @@ void AudioMixer::prepareMixForListeningNode(Node* node) {
|
|||
|
||||
if ((*otherNode != *node
|
||||
|| otherNodeBuffer->shouldLoopbackForNode())
|
||||
&& otherNodeBuffer->willBeAddedToMix()
|
||||
&& otherNodeBuffer->getAverageLoudness() > _minRequiredLoudness) {
|
||||
&& otherNodeBuffer->willBeAddedToMix()) {
|
||||
addBufferToMixForListeningNodeWithBuffer(otherNodeBuffer, nodeRingBuffer);
|
||||
}
|
||||
}
|
||||
|
@ -357,19 +362,61 @@ void AudioMixer::run() {
|
|||
+ numBytesForPacketHeaderGivenPacketType(PacketTypeMixedAudio)];
|
||||
|
||||
int usecToSleep = BUFFER_SEND_INTERVAL_USECS;
|
||||
float audabilityCutoffRatio = 0;
|
||||
|
||||
while (!_isFinished) {
|
||||
|
||||
_minSourceLoudnessInFrame = 1.0f;
|
||||
_maxSourceLoudnessInFrame = 0.0f;
|
||||
|
||||
foreach (const SharedNodePointer& node, nodeList->getNodeHash()) {
|
||||
if (node->getLinkedData()) {
|
||||
((AudioMixerClientData*) node->getLinkedData())->checkBuffersBeforeFrameSend(JITTER_BUFFER_SAMPLES,
|
||||
_minSourceLoudnessInFrame,
|
||||
_maxSourceLoudnessInFrame);
|
||||
((AudioMixerClientData*) node->getLinkedData())->checkBuffersBeforeFrameSend(JITTER_BUFFER_SAMPLES);
|
||||
}
|
||||
}
|
||||
|
||||
const float STRUGGLE_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD = 0.10;
|
||||
const float BACK_OFF_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD = 0.30;
|
||||
const float CUTOFF_EPSILON = 0.0001;
|
||||
|
||||
const int TRAILING_AVERAGE_FRAMES = 100;
|
||||
const float CURRENT_FRAME_RATIO = 1.0f / TRAILING_AVERAGE_FRAMES;
|
||||
const float PREVIOUS_FRAMES_RATIO = 1 - CURRENT_FRAME_RATIO;
|
||||
|
||||
if (usecToSleep < 0) {
|
||||
usecToSleep = 0;
|
||||
}
|
||||
|
||||
_trailingSleepRatio = (PREVIOUS_FRAMES_RATIO * _trailingSleepRatio)
|
||||
+ (usecToSleep * CURRENT_FRAME_RATIO / (float) BUFFER_SEND_INTERVAL_USECS);
|
||||
|
||||
float lastCutoffRatio = audabilityCutoffRatio;
|
||||
bool hasRatioChanged = false;
|
||||
|
||||
if (_trailingSleepRatio <= STRUGGLE_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD) {
|
||||
// we're struggling - change our min required loudness to reduce some load
|
||||
audabilityCutoffRatio += (1 - audabilityCutoffRatio) / 2;
|
||||
|
||||
qDebug() << "Mixer is struggling, sleeping" << _trailingSleepRatio * 100 << "% of frame time. Old cutoff was"
|
||||
<< lastCutoffRatio << "and is now" << audabilityCutoffRatio;
|
||||
hasRatioChanged = true;
|
||||
} else if (_trailingSleepRatio >= BACK_OFF_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD && audabilityCutoffRatio != 0) {
|
||||
// we've recovered and can back off the required loudness
|
||||
audabilityCutoffRatio -= audabilityCutoffRatio / 2;
|
||||
|
||||
if (audabilityCutoffRatio < CUTOFF_EPSILON) {
|
||||
audabilityCutoffRatio = 0;
|
||||
}
|
||||
|
||||
qDebug() << "Mixer is recovering, sleeping" << _trailingSleepRatio * 100 << "% of frame time. Old cutoff was"
|
||||
<< lastCutoffRatio << "and is now" << audabilityCutoffRatio;
|
||||
hasRatioChanged = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (hasRatioChanged) {
|
||||
// set out min required loudness from the new ratio
|
||||
_minAudabilityThreshold = LOUDNESS_TO_DISTANCE_RATIO / (2 * (1 - audabilityCutoffRatio));
|
||||
qDebug() << "Minimum loudness required to be mixed is now" << _minAudabilityThreshold;
|
||||
}
|
||||
|
||||
foreach (const SharedNodePointer& node, nodeList->getNodeHash()) {
|
||||
if (node->getType() == NodeType::Agent && node->getActiveSocket() && node->getLinkedData()
|
||||
|
|
|
@ -41,10 +41,7 @@ private:
|
|||
int16_t _clientSamples[NETWORK_BUFFER_LENGTH_SAMPLES_STEREO + (SAMPLE_PHASE_DELAY_AT_90 * 2)];
|
||||
|
||||
float _trailingSleepRatio;
|
||||
float _minSourceLoudnessInFrame;
|
||||
float _maxSourceLoudnessInFrame;
|
||||
float _loudnessCutoffRatio;
|
||||
float _minRequiredLoudness;
|
||||
float _minAudabilityThreshold;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__AudioMixer__) */
|
||||
|
|
|
@ -83,20 +83,16 @@ int AudioMixerClientData::parseData(const QByteArray& packet) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void AudioMixerClientData::checkBuffersBeforeFrameSend(int jitterBufferLengthSamples,
|
||||
float& currentMinLoudness,
|
||||
float& currentMaxLoudness) {
|
||||
void AudioMixerClientData::checkBuffersBeforeFrameSend(int jitterBufferLengthSamples) {
|
||||
for (unsigned int i = 0; i < _ringBuffers.size(); i++) {
|
||||
if (_ringBuffers[i]->shouldBeAddedToMix(jitterBufferLengthSamples)) {
|
||||
// this is a ring buffer that is ready to go
|
||||
// set its flag so we know to push its buffer when all is said and done
|
||||
_ringBuffers[i]->setWillBeAddedToMix(true);
|
||||
|
||||
|
||||
// calculate the average loudness for the next NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL
|
||||
// that would be mixed in
|
||||
_ringBuffers[i]->updateAverageLoudnessForBoundarySamples(NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ public:
|
|||
AvatarAudioRingBuffer* getAvatarAudioRingBuffer() const;
|
||||
|
||||
int parseData(const QByteArray& packet);
|
||||
void checkBuffersBeforeFrameSend(int jitterBufferLengthSamples, float& currentMinLoudness, float& currentMaxLoudness);
|
||||
void checkBuffersBeforeFrameSend(int jitterBufferLengthSamples);
|
||||
void pushBuffersAfterFrameSend();
|
||||
private:
|
||||
std::vector<PositionalAudioRingBuffer*> _ringBuffers;
|
||||
|
|
Loading…
Reference in a new issue