mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 17:03:58 +02:00
fix the filter with delay and add per listener source pair data
This commit is contained in:
parent
a5ea0479c1
commit
864c1c88a7
4 changed files with 57 additions and 10 deletions
|
@ -96,7 +96,6 @@ AudioMixer::AudioMixer(const QByteArray& packet) :
|
|||
{
|
||||
// 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
|
||||
_penumbraFilter.initialize(SAMPLE_RATE, (NETWORK_BUFFER_LENGTH_SAMPLES_STEREO + (SAMPLE_PHASE_DELAY_AT_90 * 2)) / 2);
|
||||
}
|
||||
|
||||
AudioMixer::~AudioMixer() {
|
||||
|
@ -108,8 +107,10 @@ const float ATTENUATION_BEGINS_AT_DISTANCE = 1.0f;
|
|||
const float ATTENUATION_AMOUNT_PER_DOUBLING_IN_DISTANCE = 0.18f;
|
||||
const float RADIUS_OF_HEAD = 0.076f;
|
||||
|
||||
int AudioMixer::addStreamToMixForListeningNodeWithStream(PositionalAudioStream* streamToAdd,
|
||||
AvatarAudioStream* listeningNodeStream) {
|
||||
int AudioMixer::addStreamToMixForListeningNodeWithStream(AudioMixerClientData* listenerNodeData,
|
||||
const QUuid& streamUUID,
|
||||
PositionalAudioStream* streamToAdd,
|
||||
AvatarAudioStream* listeningNodeStream) {
|
||||
// If repetition with fade is enabled:
|
||||
// If streamToAdd could not provide a frame (it was starved), then we'll mix its previously-mixed frame
|
||||
// This is preferable to not mixing it at all since that's equivalent to inserting silence.
|
||||
|
@ -413,11 +414,13 @@ int AudioMixer::addStreamToMixForListeningNodeWithStream(PositionalAudioStream*
|
|||
<< -bearingRelativeAngleToSource;
|
||||
#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
|
||||
_penumbraFilter.reset();
|
||||
_penumbraFilter.setParameters(0, 0, SAMPLE_RATE, penumbraFilterFrequency, penumbraFilterGainL, penumbraFilterSlope);
|
||||
_penumbraFilter.setParameters(0, 1, SAMPLE_RATE, penumbraFilterFrequency, penumbraFilterGainR, penumbraFilterSlope);
|
||||
_penumbraFilter.render(_preMixSamples, _preMixSamples, NETWORK_BUFFER_LENGTH_SAMPLES_STEREO / 2);
|
||||
penumbraFilter.setParameters(0, 0, SAMPLE_RATE, penumbraFilterFrequency, penumbraFilterGainL, penumbraFilterSlope);
|
||||
penumbraFilter.setParameters(0, 1, SAMPLE_RATE, penumbraFilterFrequency, penumbraFilterGainR, penumbraFilterSlope);
|
||||
penumbraFilter.render(_preMixSamples, _preMixSamples, NETWORK_BUFFER_LENGTH_SAMPLES_STEREO / 2);
|
||||
}
|
||||
|
||||
// Actually mix the _preMixSamples into the _mixSamples here.
|
||||
|
@ -430,6 +433,7 @@ int AudioMixer::addStreamToMixForListeningNodeWithStream(PositionalAudioStream*
|
|||
|
||||
int AudioMixer::prepareMixForListeningNode(Node* node) {
|
||||
AvatarAudioStream* nodeAudioStream = ((AudioMixerClientData*) node->getLinkedData())->getAvatarAudioStream();
|
||||
AudioMixerClientData* listenerNodeData = (AudioMixerClientData*)node->getLinkedData();
|
||||
|
||||
// zero out the client mix for this node
|
||||
memset(_preMixSamples, 0, sizeof(_preMixSamples));
|
||||
|
@ -447,9 +451,15 @@ int AudioMixer::prepareMixForListeningNode(Node* node) {
|
|||
QHash<QUuid, PositionalAudioStream*>::ConstIterator i;
|
||||
for (i = otherNodeAudioStreams.constBegin(); i != otherNodeAudioStreams.constEnd(); i++) {
|
||||
PositionalAudioStream* otherNodeStream = i.value();
|
||||
QUuid streamUUID = i.key();
|
||||
|
||||
if (otherNodeStream->getType() == PositionalAudioStream::Microphone) {
|
||||
streamUUID = otherNode->getUUID();
|
||||
}
|
||||
|
||||
if (*otherNode != *node || otherNodeStream->shouldLoopbackForNode()) {
|
||||
streamsMixed += addStreamToMixForListeningNodeWithStream(otherNodeStream, nodeAudioStream);
|
||||
streamsMixed += addStreamToMixForListeningNodeWithStream(listenerNodeData, streamUUID,
|
||||
otherNodeStream, nodeAudioStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
class PositionalAudioStream;
|
||||
class AvatarAudioStream;
|
||||
class AudioMixerClientData;
|
||||
|
||||
const int SAMPLE_PHASE_DELAY_AT_90 = 20;
|
||||
|
||||
|
@ -46,8 +47,10 @@ public slots:
|
|||
|
||||
private:
|
||||
/// adds one stream to the mix for a listening node
|
||||
int addStreamToMixForListeningNodeWithStream(PositionalAudioStream* streamToAdd,
|
||||
AvatarAudioStream* listeningNodeStream);
|
||||
int addStreamToMixForListeningNodeWithStream(AudioMixerClientData* listenerNodeData,
|
||||
const QUuid& streamUUID,
|
||||
PositionalAudioStream* streamToAdd,
|
||||
AvatarAudioStream* listeningNodeStream);
|
||||
|
||||
/// prepares and sends a mix to one Node
|
||||
int prepareMixForListeningNode(Node* node);
|
||||
|
|
|
@ -33,6 +33,11 @@ AudioMixerClientData::~AudioMixerClientData() {
|
|||
// delete this attached InboundAudioStream
|
||||
delete i.value();
|
||||
}
|
||||
|
||||
// clean up our pair data...
|
||||
foreach(PerListenerSourcePairData* pairData, _listenerSourcePairData) {
|
||||
delete pairData;
|
||||
}
|
||||
}
|
||||
|
||||
AvatarAudioStream* AudioMixerClientData::getAvatarAudioStream() const {
|
||||
|
@ -302,3 +307,12 @@ void AudioMixerClientData::printAudioStreamStats(const AudioStreamStats& streamS
|
|||
formatUsecTime(streamStats._timeGapWindowMax).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,26 @@
|
|||
#define hifi_AudioMixerClientData_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 "AvatarAudioStream.h"
|
||||
|
||||
class PerListenerSourcePairData {
|
||||
public:
|
||||
PerListenerSourcePairData() {
|
||||
const int SAMPLE_PHASE_DELAY_AT_90 = 20;
|
||||
_penumbraFilter.initialize(SAMPLE_RATE, (NETWORK_BUFFER_LENGTH_SAMPLES_STEREO + (SAMPLE_PHASE_DELAY_AT_90 * 2)) / 2);
|
||||
};
|
||||
AudioFilterHSF1s& getPenumbraFilter() { return _penumbraFilter; }
|
||||
|
||||
private:
|
||||
AudioFilterHSF1s _penumbraFilter;
|
||||
};
|
||||
|
||||
class AudioMixerClientData : public NodeData {
|
||||
public:
|
||||
AudioMixerClientData();
|
||||
|
@ -40,12 +56,16 @@ public:
|
|||
|
||||
void printUpstreamDownstreamStats() const;
|
||||
|
||||
PerListenerSourcePairData* getListenerSourcePairData(const QUuid& sourceUUID);
|
||||
private:
|
||||
void printAudioStreamStats(const AudioStreamStats& streamStats) const;
|
||||
|
||||
private:
|
||||
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;
|
||||
|
||||
AudioStreamStats _downstreamAudioStreamStats;
|
||||
|
|
Loading…
Reference in a new issue