mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 12:37:51 +02:00
Partial support for floating-point audio output
This commit is contained in:
parent
98699885f4
commit
784b23d05c
2 changed files with 73 additions and 29 deletions
|
@ -433,8 +433,21 @@ bool adjustedFormatForAudioDevice(const QAudioDeviceInfo& audioDevice,
|
||||||
for (int channelCount : (desiredAudioFormat.channelCount() == 1 ? inputChannels : outputChannels)) {
|
for (int channelCount : (desiredAudioFormat.channelCount() == 1 ? inputChannels : outputChannels)) {
|
||||||
for (int sampleRate : sampleRates) {
|
for (int sampleRate : sampleRates) {
|
||||||
|
|
||||||
|
// int16_t samples
|
||||||
adjustedAudioFormat.setChannelCount(channelCount);
|
adjustedAudioFormat.setChannelCount(channelCount);
|
||||||
adjustedAudioFormat.setSampleRate(sampleRate);
|
adjustedAudioFormat.setSampleRate(sampleRate);
|
||||||
|
adjustedAudioFormat.setSampleSize(16);
|
||||||
|
adjustedAudioFormat.setSampleType(QAudioFormat::SignedInt);
|
||||||
|
|
||||||
|
if (audioDevice.isFormatSupported(adjustedAudioFormat)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// float samples
|
||||||
|
adjustedAudioFormat.setChannelCount(channelCount);
|
||||||
|
adjustedAudioFormat.setSampleRate(sampleRate);
|
||||||
|
adjustedAudioFormat.setSampleSize(32);
|
||||||
|
adjustedAudioFormat.setSampleType(QAudioFormat::Float);
|
||||||
|
|
||||||
if (audioDevice.isFormatSupported(adjustedAudioFormat)) {
|
if (audioDevice.isFormatSupported(adjustedAudioFormat)) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -1545,11 +1558,15 @@ float AudioClient::gainForSource(float distance, float volume) {
|
||||||
return gain;
|
return gain;
|
||||||
}
|
}
|
||||||
|
|
||||||
qint64 AudioClient::AudioOutputIODevice::readData(char * data, qint64 maxSize) {
|
qint64 AudioClient::AudioOutputIODevice::readData(char* data, qint64 maxSize) {
|
||||||
|
|
||||||
|
// data can be int16_t* or float*
|
||||||
|
int sampleSize = _audio->_outputFormat.sampleSize() / 8;
|
||||||
|
bool isFloat = _audio->_outputFormat.sampleType() == QAudioFormat::SampleType::Float;
|
||||||
|
|
||||||
// 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 / sampleSize) * OUTPUT_CHANNEL_COUNT / deviceChannelCount;
|
||||||
|
|
||||||
int samplesPopped;
|
int samplesPopped;
|
||||||
int bytesWritten;
|
int bytesWritten;
|
||||||
|
@ -1559,14 +1576,24 @@ qint64 AudioClient::AudioOutputIODevice::readData(char * data, qint64 maxSize) {
|
||||||
AudioRingBuffer::ConstIterator lastPopOutput = _receivedAudioStream.getLastPopOutput();
|
AudioRingBuffer::ConstIterator lastPopOutput = _receivedAudioStream.getLastPopOutput();
|
||||||
|
|
||||||
// if required, upmix or downmix to deviceChannelCount
|
// if required, upmix or downmix to deviceChannelCount
|
||||||
if (deviceChannelCount == OUTPUT_CHANNEL_COUNT) {
|
if (isFloat) {
|
||||||
lastPopOutput.readSamples((int16_t*)data, samplesPopped);
|
if (deviceChannelCount == OUTPUT_CHANNEL_COUNT) {
|
||||||
} else if (deviceChannelCount > OUTPUT_CHANNEL_COUNT) {
|
lastPopOutput.readSamples((float*)data, samplesPopped);
|
||||||
lastPopOutput.readSamplesWithUpmix((int16_t*)data, samplesPopped, deviceChannelCount - OUTPUT_CHANNEL_COUNT);
|
} else if (deviceChannelCount > OUTPUT_CHANNEL_COUNT) {
|
||||||
|
lastPopOutput.readSamplesWithUpmix((float*)data, samplesPopped, deviceChannelCount - OUTPUT_CHANNEL_COUNT);
|
||||||
|
} else {
|
||||||
|
lastPopOutput.readSamplesWithDownmix((float*)data, samplesPopped);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
lastPopOutput.readSamplesWithDownmix((int16_t*)data, samplesPopped);
|
if (deviceChannelCount == OUTPUT_CHANNEL_COUNT) {
|
||||||
|
lastPopOutput.readSamples((int16_t*)data, samplesPopped);
|
||||||
|
} else if (deviceChannelCount > OUTPUT_CHANNEL_COUNT) {
|
||||||
|
lastPopOutput.readSamplesWithUpmix((int16_t*)data, samplesPopped, deviceChannelCount - OUTPUT_CHANNEL_COUNT);
|
||||||
|
} else {
|
||||||
|
lastPopOutput.readSamplesWithDownmix((int16_t*)data, samplesPopped);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
bytesWritten = (samplesPopped * AudioConstants::SAMPLE_SIZE) * deviceChannelCount / OUTPUT_CHANNEL_COUNT;
|
bytesWritten = (samplesPopped * sampleSize) * deviceChannelCount / OUTPUT_CHANNEL_COUNT;
|
||||||
} else {
|
} else {
|
||||||
// nothing on network, don't grab anything from injectors, and just return 0s
|
// nothing on network, don't grab anything from injectors, and just return 0s
|
||||||
// this will flood the log: qCDebug(audioclient, "empty/partial network buffer");
|
// this will flood the log: qCDebug(audioclient, "empty/partial network buffer");
|
||||||
|
|
|
@ -103,10 +103,11 @@ public:
|
||||||
ConstIterator operator+(int i);
|
ConstIterator operator+(int i);
|
||||||
ConstIterator operator-(int i);
|
ConstIterator operator-(int i);
|
||||||
|
|
||||||
void readSamples(int16_t* dest, int numSamples);
|
// dest can be int16_t* or float*
|
||||||
void readSamplesWithFade(int16_t* dest, int numSamples, float fade);
|
template<typename T> void readSamples(T* dest, int numSamples);
|
||||||
void readSamplesWithUpmix(int16_t* dest, int numSamples, int numExtraChannels);
|
template<typename T> void readSamplesWithFade(T* dest, int numSamples, float fade);
|
||||||
void readSamplesWithDownmix(int16_t* dest, int numSamples);
|
template<typename T> void readSamplesWithUpmix(T* dest, int numSamples, int numExtraChannels);
|
||||||
|
template<typename T> void readSamplesWithDownmix(T* dest, int numSamples);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int16_t* atShiftedBy(int i);
|
int16_t* atShiftedBy(int i);
|
||||||
|
@ -203,6 +204,28 @@ inline int16_t* AudioRingBuffer::ConstIterator::atShiftedBy(int i) {
|
||||||
return _bufferFirst + i;
|
return _bufferFirst + i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline AudioRingBuffer::ConstIterator AudioRingBuffer::nextOutput() const {
|
||||||
|
return ConstIterator(_buffer, _bufferLength, _nextOutput);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline AudioRingBuffer::ConstIterator AudioRingBuffer::lastFrameWritten() const {
|
||||||
|
return ConstIterator(_buffer, _bufferLength, _endOfLastWrite) - _numFrameSamples;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// dest can be int16_t* or float*
|
||||||
|
//
|
||||||
|
template<typename T>
|
||||||
|
inline void AudioRingBuffer::ConstIterator::readSamples(T* dest, int numSamples) {
|
||||||
|
int16_t* at = _at;
|
||||||
|
for (int i = 0; i < numSamples; i++) {
|
||||||
|
*dest++ = (T)*at;
|
||||||
|
at = (at == _bufferLast) ? _bufferFirst : at + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fast path for int16_t*
|
||||||
|
template<>
|
||||||
inline void AudioRingBuffer::ConstIterator::readSamples(int16_t* dest, int numSamples) {
|
inline void AudioRingBuffer::ConstIterator::readSamples(int16_t* dest, int numSamples) {
|
||||||
auto samplesToEnd = _bufferLast - _at + 1;
|
auto samplesToEnd = _bufferLast - _at + 1;
|
||||||
|
|
||||||
|
@ -218,16 +241,17 @@ inline void AudioRingBuffer::ConstIterator::readSamples(int16_t* dest, int numSa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void AudioRingBuffer::ConstIterator::readSamplesWithFade(int16_t* dest, int numSamples, float fade) {
|
template<typename T>
|
||||||
|
inline void AudioRingBuffer::ConstIterator::readSamplesWithFade(T* dest, int numSamples, float fade) {
|
||||||
int16_t* at = _at;
|
int16_t* at = _at;
|
||||||
for (int i = 0; i < numSamples; i++) {
|
for (int i = 0; i < numSamples; i++) {
|
||||||
*dest = (float)*at * fade;
|
*dest++ = (T)(*at * fade);
|
||||||
++dest;
|
|
||||||
at = (at == _bufferLast) ? _bufferFirst : at + 1;
|
at = (at == _bufferLast) ? _bufferFirst : at + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void AudioRingBuffer::ConstIterator::readSamplesWithUpmix(int16_t* dest, int numSamples, int numExtraChannels) {
|
template<typename T>
|
||||||
|
inline void AudioRingBuffer::ConstIterator::readSamplesWithUpmix(T* dest, int numSamples, int numExtraChannels) {
|
||||||
int16_t* at = _at;
|
int16_t* at = _at;
|
||||||
for (int i = 0; i < numSamples/2; i++) {
|
for (int i = 0; i < numSamples/2; i++) {
|
||||||
|
|
||||||
|
@ -238,15 +262,16 @@ inline void AudioRingBuffer::ConstIterator::readSamplesWithUpmix(int16_t* dest,
|
||||||
at = (at == _bufferLast) ? _bufferFirst : at + 1;
|
at = (at == _bufferLast) ? _bufferFirst : at + 1;
|
||||||
|
|
||||||
// write 2 + N samples
|
// write 2 + N samples
|
||||||
*dest++ = left;
|
*dest++ = (T)left;
|
||||||
*dest++ = right;
|
*dest++ = (T)right;
|
||||||
for (int n = 0; n < numExtraChannels; n++) {
|
for (int n = 0; n < numExtraChannels; n++) {
|
||||||
*dest++ = 0;
|
*dest++ = (T)0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void AudioRingBuffer::ConstIterator::readSamplesWithDownmix(int16_t* dest, int numSamples) {
|
template<typename T>
|
||||||
|
inline void AudioRingBuffer::ConstIterator::readSamplesWithDownmix(T* dest, int numSamples) {
|
||||||
int16_t* at = _at;
|
int16_t* at = _at;
|
||||||
for (int i = 0; i < numSamples/2; i++) {
|
for (int i = 0; i < numSamples/2; i++) {
|
||||||
|
|
||||||
|
@ -257,16 +282,8 @@ inline void AudioRingBuffer::ConstIterator::readSamplesWithDownmix(int16_t* dest
|
||||||
at = (at == _bufferLast) ? _bufferFirst : at + 1;
|
at = (at == _bufferLast) ? _bufferFirst : at + 1;
|
||||||
|
|
||||||
// write 1 sample
|
// write 1 sample
|
||||||
*dest++ = (int16_t)((left + right) / 2);
|
*dest++ = (T)((left + right) / 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline AudioRingBuffer::ConstIterator AudioRingBuffer::nextOutput() const {
|
|
||||||
return ConstIterator(_buffer, _bufferLength, _nextOutput);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline AudioRingBuffer::ConstIterator AudioRingBuffer::lastFrameWritten() const {
|
|
||||||
return ConstIterator(_buffer, _bufferLength, _endOfLastWrite) - _numFrameSamples;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // hifi_AudioRingBuffer_h
|
#endif // hifi_AudioRingBuffer_h
|
||||||
|
|
Loading…
Reference in a new issue