mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 12:49:34 +02:00
Merge branch 'master' of github.com:highfidelity/hifi into nut
This commit is contained in:
commit
7c477740d3
3 changed files with 57 additions and 43 deletions
|
@ -1869,6 +1869,7 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo outputDeviceI
|
||||||
if (_audioOutput) {
|
if (_audioOutput) {
|
||||||
_audioOutputIODevice.close();
|
_audioOutputIODevice.close();
|
||||||
_audioOutput->stop();
|
_audioOutput->stop();
|
||||||
|
_audioOutputInitialized = false;
|
||||||
|
|
||||||
//must be deleted in next eventloop cycle when its called from notify()
|
//must be deleted in next eventloop cycle when its called from notify()
|
||||||
_audioOutput->deleteLater();
|
_audioOutput->deleteLater();
|
||||||
|
@ -1939,52 +1940,50 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo outputDeviceI
|
||||||
int requestedSize = _sessionOutputBufferSizeFrames * frameSize * AudioConstants::SAMPLE_SIZE;
|
int requestedSize = _sessionOutputBufferSizeFrames * frameSize * AudioConstants::SAMPLE_SIZE;
|
||||||
_audioOutput->setBufferSize(requestedSize);
|
_audioOutput->setBufferSize(requestedSize);
|
||||||
|
|
||||||
// initialize mix buffers on the _audioOutput thread to avoid races
|
|
||||||
connect(_audioOutput, &QAudioOutput::stateChanged, [&, frameSize, requestedSize](QAudio::State state) {
|
|
||||||
if (state == QAudio::ActiveState) {
|
|
||||||
// restrict device callback to _outputPeriod samples
|
|
||||||
_outputPeriod = _audioOutput->periodSize() / AudioConstants::SAMPLE_SIZE;
|
|
||||||
// device callback may exceed reported period, so double it to avoid stutter
|
|
||||||
_outputPeriod *= 2;
|
|
||||||
|
|
||||||
_outputMixBuffer = new float[_outputPeriod];
|
|
||||||
_outputScratchBuffer = new int16_t[_outputPeriod];
|
|
||||||
|
|
||||||
// size local output mix buffer based on resampled network frame size
|
|
||||||
int networkPeriod = _localToOutputResampler ? _localToOutputResampler->getMaxOutput(AudioConstants::NETWORK_FRAME_SAMPLES_STEREO) : AudioConstants::NETWORK_FRAME_SAMPLES_STEREO;
|
|
||||||
_localOutputMixBuffer = new float[networkPeriod];
|
|
||||||
|
|
||||||
// local period should be at least twice the output period,
|
|
||||||
// in case two device reads happen before more data can be read (worst case)
|
|
||||||
int localPeriod = _outputPeriod * 2;
|
|
||||||
// round up to an exact multiple of networkPeriod
|
|
||||||
localPeriod = ((localPeriod + networkPeriod - 1) / networkPeriod) * networkPeriod;
|
|
||||||
// this ensures lowest latency without stutter from underrun
|
|
||||||
_localInjectorsStream.resizeForFrameSize(localPeriod);
|
|
||||||
|
|
||||||
int bufferSize = _audioOutput->bufferSize();
|
|
||||||
int bufferSamples = bufferSize / AudioConstants::SAMPLE_SIZE;
|
|
||||||
int bufferFrames = bufferSamples / (float)frameSize;
|
|
||||||
qCDebug(audioclient) << "frame (samples):" << frameSize;
|
|
||||||
qCDebug(audioclient) << "buffer (frames):" << bufferFrames;
|
|
||||||
qCDebug(audioclient) << "buffer (samples):" << bufferSamples;
|
|
||||||
qCDebug(audioclient) << "buffer (bytes):" << bufferSize;
|
|
||||||
qCDebug(audioclient) << "requested (bytes):" << requestedSize;
|
|
||||||
qCDebug(audioclient) << "period (samples):" << _outputPeriod;
|
|
||||||
qCDebug(audioclient) << "local buffer (samples):" << localPeriod;
|
|
||||||
|
|
||||||
disconnect(_audioOutput, &QAudioOutput::stateChanged, 0, 0);
|
|
||||||
|
|
||||||
// unlock to avoid a deadlock with the device callback (which always succeeds this initialization)
|
|
||||||
localAudioLock.unlock();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
connect(_audioOutput, &QAudioOutput::notify, this, &AudioClient::outputNotify);
|
connect(_audioOutput, &QAudioOutput::notify, this, &AudioClient::outputNotify);
|
||||||
|
|
||||||
|
// start the output device
|
||||||
_audioOutputIODevice.start();
|
_audioOutputIODevice.start();
|
||||||
|
|
||||||
_audioOutput->start(&_audioOutputIODevice);
|
_audioOutput->start(&_audioOutputIODevice);
|
||||||
|
|
||||||
|
// initialize mix buffers
|
||||||
|
|
||||||
|
// restrict device callback to _outputPeriod samples
|
||||||
|
_outputPeriod = _audioOutput->periodSize() / AudioConstants::SAMPLE_SIZE;
|
||||||
|
// device callback may exceed reported period, so double it to avoid stutter
|
||||||
|
_outputPeriod *= 2;
|
||||||
|
|
||||||
|
_outputMixBuffer = new float[_outputPeriod];
|
||||||
|
_outputScratchBuffer = new int16_t[_outputPeriod];
|
||||||
|
|
||||||
|
// size local output mix buffer based on resampled network frame size
|
||||||
|
int networkPeriod = _localToOutputResampler ? _localToOutputResampler->getMaxOutput(AudioConstants::NETWORK_FRAME_SAMPLES_STEREO) : AudioConstants::NETWORK_FRAME_SAMPLES_STEREO;
|
||||||
|
_localOutputMixBuffer = new float[networkPeriod];
|
||||||
|
|
||||||
|
// local period should be at least twice the output period,
|
||||||
|
// in case two device reads happen before more data can be read (worst case)
|
||||||
|
int localPeriod = _outputPeriod * 2;
|
||||||
|
// round up to an exact multiple of networkPeriod
|
||||||
|
localPeriod = ((localPeriod + networkPeriod - 1) / networkPeriod) * networkPeriod;
|
||||||
|
// this ensures lowest latency without stutter from underrun
|
||||||
|
_localInjectorsStream.resizeForFrameSize(localPeriod);
|
||||||
|
|
||||||
|
_audioOutputInitialized = true;
|
||||||
|
|
||||||
|
int bufferSize = _audioOutput->bufferSize();
|
||||||
|
int bufferSamples = bufferSize / AudioConstants::SAMPLE_SIZE;
|
||||||
|
int bufferFrames = bufferSamples / (float)frameSize;
|
||||||
|
qCDebug(audioclient) << "frame (samples):" << frameSize;
|
||||||
|
qCDebug(audioclient) << "buffer (frames):" << bufferFrames;
|
||||||
|
qCDebug(audioclient) << "buffer (samples):" << bufferSamples;
|
||||||
|
qCDebug(audioclient) << "buffer (bytes):" << bufferSize;
|
||||||
|
qCDebug(audioclient) << "requested (bytes):" << requestedSize;
|
||||||
|
qCDebug(audioclient) << "period (samples):" << _outputPeriod;
|
||||||
|
qCDebug(audioclient) << "local buffer (samples):" << localPeriod;
|
||||||
|
|
||||||
|
// unlock to avoid a deadlock with the device callback (which always succeeds this initialization)
|
||||||
|
localAudioLock.unlock();
|
||||||
|
|
||||||
// setup a loopback audio output device
|
// setup a loopback audio output device
|
||||||
_loopbackAudioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this);
|
_loopbackAudioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this);
|
||||||
|
|
||||||
|
@ -2082,6 +2081,12 @@ float AudioClient::gainForSource(float distance, float volume) {
|
||||||
|
|
||||||
qint64 AudioClient::AudioOutputIODevice::readData(char * data, qint64 maxSize) {
|
qint64 AudioClient::AudioOutputIODevice::readData(char * data, qint64 maxSize) {
|
||||||
|
|
||||||
|
// lock-free wait for initialization to avoid races
|
||||||
|
if (!_audio->_audioOutputInitialized.load(std::memory_order_acquire)) {
|
||||||
|
memset(data, 0, maxSize);
|
||||||
|
return maxSize;
|
||||||
|
}
|
||||||
|
|
||||||
// samples requested from OUTPUT_CHANNEL_COUNT
|
// samples requested from OUTPUT_CHANNEL_COUNT
|
||||||
int deviceChannelCount = _audio->_outputFormat.channelCount();
|
int deviceChannelCount = _audio->_outputFormat.channelCount();
|
||||||
int samplesRequested = (int)(maxSize / AudioConstants::SAMPLE_SIZE) * OUTPUT_CHANNEL_COUNT / deviceChannelCount;
|
int samplesRequested = (int)(maxSize / AudioConstants::SAMPLE_SIZE) * OUTPUT_CHANNEL_COUNT / deviceChannelCount;
|
||||||
|
|
|
@ -340,6 +340,7 @@ private:
|
||||||
QIODevice* _inputDevice;
|
QIODevice* _inputDevice;
|
||||||
int _numInputCallbackBytes;
|
int _numInputCallbackBytes;
|
||||||
QAudioOutput* _audioOutput;
|
QAudioOutput* _audioOutput;
|
||||||
|
std::atomic<bool> _audioOutputInitialized { false };
|
||||||
QAudioFormat _desiredOutputFormat;
|
QAudioFormat _desiredOutputFormat;
|
||||||
QAudioFormat _outputFormat;
|
QAudioFormat _outputFormat;
|
||||||
int _outputFrameSize;
|
int _outputFrameSize;
|
||||||
|
|
|
@ -26,6 +26,14 @@ layout(location=0) in vec3 _normal;
|
||||||
layout(location=0) out vec4 _fragColor;
|
layout(location=0) out vec4 _fragColor;
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
vec3 skyboxColor = texture(cubeMap, normalize(_normal)).rgb;
|
// FIXME: For legacy reasons, when skybox.color.a is 0.5, this is equivalent to:
|
||||||
_fragColor = vec4(mix(skybox.color.rgb, skyboxColor, skybox.color.a), 1.0);
|
// skyboxColor * skyboxTexel
|
||||||
|
// It should actually be:
|
||||||
|
// mix(skyboxColor, skyboxTexel, skybox.color.a)
|
||||||
|
// and the blend factor should be user controlled
|
||||||
|
|
||||||
|
vec3 skyboxTexel = texture(cubeMap, normalize(_normal)).rgb;
|
||||||
|
vec3 skyboxColor = skybox.color.rgb;
|
||||||
|
_fragColor = vec4(mix(vec3(1.0), skyboxTexel, float(skybox.color.a > 0.0)) *
|
||||||
|
mix(vec3(1.0), skyboxColor, float(skybox.color.a < 1.0)), 1.0);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue