Replace Gverb with new reverb

This commit is contained in:
Ken Cooke 2015-11-18 09:16:18 -08:00
parent 0f214555c1
commit c61dad108c
2 changed files with 114 additions and 82 deletions

View file

@ -119,7 +119,7 @@ AudioClient::AudioClient() :
_audioSourceInjectEnabled(false),
_reverb(false),
_reverbOptions(&_scriptReverbOptions),
_gverb(NULL),
//_gverb(NULL),
_inputToNetworkResampler(NULL),
_networkToOutputResampler(NULL),
_loopbackResampler(NULL),
@ -145,8 +145,8 @@ AudioClient::AudioClient() :
updateTimer->start(DEVICE_CHECK_INTERVAL_MSECS);
// create GVerb filter
_gverb = createGverbFilter();
configureGverbFilter(_gverb);
//_gverb = createGverbFilter();
configureReverb();
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
packetReceiver.registerListener(PacketType::AudioStreamStats, &_stats, "processStreamStatsPacket");
@ -160,9 +160,9 @@ AudioClient::AudioClient() :
AudioClient::~AudioClient() {
stop();
if (_gverb) {
gverb_free(_gverb);
}
//if (_gverb) {
// gverb_free(_gverb);
//}
}
void AudioClient::reset() {
@ -173,7 +173,8 @@ void AudioClient::reset() {
_sourceGain.reset();
_inputGain.reset();
gverb_flush(_gverb);
//gverb_flush(_gverb);
_stereoReverb.reset();
}
void AudioClient::audioMixerKilled() {
@ -568,27 +569,42 @@ bool AudioClient::switchOutputToAudioDevice(const QString& outputDeviceName) {
return switchOutputToAudioDevice(getNamedAudioDeviceForMode(QAudio::AudioOutput, outputDeviceName));
}
ty_gverb* AudioClient::createGverbFilter() {
// Initialize a new gverb instance
ty_gverb* filter = gverb_new(_outputFormat.sampleRate(), _reverbOptions->getMaxRoomSize(), _reverbOptions->getRoomSize(),
_reverbOptions->getReverbTime(), _reverbOptions->getDamping(), _reverbOptions->getSpread(),
_reverbOptions->getInputBandwidth(), _reverbOptions->getEarlyLevel(),
_reverbOptions->getTailLevel());
//ty_gverb* AudioClient::createGverbFilter() {
// // Initialize a new gverb instance
// ty_gverb* filter = gverb_new(_outputFormat.sampleRate(), _reverbOptions->getMaxRoomSize(), _reverbOptions->getRoomSize(),
// _reverbOptions->getReverbTime(), _reverbOptions->getDamping(), _reverbOptions->getSpread(),
// _reverbOptions->getInputBandwidth(), _reverbOptions->getEarlyLevel(),
// _reverbOptions->getTailLevel());
//
// return filter;
//}
return filter;
}
void AudioClient::configureGverbFilter(ty_gverb* filter) {
void AudioClient::configureReverb() {
// Configure the instance (these functions are not super well named - they actually set several internal variables)
gverb_set_roomsize(filter, _reverbOptions->getRoomSize());
gverb_set_revtime(filter, _reverbOptions->getReverbTime());
gverb_set_damping(filter, _reverbOptions->getDamping());
gverb_set_inputbandwidth(filter, _reverbOptions->getInputBandwidth());
gverb_set_earlylevel(filter, DB_CO(_reverbOptions->getEarlyLevel()));
gverb_set_taillevel(filter, DB_CO(_reverbOptions->getTailLevel()));
//gverb_set_roomsize(filter, _reverbOptions->getRoomSize());
//gverb_set_revtime(filter, _reverbOptions->getReverbTime());
//gverb_set_damping(filter, _reverbOptions->getDamping());
//gverb_set_inputbandwidth(filter, _reverbOptions->getInputBandwidth());
//gverb_set_earlylevel(filter, DB_CO(_reverbOptions->getEarlyLevel()));
//gverb_set_taillevel(filter, DB_CO(_reverbOptions->getTailLevel()));
ReverbParameters p;
_stereoReverb.getParameters(&p);
// for now, use the gverb settings
p.sampleRate = _outputFormat.sampleRate();
p.roomSize = _reverbOptions->getRoomSize();
p.reverbTime = _reverbOptions->getReverbTime();
p.highGain = -24.0f * _reverbOptions->getDamping();
p.bandwidth = 12000.0f * _reverbOptions->getInputBandwidth();
//p.earlyGain = _reverbOptions->getEarlyLevel();
//p.lateGain = _reverbOptions->getTailLevel();
p.wetDryMix = _shouldEchoLocally ? DB_CO(_reverbOptions->getWetLevel()) : 100.0f; // !_shouldEchoLocally apparently means 100% wet?
_stereoReverb.setParameters(&p);
}
void AudioClient::updateGverbOptions() {
void AudioClient::updateReverbOptions() {
bool reverbChanged = false;
if (_receivedAudioStream.hasReverb()) {
@ -599,6 +615,7 @@ void AudioClient::updateGverbOptions() {
if (_zoneReverbOptions.getWetLevel() != _receivedAudioStream.getWetLevel()) {
_zoneReverbOptions.setWetLevel(_receivedAudioStream.getWetLevel());
// Not part of actual filter config, no need to set reverbChanged to true
reverbChanged = true;
}
if (_reverbOptions != &_zoneReverbOptions) {
@ -611,9 +628,9 @@ void AudioClient::updateGverbOptions() {
}
if (reverbChanged) {
gverb_free(_gverb);
_gverb = createGverbFilter();
configureGverbFilter(_gverb);
//gverb_free(_gverb);
//_gverb = createGverbFilter();
configureReverb();
}
}
@ -621,7 +638,8 @@ void AudioClient::setReverb(bool reverb) {
_reverb = reverb;
if (!_reverb) {
gverb_flush(_gverb);
//gverb_flush(_gverb);
_stereoReverb.reset();
}
}
@ -641,49 +659,49 @@ void AudioClient::setReverbOptions(const AudioEffectOptions* options) {
if (_reverbOptions == &_scriptReverbOptions) {
// Apply them to the reverb instances
gverb_free(_gverb);
_gverb = createGverbFilter();
configureGverbFilter(_gverb);
//gverb_free(_gverb);
//_gverb = createGverbFilter();
configureReverb();
}
}
void AudioClient::addReverb(ty_gverb* gverb, int16_t* samplesData, int16_t* reverbAlone, int numSamples,
QAudioFormat& audioFormat, bool noEcho) {
float wetFraction = DB_CO(_reverbOptions->getWetLevel());
float dryFraction = 1.0f - wetFraction;
float lValue,rValue;
for (int sample = 0; sample < numSamples; sample += audioFormat.channelCount()) {
// Run GVerb
float value = (float)samplesData[sample];
gverb_do(gverb, value, &lValue, &rValue);
// Mix, accounting for clipping, the left and right channels. Ignore the rest.
for (int j = sample; j < sample + audioFormat.channelCount(); j++) {
if (j == sample) {
// left channel
int lResult = glm::clamp((int)(samplesData[j] * dryFraction + lValue * wetFraction),
AudioConstants::MIN_SAMPLE_VALUE, AudioConstants::MAX_SAMPLE_VALUE);
samplesData[j] = (int16_t)lResult;
if (noEcho) {
reverbAlone[j] = (int16_t)lValue * wetFraction;
}
} else if (j == (sample + 1)) {
// right channel
int rResult = glm::clamp((int)(samplesData[j] * dryFraction + rValue * wetFraction),
AudioConstants::MIN_SAMPLE_VALUE, AudioConstants::MAX_SAMPLE_VALUE);
samplesData[j] = (int16_t)rResult;
if (noEcho) {
reverbAlone[j] = (int16_t)rValue * wetFraction;
}
} else {
// ignore channels above 2
}
}
}
}
//void AudioClient::addReverb(ty_gverb* gverb, int16_t* samplesData, int16_t* reverbAlone, int numSamples,
// QAudioFormat& audioFormat, bool noEcho) {
// float wetFraction = DB_CO(_reverbOptions->getWetLevel());
// float dryFraction = 1.0f - wetFraction;
//
// float lValue,rValue;
// for (int sample = 0; sample < numSamples; sample += audioFormat.channelCount()) {
// // Run GVerb
// float value = (float)samplesData[sample];
// gverb_do(gverb, value, &lValue, &rValue);
//
// // Mix, accounting for clipping, the left and right channels. Ignore the rest.
// for (int j = sample; j < sample + audioFormat.channelCount(); j++) {
// if (j == sample) {
// // left channel
// int lResult = glm::clamp((int)(samplesData[j] * dryFraction + lValue * wetFraction),
// AudioConstants::MIN_SAMPLE_VALUE, AudioConstants::MAX_SAMPLE_VALUE);
// samplesData[j] = (int16_t)lResult;
//
// if (noEcho) {
// reverbAlone[j] = (int16_t)lValue * wetFraction;
// }
// } else if (j == (sample + 1)) {
// // right channel
// int rResult = glm::clamp((int)(samplesData[j] * dryFraction + rValue * wetFraction),
// AudioConstants::MIN_SAMPLE_VALUE, AudioConstants::MAX_SAMPLE_VALUE);
// samplesData[j] = (int16_t)rResult;
//
// if (noEcho) {
// reverbAlone[j] = (int16_t)rValue * wetFraction;
// }
// } else {
// // ignore channels above 2
// }
// }
// }
//}
void AudioClient::handleLocalEchoAndReverb(QByteArray& inputByteArray) {
// If there is server echo, reverb will be applied to the recieved audio stream so no need to have it here.
@ -715,30 +733,42 @@ void AudioClient::handleLocalEchoAndReverb(QByteArray& inputByteArray) {
_loopbackResampler = new AudioSRC(_inputFormat.sampleRate(), _outputFormat.sampleRate(), channelCount);
}
static QByteArray reverbAlone; // Intermediary for local reverb with no echo
//static QByteArray reverbAlone; // Intermediary for local reverb with no echo
static QByteArray loopBackByteArray;
int numInputSamples = inputByteArray.size() / sizeof(int16_t);
int numLoopbackSamples = numDestinationSamplesRequired(_inputFormat, _outputFormat, numInputSamples);
reverbAlone.resize(numInputSamples * sizeof(int16_t));
//reverbAlone.resize(numInputSamples * sizeof(int16_t));
loopBackByteArray.resize(numLoopbackSamples * sizeof(int16_t));
int16_t* inputSamples = reinterpret_cast<int16_t*>(inputByteArray.data());
int16_t* reverbAloneSamples = reinterpret_cast<int16_t*>(reverbAlone.data());
//int16_t* reverbAloneSamples = reinterpret_cast<int16_t*>(reverbAlone.data());
int16_t* loopbackSamples = reinterpret_cast<int16_t*>(loopBackByteArray.data());
if (hasReverb) {
updateGverbOptions();
addReverb(_gverb, inputSamples, reverbAloneSamples, numInputSamples,
_inputFormat, !_shouldEchoLocally);
}
//if (hasReverb) {
// updateGverbOptions();
// addReverb(_gverb, inputSamples, reverbAloneSamples, numInputSamples,
// _inputFormat, !_shouldEchoLocally);
//}
//possibleResampling(_loopbackResampler,
// (_shouldEchoLocally) ? inputSamples : reverbAloneSamples, loopbackSamples,
// numInputSamples, numLoopbackSamples,
// _inputFormat, _outputFormat);
possibleResampling(_loopbackResampler,
(_shouldEchoLocally) ? inputSamples : reverbAloneSamples, loopbackSamples,
inputSamples, loopbackSamples,
numInputSamples, numLoopbackSamples,
_inputFormat, _outputFormat);
if (hasReverb) {
// always use the stereo reverb output
assert(_outputFormat.channelCount() == 2);
updateReverbOptions();
_stereoReverb.render(loopbackSamples, loopbackSamples, numLoopbackSamples/2);
}
_loopbackOutputDevice->write(loopBackByteArray);
}

View file

@ -46,6 +46,7 @@
#include "AudioIOStats.h"
#include "AudioNoiseGate.h"
#include "AudioSRC.h"
#include "AudioReverb.h"
#ifdef _WIN32
#pragma warning( push )
@ -262,7 +263,8 @@ private:
AudioEffectOptions _scriptReverbOptions;
AudioEffectOptions _zoneReverbOptions;
AudioEffectOptions* _reverbOptions;
ty_gverb* _gverb;
//ty_gverb* _gverb;
AudioReverb _stereoReverb { AudioConstants::SAMPLE_RATE };
// possible streams needed for resample
AudioSRC* _inputToNetworkResampler;
@ -270,10 +272,10 @@ private:
AudioSRC* _loopbackResampler;
// Adds Reverb
ty_gverb* createGverbFilter();
void configureGverbFilter(ty_gverb* filter);
void updateGverbOptions();
void addReverb(ty_gverb* gverb, int16_t* samples, int16_t* reverbAlone, int numSamples, QAudioFormat& format, bool noEcho = false);
//ty_gverb* createGverbFilter();
void configureReverb();
void updateReverbOptions();
//void addReverb(ty_gverb* gverb, int16_t* samples, int16_t* reverbAlone, int numSamples, QAudioFormat& format, bool noEcho = false);
void handleLocalEchoAndReverb(QByteArray& inputByteArray);