mirror of
https://github.com/overte-org/overte.git
synced 2025-08-12 13:34:02 +02:00
Merge pull request #1385 from birarda/master
audio fixes for clipping and off-axis
This commit is contained in:
commit
610d0f4680
3 changed files with 43 additions and 15 deletions
|
@ -164,7 +164,6 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf
|
|||
if ((s / 2) < numSamplesDelay) {
|
||||
// pull the earlier sample for the delayed channel
|
||||
int earlierSample = (*bufferToAdd)[(s / 2) - numSamplesDelay] * attenuationCoefficient * weakChannelAmplitudeRatio;
|
||||
|
||||
_clientSamples[s + delayedChannelOffset] = glm::clamp(_clientSamples[s + delayedChannelOffset] + earlierSample,
|
||||
MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE);
|
||||
}
|
||||
|
@ -175,11 +174,11 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf
|
|||
MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE);
|
||||
|
||||
if ((s / 2) + numSamplesDelay < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL) {
|
||||
// place the curernt sample at the right spot in the delayed channel
|
||||
int16_t clampedSample = glm::clamp((int) (_clientSamples[s + numSamplesDelay + delayedChannelOffset]
|
||||
// place the current sample at the right spot in the delayed channel
|
||||
int16_t clampedSample = glm::clamp((int) (_clientSamples[s + (numSamplesDelay * 2) + delayedChannelOffset]
|
||||
+ (currentSample * weakChannelAmplitudeRatio)),
|
||||
MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE);
|
||||
_clientSamples[s + numSamplesDelay + delayedChannelOffset] = clampedSample;
|
||||
_clientSamples[s + (numSamplesDelay * 2) + delayedChannelOffset] = clampedSample;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,6 +52,8 @@ Audio::Audio(Oscilloscope* scope, int16_t initialJitterBufferSamples, QObject* p
|
|||
_outputFormat(),
|
||||
_outputDevice(NULL),
|
||||
_numOutputCallbackBytes(0),
|
||||
_loopbackAudioOutput(NULL),
|
||||
_loopbackOutputDevice(NULL),
|
||||
_inputRingBuffer(0),
|
||||
_ringBuffer(NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL),
|
||||
_scope(scope),
|
||||
|
@ -201,19 +203,20 @@ void linearResampling(int16_t* sourceSamples, int16_t* destinationSamples,
|
|||
// upsample from 24 to 48
|
||||
// for now this only supports a stereo to stereo conversion - this is our case for network audio to output
|
||||
int sourceIndex = 0;
|
||||
int destinationToSourceFactor = (1 / sourceToDestinationFactor);
|
||||
int destinationToSourceFactor = (1 / sourceToDestinationFactor);
|
||||
int dtsSampleRateFactor = (destinationAudioFormat.sampleRate() / sourceAudioFormat.sampleRate());
|
||||
|
||||
for (int i = 0; i < numDestinationSamples; i += destinationAudioFormat.channelCount() * destinationToSourceFactor) {
|
||||
for (int i = 0; i < numDestinationSamples; i += destinationAudioFormat.channelCount() * dtsSampleRateFactor) {
|
||||
sourceIndex = (i / destinationToSourceFactor);
|
||||
|
||||
// fill the L/R channels and make the rest silent
|
||||
for (int j = i; j < i + (destinationToSourceFactor * destinationAudioFormat.channelCount()); j++) {
|
||||
for (int j = i; j < i + (dtsSampleRateFactor * destinationAudioFormat.channelCount()); j++) {
|
||||
if (j % destinationAudioFormat.channelCount() == 0) {
|
||||
// left channel
|
||||
destinationSamples[j] = sourceSamples[sourceIndex];
|
||||
} else if (j % destinationAudioFormat.channelCount() == 1) {
|
||||
// right channel
|
||||
destinationSamples[j] = sourceSamples[sourceIndex + 1];
|
||||
destinationSamples[j] = sourceSamples[sourceIndex + (sourceAudioFormat.channelCount() > 1 ? 1 : 0)];
|
||||
} else {
|
||||
// channels above 2, fill with silence
|
||||
destinationSamples[j] = 0;
|
||||
|
@ -263,9 +266,13 @@ void Audio::start() {
|
|||
_inputDevice = _audioInput->start();
|
||||
connect(_inputDevice, SIGNAL(readyRead()), this, SLOT(handleAudioInput()));
|
||||
|
||||
// setup our general output device for audio-mixer audio
|
||||
_audioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this);
|
||||
_outputDevice = _audioOutput->start();
|
||||
|
||||
// setup a loopback audio output device
|
||||
_loopbackAudioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this);
|
||||
|
||||
gettimeofday(&_lastReceiveTime, NULL);
|
||||
}
|
||||
|
||||
|
@ -290,6 +297,30 @@ void Audio::handleAudioInput() {
|
|||
|
||||
QByteArray inputByteArray = _inputDevice->readAll();
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::EchoLocalAudio)) {
|
||||
// if this person wants local loopback add that to the locally injected audio
|
||||
|
||||
if (!_loopbackOutputDevice) {
|
||||
// we didn't have the loopback output device going so set that up now
|
||||
_loopbackOutputDevice = _loopbackAudioOutput->start();
|
||||
}
|
||||
|
||||
if (_inputFormat == _outputFormat) {
|
||||
_loopbackOutputDevice->write(inputByteArray);
|
||||
} else {
|
||||
static float loopbackOutputToInputRatio = (_outputFormat.sampleRate() / (float) _inputFormat.sampleRate())
|
||||
* (_outputFormat.channelCount() / _inputFormat.channelCount());
|
||||
|
||||
QByteArray loopBackByteArray(inputByteArray.size() * loopbackOutputToInputRatio, 0);
|
||||
|
||||
linearResampling((int16_t*) inputByteArray.data(), (int16_t*) loopBackByteArray.data(),
|
||||
inputByteArray.size() / sizeof(int16_t),
|
||||
loopBackByteArray.size() / sizeof(int16_t), _inputFormat, _outputFormat);
|
||||
|
||||
_loopbackOutputDevice->write(loopBackByteArray);
|
||||
}
|
||||
}
|
||||
|
||||
_inputRingBuffer.writeData(inputByteArray.data(), inputByteArray.size());
|
||||
|
||||
while (_inputRingBuffer.samplesAvailable() > inputSamplesRequired) {
|
||||
|
@ -324,11 +355,6 @@ void Audio::handleAudioInput() {
|
|||
Q_ARG(QByteArray, QByteArray((char*) monoAudioSamples,
|
||||
NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL)),
|
||||
Q_ARG(bool, false), Q_ARG(bool, true));
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::EchoLocalAudio)) {
|
||||
// if this person wants local loopback add that to the locally injected audio
|
||||
memcpy(_localInjectedSamples, monoAudioSamples, NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL);
|
||||
}
|
||||
} else {
|
||||
// our input loudness is 0, since we're muted
|
||||
_lastInputLoudness = 0;
|
||||
|
@ -438,8 +464,8 @@ void Audio::addReceivedAudioToBuffer(const QByteArray& audioByteArray) {
|
|||
for (int i = 0; i < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; i++) {
|
||||
ringBufferSamples[i * 2] = glm::clamp(ringBufferSamples[i * 2] + _localInjectedSamples[i],
|
||||
MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE);
|
||||
ringBufferSamples[(i * 2) + 1] += glm::clamp(ringBufferSamples[(i * 2) + 1] + _localInjectedSamples[i],
|
||||
MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE);
|
||||
ringBufferSamples[(i * 2) + 1] = glm::clamp(ringBufferSamples[(i * 2) + 1] + _localInjectedSamples[i],
|
||||
MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE);
|
||||
}
|
||||
|
||||
// copy the packet from the RB to the output
|
||||
|
|
|
@ -78,8 +78,11 @@ private:
|
|||
QAudioFormat _outputFormat;
|
||||
QIODevice* _outputDevice;
|
||||
int _numOutputCallbackBytes;
|
||||
QAudioOutput* _loopbackAudioOutput;
|
||||
QIODevice* _loopbackOutputDevice;
|
||||
AudioRingBuffer _inputRingBuffer;
|
||||
AudioRingBuffer _ringBuffer;
|
||||
|
||||
Oscilloscope* _scope;
|
||||
StDev _stdev;
|
||||
timeval _lastReceiveTime;
|
||||
|
|
Loading…
Reference in a new issue