mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 07:10:06 +02:00
complete piping of stereo audio through mixer
This commit is contained in:
parent
681ce247d6
commit
ae2f6a3cb6
8 changed files with 160 additions and 117 deletions
|
@ -174,12 +174,15 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const int16_t* nextOutputStart = bufferToAdd->getNextOutput();
|
||||||
|
|
||||||
|
if (!bufferToAdd->isStereo()) {
|
||||||
|
// this is a mono buffer, 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
|
// 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 delayedChannelOffset = (bearingRelativeAngleToSource > 0.0f) ? 1 : 0;
|
||||||
int goodChannelOffset = delayedChannelOffset == 0 ? 1 : 0;
|
int goodChannelOffset = delayedChannelOffset == 0 ? 1 : 0;
|
||||||
|
|
||||||
const int16_t* nextOutputStart = bufferToAdd->getNextOutput();
|
|
||||||
|
|
||||||
const int16_t* bufferStart = bufferToAdd->getBuffer();
|
const int16_t* bufferStart = bufferToAdd->getBuffer();
|
||||||
int ringBufferSampleCapacity = bufferToAdd->getSampleCapacity();
|
int ringBufferSampleCapacity = bufferToAdd->getSampleCapacity();
|
||||||
|
|
||||||
|
@ -303,6 +306,29 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf
|
||||||
_clientSamples[parentIndex + delayedChannelOffset] = shortResults[3];
|
_clientSamples[parentIndex + delayedChannelOffset] = shortResults[3];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// stereo buffer - do attenuation but no sample delay for spatialization
|
||||||
|
qDebug() << "Adding a stereo buffer";
|
||||||
|
|
||||||
|
for (int s = 0; s < NETWORK_BUFFER_LENGTH_SAMPLES_STEREO; s += 4) {
|
||||||
|
// use MMX to clamp four additions at a time
|
||||||
|
|
||||||
|
__m64 bufferSamples = _mm_set_pi16(_clientSamples[s], _clientSamples[s + 1],
|
||||||
|
_clientSamples[s + 2], _clientSamples[s + 3]);
|
||||||
|
__m64 addSamples = _mm_set_pi16(nextOutputStart[s] * attenuationCoefficient,
|
||||||
|
nextOutputStart[s + 1] * attenuationCoefficient,
|
||||||
|
nextOutputStart[s + 2] * attenuationCoefficient,
|
||||||
|
nextOutputStart[s + 3] * attenuationCoefficient);
|
||||||
|
|
||||||
|
__m64 mmxResult = _mm_adds_pi16(bufferSamples, addSamples);
|
||||||
|
int16_t* shortResults = reinterpret_cast<int16_t*>(&mmxResult);
|
||||||
|
|
||||||
|
_clientSamples[s] = shortResults[3];
|
||||||
|
_clientSamples[s + 1] = shortResults[2];
|
||||||
|
_clientSamples[s + 2] = shortResults[1];
|
||||||
|
_clientSamples[s + 3] = shortResults[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioMixer::prepareMixForListeningNode(Node* node) {
|
void AudioMixer::prepareMixForListeningNode(Node* node) {
|
||||||
|
|
|
@ -51,9 +51,21 @@ int AudioMixerClientData::parseData(const QByteArray& packet) {
|
||||||
// grab the AvatarAudioRingBuffer from the vector (or create it if it doesn't exist)
|
// grab the AvatarAudioRingBuffer from the vector (or create it if it doesn't exist)
|
||||||
AvatarAudioRingBuffer* avatarRingBuffer = getAvatarAudioRingBuffer();
|
AvatarAudioRingBuffer* avatarRingBuffer = getAvatarAudioRingBuffer();
|
||||||
|
|
||||||
|
// read the first byte after the header to see if this is a stereo or mono buffer
|
||||||
|
quint8 channelFlag = packet.at(numBytesForPacketHeader(packet));
|
||||||
|
bool isStereo = channelFlag == 1;
|
||||||
|
|
||||||
|
if (avatarRingBuffer && avatarRingBuffer->isStereo() != isStereo) {
|
||||||
|
// there's a mismatch in the buffer channels for the incoming and current buffer
|
||||||
|
// so delete our current buffer and create a new one
|
||||||
|
_ringBuffers.removeOne(avatarRingBuffer);
|
||||||
|
avatarRingBuffer->deleteLater();
|
||||||
|
avatarRingBuffer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!avatarRingBuffer) {
|
if (!avatarRingBuffer) {
|
||||||
// we don't have an AvatarAudioRingBuffer yet, so add it
|
// we don't have an AvatarAudioRingBuffer yet, so add it
|
||||||
avatarRingBuffer = new AvatarAudioRingBuffer();
|
avatarRingBuffer = new AvatarAudioRingBuffer(isStereo);
|
||||||
_ringBuffers.push_back(avatarRingBuffer);
|
_ringBuffers.push_back(avatarRingBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,14 +24,14 @@ public:
|
||||||
AudioMixerClientData();
|
AudioMixerClientData();
|
||||||
~AudioMixerClientData();
|
~AudioMixerClientData();
|
||||||
|
|
||||||
const std::vector<PositionalAudioRingBuffer*> getRingBuffers() const { return _ringBuffers; }
|
const QList<PositionalAudioRingBuffer*> getRingBuffers() const { return _ringBuffers; }
|
||||||
AvatarAudioRingBuffer* getAvatarAudioRingBuffer() const;
|
AvatarAudioRingBuffer* getAvatarAudioRingBuffer() const;
|
||||||
|
|
||||||
int parseData(const QByteArray& packet);
|
int parseData(const QByteArray& packet);
|
||||||
void checkBuffersBeforeFrameSend(int jitterBufferLengthSamples);
|
void checkBuffersBeforeFrameSend(int jitterBufferLengthSamples);
|
||||||
void pushBuffersAfterFrameSend();
|
void pushBuffersAfterFrameSend();
|
||||||
private:
|
private:
|
||||||
std::vector<PositionalAudioRingBuffer*> _ringBuffers;
|
QList<PositionalAudioRingBuffer*> _ringBuffers;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_AudioMixerClientData_h
|
#endif // hifi_AudioMixerClientData_h
|
||||||
|
|
|
@ -13,8 +13,8 @@
|
||||||
|
|
||||||
#include "AvatarAudioRingBuffer.h"
|
#include "AvatarAudioRingBuffer.h"
|
||||||
|
|
||||||
AvatarAudioRingBuffer::AvatarAudioRingBuffer() :
|
AvatarAudioRingBuffer::AvatarAudioRingBuffer(bool isStereo) :
|
||||||
PositionalAudioRingBuffer(PositionalAudioRingBuffer::Microphone) {
|
PositionalAudioRingBuffer(PositionalAudioRingBuffer::Microphone, isStereo) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
class AvatarAudioRingBuffer : public PositionalAudioRingBuffer {
|
class AvatarAudioRingBuffer : public PositionalAudioRingBuffer {
|
||||||
public:
|
public:
|
||||||
AvatarAudioRingBuffer();
|
AvatarAudioRingBuffer(bool isStereo = false);
|
||||||
|
|
||||||
int parseData(const QByteArray& packet);
|
int parseData(const QByteArray& packet);
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -641,6 +641,9 @@ void Audio::handleAudioInput() {
|
||||||
|
|
||||||
char* currentPacketPtr = audioDataPacket + populatePacketHeader(audioDataPacket, packetType);
|
char* currentPacketPtr = audioDataPacket + populatePacketHeader(audioDataPacket, packetType);
|
||||||
|
|
||||||
|
// set the mono/stereo byte
|
||||||
|
*currentPacketPtr++ = isStereo;
|
||||||
|
|
||||||
// memcpy the three float positions
|
// memcpy the three float positions
|
||||||
memcpy(currentPacketPtr, &headPosition, sizeof(headPosition));
|
memcpy(currentPacketPtr, &headPosition, sizeof(headPosition));
|
||||||
currentPacketPtr += (sizeof(headPosition));
|
currentPacketPtr += (sizeof(headPosition));
|
||||||
|
@ -649,9 +652,6 @@ void Audio::handleAudioInput() {
|
||||||
memcpy(currentPacketPtr, &headOrientation, sizeof(headOrientation));
|
memcpy(currentPacketPtr, &headOrientation, sizeof(headOrientation));
|
||||||
currentPacketPtr += sizeof(headOrientation);
|
currentPacketPtr += sizeof(headOrientation);
|
||||||
|
|
||||||
// set the mono/stereo byte
|
|
||||||
*currentPacketPtr++ = isStereo;
|
|
||||||
|
|
||||||
nodeList->writeDatagram(audioDataPacket, numAudioBytes + leadingBytes, audioMixer);
|
nodeList->writeDatagram(audioDataPacket, numAudioBytes + leadingBytes, audioMixer);
|
||||||
|
|
||||||
Application::getInstance()->getBandwidthMeter()->outputStream(BandwidthMeter::AUDIO)
|
Application::getInstance()->getBandwidthMeter()->outputStream(BandwidthMeter::AUDIO)
|
||||||
|
|
|
@ -41,6 +41,9 @@ int PositionalAudioRingBuffer::parseData(const QByteArray& packet) {
|
||||||
// skip the packet header (includes the source UUID)
|
// skip the packet header (includes the source UUID)
|
||||||
int readBytes = numBytesForPacketHeader(packet);
|
int readBytes = numBytesForPacketHeader(packet);
|
||||||
|
|
||||||
|
// hop over the channel flag that has already been read in AudioMixerClientData
|
||||||
|
readBytes += sizeof(quint8);
|
||||||
|
// read the positional data
|
||||||
readBytes += parsePositionalData(packet.mid(readBytes));
|
readBytes += parsePositionalData(packet.mid(readBytes));
|
||||||
|
|
||||||
if (packetTypeForPacket(packet) == PacketTypeSilentAudioFrame) {
|
if (packetTypeForPacket(packet) == PacketTypeSilentAudioFrame) {
|
||||||
|
|
|
@ -41,6 +41,8 @@ public:
|
||||||
|
|
||||||
bool shouldLoopbackForNode() const { return _shouldLoopbackForNode; }
|
bool shouldLoopbackForNode() const { return _shouldLoopbackForNode; }
|
||||||
|
|
||||||
|
bool isStereo() const { return _isStereo; }
|
||||||
|
|
||||||
PositionalAudioRingBuffer::Type getType() const { return _type; }
|
PositionalAudioRingBuffer::Type getType() const { return _type; }
|
||||||
const glm::vec3& getPosition() const { return _position; }
|
const glm::vec3& getPosition() const { return _position; }
|
||||||
const glm::quat& getOrientation() const { return _orientation; }
|
const glm::quat& getOrientation() const { return _orientation; }
|
||||||
|
|
Loading…
Reference in a new issue