mirror of
https://github.com/overte-org/overte.git
synced 2025-07-23 21:05:04 +02:00
Merge pull request #3454 from ZappoMan/perListenerSourcePairMixerData
Per listener source pair mixer data
This commit is contained in:
commit
049810c00d
4 changed files with 56 additions and 16 deletions
|
@ -96,7 +96,6 @@ AudioMixer::AudioMixer(const QByteArray& packet) :
|
||||||
{
|
{
|
||||||
// constant defined in AudioMixer.h. However, we don't want to include this here
|
// constant defined in AudioMixer.h. However, we don't want to include this here
|
||||||
// we will soon find a better common home for these audio-related constants
|
// we will soon find a better common home for these audio-related constants
|
||||||
_penumbraFilter.initialize(SAMPLE_RATE, (NETWORK_BUFFER_LENGTH_SAMPLES_STEREO + (SAMPLE_PHASE_DELAY_AT_90 * 2)) / 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioMixer::~AudioMixer() {
|
AudioMixer::~AudioMixer() {
|
||||||
|
@ -108,7 +107,9 @@ const float ATTENUATION_BEGINS_AT_DISTANCE = 1.0f;
|
||||||
const float ATTENUATION_AMOUNT_PER_DOUBLING_IN_DISTANCE = 0.18f;
|
const float ATTENUATION_AMOUNT_PER_DOUBLING_IN_DISTANCE = 0.18f;
|
||||||
const float RADIUS_OF_HEAD = 0.076f;
|
const float RADIUS_OF_HEAD = 0.076f;
|
||||||
|
|
||||||
int AudioMixer::addStreamToMixForListeningNodeWithStream(PositionalAudioStream* streamToAdd,
|
int AudioMixer::addStreamToMixForListeningNodeWithStream(AudioMixerClientData* listenerNodeData,
|
||||||
|
const QUuid& streamUUID,
|
||||||
|
PositionalAudioStream* streamToAdd,
|
||||||
AvatarAudioStream* listeningNodeStream) {
|
AvatarAudioStream* listeningNodeStream) {
|
||||||
// If repetition with fade is enabled:
|
// If repetition with fade is enabled:
|
||||||
// If streamToAdd could not provide a frame (it was starved), then we'll mix its previously-mixed frame
|
// If streamToAdd could not provide a frame (it was starved), then we'll mix its previously-mixed frame
|
||||||
|
@ -413,11 +414,13 @@ int AudioMixer::addStreamToMixForListeningNodeWithStream(PositionalAudioStream*
|
||||||
<< -bearingRelativeAngleToSource;
|
<< -bearingRelativeAngleToSource;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Get our per listener/source data so we can get our filter
|
||||||
|
AudioFilterHSF1s& penumbraFilter = listenerNodeData->getListenerSourcePairData(streamUUID)->getPenumbraFilter();
|
||||||
|
|
||||||
// set the gain on both filter channels
|
// set the gain on both filter channels
|
||||||
_penumbraFilter.reset();
|
penumbraFilter.setParameters(0, 0, SAMPLE_RATE, penumbraFilterFrequency, penumbraFilterGainL, penumbraFilterSlope);
|
||||||
_penumbraFilter.setParameters(0, 0, SAMPLE_RATE, penumbraFilterFrequency, penumbraFilterGainL, penumbraFilterSlope);
|
penumbraFilter.setParameters(0, 1, SAMPLE_RATE, penumbraFilterFrequency, penumbraFilterGainR, penumbraFilterSlope);
|
||||||
_penumbraFilter.setParameters(0, 1, SAMPLE_RATE, penumbraFilterFrequency, penumbraFilterGainR, penumbraFilterSlope);
|
penumbraFilter.render(_preMixSamples, _preMixSamples, NETWORK_BUFFER_LENGTH_SAMPLES_STEREO / 2);
|
||||||
_penumbraFilter.render(_preMixSamples, _preMixSamples, NETWORK_BUFFER_LENGTH_SAMPLES_STEREO / 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actually mix the _preMixSamples into the _mixSamples here.
|
// Actually mix the _preMixSamples into the _mixSamples here.
|
||||||
|
@ -430,6 +433,7 @@ int AudioMixer::addStreamToMixForListeningNodeWithStream(PositionalAudioStream*
|
||||||
|
|
||||||
int AudioMixer::prepareMixForListeningNode(Node* node) {
|
int AudioMixer::prepareMixForListeningNode(Node* node) {
|
||||||
AvatarAudioStream* nodeAudioStream = ((AudioMixerClientData*) node->getLinkedData())->getAvatarAudioStream();
|
AvatarAudioStream* nodeAudioStream = ((AudioMixerClientData*) node->getLinkedData())->getAvatarAudioStream();
|
||||||
|
AudioMixerClientData* listenerNodeData = (AudioMixerClientData*)node->getLinkedData();
|
||||||
|
|
||||||
// zero out the client mix for this node
|
// zero out the client mix for this node
|
||||||
memset(_preMixSamples, 0, sizeof(_preMixSamples));
|
memset(_preMixSamples, 0, sizeof(_preMixSamples));
|
||||||
|
@ -447,9 +451,15 @@ int AudioMixer::prepareMixForListeningNode(Node* node) {
|
||||||
QHash<QUuid, PositionalAudioStream*>::ConstIterator i;
|
QHash<QUuid, PositionalAudioStream*>::ConstIterator i;
|
||||||
for (i = otherNodeAudioStreams.constBegin(); i != otherNodeAudioStreams.constEnd(); i++) {
|
for (i = otherNodeAudioStreams.constBegin(); i != otherNodeAudioStreams.constEnd(); i++) {
|
||||||
PositionalAudioStream* otherNodeStream = i.value();
|
PositionalAudioStream* otherNodeStream = i.value();
|
||||||
|
QUuid streamUUID = i.key();
|
||||||
|
|
||||||
|
if (otherNodeStream->getType() == PositionalAudioStream::Microphone) {
|
||||||
|
streamUUID = otherNode->getUUID();
|
||||||
|
}
|
||||||
|
|
||||||
if (*otherNode != *node || otherNodeStream->shouldLoopbackForNode()) {
|
if (*otherNode != *node || otherNodeStream->shouldLoopbackForNode()) {
|
||||||
streamsMixed += addStreamToMixForListeningNodeWithStream(otherNodeStream, nodeAudioStream);
|
streamsMixed += addStreamToMixForListeningNodeWithStream(listenerNodeData, streamUUID,
|
||||||
|
otherNodeStream, nodeAudioStream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,15 +13,12 @@
|
||||||
#define hifi_AudioMixer_h
|
#define hifi_AudioMixer_h
|
||||||
|
|
||||||
#include <AABox.h>
|
#include <AABox.h>
|
||||||
#include <AudioFormat.h> // For AudioFilterHSF1s and _penumbraFilter
|
|
||||||
#include <AudioBuffer.h> // For AudioFilterHSF1s and _penumbraFilter
|
|
||||||
#include <AudioFilter.h> // For AudioFilterHSF1s and _penumbraFilter
|
|
||||||
#include <AudioFilterBank.h> // For AudioFilterHSF1s and _penumbraFilter
|
|
||||||
#include <AudioRingBuffer.h>
|
#include <AudioRingBuffer.h>
|
||||||
#include <ThreadedAssignment.h>
|
#include <ThreadedAssignment.h>
|
||||||
|
|
||||||
class PositionalAudioStream;
|
class PositionalAudioStream;
|
||||||
class AvatarAudioStream;
|
class AvatarAudioStream;
|
||||||
|
class AudioMixerClientData;
|
||||||
|
|
||||||
const int SAMPLE_PHASE_DELAY_AT_90 = 20;
|
const int SAMPLE_PHASE_DELAY_AT_90 = 20;
|
||||||
|
|
||||||
|
@ -46,7 +43,9 @@ public slots:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// adds one stream to the mix for a listening node
|
/// adds one stream to the mix for a listening node
|
||||||
int addStreamToMixForListeningNodeWithStream(PositionalAudioStream* streamToAdd,
|
int addStreamToMixForListeningNodeWithStream(AudioMixerClientData* listenerNodeData,
|
||||||
|
const QUuid& streamUUID,
|
||||||
|
PositionalAudioStream* streamToAdd,
|
||||||
AvatarAudioStream* listeningNodeStream);
|
AvatarAudioStream* listeningNodeStream);
|
||||||
|
|
||||||
/// prepares and sends a mix to one Node
|
/// prepares and sends a mix to one Node
|
||||||
|
@ -60,8 +59,6 @@ private:
|
||||||
// we are MMX adding 4 samples at a time so we need client samples to have an extra 4
|
// we are MMX adding 4 samples at a time so we need client samples to have an extra 4
|
||||||
int16_t _mixSamples[NETWORK_BUFFER_LENGTH_SAMPLES_STEREO + (SAMPLE_PHASE_DELAY_AT_90 * 2)];
|
int16_t _mixSamples[NETWORK_BUFFER_LENGTH_SAMPLES_STEREO + (SAMPLE_PHASE_DELAY_AT_90 * 2)];
|
||||||
|
|
||||||
AudioFilterHSF1s _penumbraFilter;
|
|
||||||
|
|
||||||
void perSecondActions();
|
void perSecondActions();
|
||||||
|
|
||||||
QString getReadPendingDatagramsCallsPerSecondsStatsString() const;
|
QString getReadPendingDatagramsCallsPerSecondsStatsString() const;
|
||||||
|
|
|
@ -33,6 +33,11 @@ AudioMixerClientData::~AudioMixerClientData() {
|
||||||
// delete this attached InboundAudioStream
|
// delete this attached InboundAudioStream
|
||||||
delete i.value();
|
delete i.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clean up our pair data...
|
||||||
|
foreach(PerListenerSourcePairData* pairData, _listenerSourcePairData) {
|
||||||
|
delete pairData;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AvatarAudioStream* AudioMixerClientData::getAvatarAudioStream() const {
|
AvatarAudioStream* AudioMixerClientData::getAvatarAudioStream() const {
|
||||||
|
@ -302,3 +307,12 @@ void AudioMixerClientData::printAudioStreamStats(const AudioStreamStats& streamS
|
||||||
formatUsecTime(streamStats._timeGapWindowMax).toLatin1().data(),
|
formatUsecTime(streamStats._timeGapWindowMax).toLatin1().data(),
|
||||||
formatUsecTime(streamStats._timeGapWindowAverage).toLatin1().data());
|
formatUsecTime(streamStats._timeGapWindowAverage).toLatin1().data());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PerListenerSourcePairData* AudioMixerClientData::getListenerSourcePairData(const QUuid& sourceUUID) {
|
||||||
|
if (!_listenerSourcePairData.contains(sourceUUID)) {
|
||||||
|
PerListenerSourcePairData* newData = new PerListenerSourcePairData();
|
||||||
|
_listenerSourcePairData[sourceUUID] = newData;
|
||||||
|
}
|
||||||
|
return _listenerSourcePairData[sourceUUID];
|
||||||
|
}
|
||||||
|
|
|
@ -13,10 +13,25 @@
|
||||||
#define hifi_AudioMixerClientData_h
|
#define hifi_AudioMixerClientData_h
|
||||||
|
|
||||||
#include <AABox.h>
|
#include <AABox.h>
|
||||||
|
#include <AudioFormat.h> // For AudioFilterHSF1s and _penumbraFilter
|
||||||
|
#include <AudioBuffer.h> // For AudioFilterHSF1s and _penumbraFilter
|
||||||
|
#include <AudioFilter.h> // For AudioFilterHSF1s and _penumbraFilter
|
||||||
|
#include <AudioFilterBank.h> // For AudioFilterHSF1s and _penumbraFilter
|
||||||
|
|
||||||
#include "PositionalAudioStream.h"
|
#include "PositionalAudioStream.h"
|
||||||
#include "AvatarAudioStream.h"
|
#include "AvatarAudioStream.h"
|
||||||
|
|
||||||
|
class PerListenerSourcePairData {
|
||||||
|
public:
|
||||||
|
PerListenerSourcePairData() {
|
||||||
|
_penumbraFilter.initialize(SAMPLE_RATE, NETWORK_BUFFER_LENGTH_SAMPLES_STEREO / 2);
|
||||||
|
};
|
||||||
|
AudioFilterHSF1s& getPenumbraFilter() { return _penumbraFilter; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
AudioFilterHSF1s _penumbraFilter;
|
||||||
|
};
|
||||||
|
|
||||||
class AudioMixerClientData : public NodeData {
|
class AudioMixerClientData : public NodeData {
|
||||||
public:
|
public:
|
||||||
AudioMixerClientData();
|
AudioMixerClientData();
|
||||||
|
@ -40,12 +55,16 @@ public:
|
||||||
|
|
||||||
void printUpstreamDownstreamStats() const;
|
void printUpstreamDownstreamStats() const;
|
||||||
|
|
||||||
|
PerListenerSourcePairData* getListenerSourcePairData(const QUuid& sourceUUID);
|
||||||
private:
|
private:
|
||||||
void printAudioStreamStats(const AudioStreamStats& streamStats) const;
|
void printAudioStreamStats(const AudioStreamStats& streamStats) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QHash<QUuid, PositionalAudioStream*> _audioStreams; // mic stream stored under key of null UUID
|
QHash<QUuid, PositionalAudioStream*> _audioStreams; // mic stream stored under key of null UUID
|
||||||
|
|
||||||
|
// TODO: how can we prune this hash when a stream is no longer present?
|
||||||
|
QHash<QUuid, PerListenerSourcePairData*> _listenerSourcePairData;
|
||||||
|
|
||||||
quint16 _outgoingMixedAudioSequenceNumber;
|
quint16 _outgoingMixedAudioSequenceNumber;
|
||||||
|
|
||||||
AudioStreamStats _downstreamAudioStreamStats;
|
AudioStreamStats _downstreamAudioStreamStats;
|
||||||
|
|
Loading…
Reference in a new issue