mirror of
https://github.com/overte-org/overte.git
synced 2025-06-25 23:49:43 +02:00
resolve conflicts on merge with upstream/master
This commit is contained in:
commit
31b136f807
10 changed files with 185 additions and 90 deletions
|
@ -47,6 +47,7 @@ Agent::Agent(const QByteArray& packet) :
|
||||||
_scriptEngine.getEntityScriptingInterface()->setPacketSender(&_entityEditSender);
|
_scriptEngine.getEntityScriptingInterface()->setPacketSender(&_entityEditSender);
|
||||||
|
|
||||||
DependencyManager::set<ResouceCacheSharedItems>();
|
DependencyManager::set<ResouceCacheSharedItems>();
|
||||||
|
DependencyManager::set<SoundCache>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Agent::readPendingDatagrams() {
|
void Agent::readPendingDatagrams() {
|
||||||
|
|
|
@ -136,7 +136,6 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) :
|
||||||
|
|
||||||
// Create Singleton objects on main thread
|
// Create Singleton objects on main thread
|
||||||
NetworkAccessManager::getInstance();
|
NetworkAccessManager::getInstance();
|
||||||
auto soundCache = DependencyManager::get<SoundCache>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssignmentClient::sendAssignmentRequest() {
|
void AssignmentClient::sendAssignmentRequest() {
|
||||||
|
|
|
@ -479,10 +479,20 @@ void AudioMixer::sendAudioEnvironmentPacket(SharedNodePointer node) {
|
||||||
for (int i = 0; i < _zoneReverbSettings.size(); ++i) {
|
for (int i = 0; i < _zoneReverbSettings.size(); ++i) {
|
||||||
AudioMixerClientData* data = static_cast<AudioMixerClientData*>(node->getLinkedData());
|
AudioMixerClientData* data = static_cast<AudioMixerClientData*>(node->getLinkedData());
|
||||||
glm::vec3 streamPosition = data->getAvatarAudioStream()->getPosition();
|
glm::vec3 streamPosition = data->getAvatarAudioStream()->getPosition();
|
||||||
if (_audioZones[_zoneReverbSettings[i].zone].contains(streamPosition)) {
|
AABox box = _audioZones[_zoneReverbSettings[i].zone];
|
||||||
|
if (box.contains(streamPosition)) {
|
||||||
hasReverb = true;
|
hasReverb = true;
|
||||||
reverbTime = _zoneReverbSettings[i].reverbTime;
|
reverbTime = _zoneReverbSettings[i].reverbTime;
|
||||||
wetLevel = _zoneReverbSettings[i].wetLevel;
|
wetLevel = _zoneReverbSettings[i].wetLevel;
|
||||||
|
|
||||||
|
// Modulate wet level with distance to wall
|
||||||
|
float MIN_ATTENUATION_DISTANCE = 2.0f;
|
||||||
|
float MAX_ATTENUATION = -12; // dB
|
||||||
|
glm::vec3 distanceToWalls = (box.getDimensions() / 2.0f) - glm::abs(streamPosition - box.calcCenter());
|
||||||
|
float distanceToClosestWall = glm::min(distanceToWalls.x, distanceToWalls.z);
|
||||||
|
if (distanceToClosestWall < MIN_ATTENUATION_DISTANCE) {
|
||||||
|
wetLevel += MAX_ATTENUATION * (1.0f - distanceToClosestWall / MIN_ATTENUATION_DISTANCE);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2
cmake/externals/gverb/CMakeLists.txt
vendored
2
cmake/externals/gverb/CMakeLists.txt
vendored
|
@ -7,7 +7,7 @@ endif ()
|
||||||
include(ExternalProject)
|
include(ExternalProject)
|
||||||
ExternalProject_Add(
|
ExternalProject_Add(
|
||||||
${EXTERNAL_NAME}
|
${EXTERNAL_NAME}
|
||||||
GIT_REPOSITORY https://github.com/birarda/gverb.git
|
URL http://hifi-public.s3.amazonaws.com/dependencies/gverb-master.zip
|
||||||
CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
|
CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
|
||||||
LOG_DOWNLOAD ON
|
LOG_DOWNLOAD ON
|
||||||
)
|
)
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
Script.include("../../libraries/globals.js");
|
Script.include("../../libraries/globals.js");
|
||||||
Script.include("../../libraries/virtualKeyboard.js");
|
Script.include("../../libraries/virtualKeyboard.js");
|
||||||
|
Script.include("../../libraries/soundArray.js");
|
||||||
|
|
||||||
const MAX_SHOW_INSTRUCTION_TIMES = 2;
|
const MAX_SHOW_INSTRUCTION_TIMES = 2;
|
||||||
const INSTRUCTIONS_SETTING = "GoToInstructionsShowCounter"
|
const INSTRUCTIONS_SETTING = "GoToInstructionsShowCounter"
|
||||||
|
@ -82,6 +83,12 @@ var textFontSize = 9;
|
||||||
var text = null;
|
var text = null;
|
||||||
var locationURL = "";
|
var locationURL = "";
|
||||||
|
|
||||||
|
var randomSounds = new SoundArray({}, true);
|
||||||
|
var numberOfSounds = 7;
|
||||||
|
for (var i = 1; i <= numberOfSounds; i++) {
|
||||||
|
randomSounds.addSound(HIFI_PUBLIC_BUCKET + "sounds/UI/virtualKeyboard-press" + i + ".raw");
|
||||||
|
}
|
||||||
|
|
||||||
function appendChar(char) {
|
function appendChar(char) {
|
||||||
locationURL += char;
|
locationURL += char;
|
||||||
updateTextOverlay();
|
updateTextOverlay();
|
||||||
|
@ -107,6 +114,7 @@ function updateTextOverlay() {
|
||||||
}
|
}
|
||||||
|
|
||||||
keyboard.onKeyPress = function(event) {
|
keyboard.onKeyPress = function(event) {
|
||||||
|
randomSounds.playRandom();
|
||||||
if (event.event == 'keypress') {
|
if (event.event == 'keypress') {
|
||||||
appendChar(event.char);
|
appendChar(event.char);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
Script.include("../../libraries/globals.js");
|
Script.include("../../libraries/globals.js");
|
||||||
Script.include("../../libraries/virtualKeyboard.js");
|
Script.include("../../libraries/virtualKeyboard.js");
|
||||||
|
Script.include("../../libraries/soundArray.js");
|
||||||
|
|
||||||
const SPAWN_DISTANCE = 1;
|
const SPAWN_DISTANCE = 1;
|
||||||
const DEFAULT_TEXT_DIMENSION_Z = 0.02;
|
const DEFAULT_TEXT_DIMENSION_Z = 0.02;
|
||||||
|
@ -34,6 +35,12 @@ var text = null;
|
||||||
var textText = "";
|
var textText = "";
|
||||||
var textSizeMeasureOverlay = Overlays.addOverlay("text3d", {visible: false});
|
var textSizeMeasureOverlay = Overlays.addOverlay("text3d", {visible: false});
|
||||||
|
|
||||||
|
var randomSounds = new SoundArray({}, true);
|
||||||
|
var numberOfSounds = 7;
|
||||||
|
for (var i = 1; i <= numberOfSounds; i++) {
|
||||||
|
randomSounds.addSound(HIFI_PUBLIC_BUCKET + "sounds/UI/virtualKeyboard-press" + i + ".raw");
|
||||||
|
}
|
||||||
|
|
||||||
function appendChar(char) {
|
function appendChar(char) {
|
||||||
textText += char;
|
textText += char;
|
||||||
updateTextOverlay();
|
updateTextOverlay();
|
||||||
|
@ -58,6 +65,7 @@ function updateTextOverlay() {
|
||||||
}
|
}
|
||||||
|
|
||||||
keyboard.onKeyPress = function(event) {
|
keyboard.onKeyPress = function(event) {
|
||||||
|
randomSounds.playRandom();
|
||||||
if (event.event == 'keypress') {
|
if (event.event == 'keypress') {
|
||||||
appendChar(event.char);
|
appendChar(event.char);
|
||||||
} else if (event.event == 'enter') {
|
} else if (event.event == 'enter') {
|
||||||
|
|
42
examples/libraries/soundArray.js
Normal file
42
examples/libraries/soundArray.js
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/**
|
||||||
|
* An array for sounds, allows you to randomly play a sound
|
||||||
|
* taken from the removed editVoxels.js
|
||||||
|
*/
|
||||||
|
SoundArray = function(audioOptions, autoUpdateAudioPosition) {
|
||||||
|
this.audioOptions = audioOptions !== undefined ? audioOptions : {};
|
||||||
|
this.autoUpdateAudioPosition = autoUpdateAudioPosition !== undefined ? autoUpdateAudioPosition : false;
|
||||||
|
if (this.audioOptions.position === undefined) {
|
||||||
|
this.audioOptions.position = Vec3.sum(MyAvatar.position, { x: 0, y: 1, z: 0}),
|
||||||
|
}
|
||||||
|
if (this.audioOptions.volume === undefined) {
|
||||||
|
this.audioOptions.volume = 1.0;
|
||||||
|
}
|
||||||
|
this.sounds = new Array();
|
||||||
|
this.addSound = function (soundURL) {
|
||||||
|
this.sounds[this.sounds.length] = SoundCache.getSound(soundURL);
|
||||||
|
};
|
||||||
|
this.play = function (index) {
|
||||||
|
if (0 <= index && index < this.sounds.length) {
|
||||||
|
if (this.autoUpdateAudioPosition) {
|
||||||
|
this.updateAudioPosition();
|
||||||
|
}
|
||||||
|
if (this.sounds[index].downloaded) {
|
||||||
|
Audio.playSound(this.sounds[index], this.audioOptions);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print("[ERROR] libraries/soundArray.js:play() : Index " + index + " out of range.");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.playRandom = function () {
|
||||||
|
if (this.sounds.length > 0) {
|
||||||
|
this.play(Math.floor(Math.random() * this.sounds.length));
|
||||||
|
} else {
|
||||||
|
print("[ERROR] libraries/soundArray.js:playRandom() : Array is empty.");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.updateAudioPosition = function() {
|
||||||
|
var position = MyAvatar.position;
|
||||||
|
var forwardVector = Quat.getFront(MyAvatar.orientation);
|
||||||
|
this.audioOptions.position = Vec3.sum(position, forwardVector);
|
||||||
|
};
|
||||||
|
};
|
|
@ -57,6 +57,8 @@
|
||||||
// var welcome = "There are " + GlobalServices.onlineUsers.length + " users online now.";
|
// var welcome = "There are " + GlobalServices.onlineUsers.length + " users online now.";
|
||||||
// createNotification(welcome);
|
// createNotification(welcome);
|
||||||
// }
|
// }
|
||||||
|
Script.include("./libraries/globals.js");
|
||||||
|
Script.include("./libraries/soundArray.js");
|
||||||
|
|
||||||
var width = 340.0; //width of notification overlay
|
var width = 340.0; //width of notification overlay
|
||||||
var windowDimensions = Controller.getViewportDimensions(); // get the size of the interface window
|
var windowDimensions = Controller.getViewportDimensions(); // get the size of the interface window
|
||||||
|
@ -81,6 +83,22 @@ var last_users = GlobalServices.onlineUsers;
|
||||||
var users = [];
|
var users = [];
|
||||||
var ctrlIsPressed = false;
|
var ctrlIsPressed = false;
|
||||||
var ready = true;
|
var ready = true;
|
||||||
|
|
||||||
|
var randomSounds = new SoundArray({}, true);
|
||||||
|
var numberOfSounds = 2;
|
||||||
|
for (var i = 1; i <= numberOfSounds; i++) {
|
||||||
|
randomSounds.addSound(HIFI_PUBLIC_BUCKET + "sounds/UI/notification-general" + i + ".raw");
|
||||||
|
}
|
||||||
|
|
||||||
|
// When our script shuts down, we should clean up all of our overlays
|
||||||
|
function scriptEnding() {
|
||||||
|
for (i = 0; i < notifications.length; i++) {
|
||||||
|
Overlays.deleteOverlay(notifications[i]);
|
||||||
|
Overlays.deleteOverlay(buttons[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Script.scriptEnding.connect(scriptEnding);
|
||||||
|
|
||||||
var notifications = [];
|
var notifications = [];
|
||||||
var buttons = [];
|
var buttons = [];
|
||||||
var times = [];
|
var times = [];
|
||||||
|
@ -193,6 +211,8 @@ function notify(notice, button, height) {
|
||||||
positions,
|
positions,
|
||||||
last;
|
last;
|
||||||
|
|
||||||
|
randomSounds.playRandom();
|
||||||
|
|
||||||
if (isOnHMD) {
|
if (isOnHMD) {
|
||||||
// Calculate 3D values from 2D overlay properties.
|
// Calculate 3D values from 2D overlay properties.
|
||||||
|
|
||||||
|
@ -454,7 +474,6 @@ function onOnlineUsersChanged(users) {
|
||||||
if (last_users.indexOf(users[i]) === -1.0) {
|
if (last_users.indexOf(users[i]) === -1.0) {
|
||||||
createNotification(users[i] + " has joined");
|
createNotification(users[i] + " has joined");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < last_users.length; i += 1) {
|
for (i = 0; i < last_users.length; i += 1) {
|
||||||
|
|
|
@ -109,7 +109,6 @@ AudioClient::AudioClient() :
|
||||||
_audioSourceInjectEnabled(false),
|
_audioSourceInjectEnabled(false),
|
||||||
_reverb(false),
|
_reverb(false),
|
||||||
_reverbOptions(&_scriptReverbOptions),
|
_reverbOptions(&_scriptReverbOptions),
|
||||||
_gverbLocal(NULL),
|
|
||||||
_gverb(NULL),
|
_gverb(NULL),
|
||||||
_inputToNetworkResampler(NULL),
|
_inputToNetworkResampler(NULL),
|
||||||
_networkToOutputResampler(NULL),
|
_networkToOutputResampler(NULL),
|
||||||
|
@ -127,25 +126,22 @@ AudioClient::AudioClient() :
|
||||||
connect(&_receivedAudioStream, &MixedProcessedAudioStream::processSamples,
|
connect(&_receivedAudioStream, &MixedProcessedAudioStream::processSamples,
|
||||||
this, &AudioClient::processReceivedSamples, Qt::DirectConnection);
|
this, &AudioClient::processReceivedSamples, Qt::DirectConnection);
|
||||||
|
|
||||||
// Initialize GVerb
|
|
||||||
initGverb();
|
|
||||||
|
|
||||||
const qint64 DEVICE_CHECK_INTERVAL_MSECS = 2 * 1000;
|
|
||||||
|
|
||||||
_inputDevices = getDeviceNames(QAudio::AudioInput);
|
_inputDevices = getDeviceNames(QAudio::AudioInput);
|
||||||
_outputDevices = getDeviceNames(QAudio::AudioOutput);
|
_outputDevices = getDeviceNames(QAudio::AudioOutput);
|
||||||
|
|
||||||
|
const qint64 DEVICE_CHECK_INTERVAL_MSECS = 2 * 1000;
|
||||||
QTimer* updateTimer = new QTimer(this);
|
QTimer* updateTimer = new QTimer(this);
|
||||||
connect(updateTimer, &QTimer::timeout, this, &AudioClient::checkDevices);
|
connect(updateTimer, &QTimer::timeout, this, &AudioClient::checkDevices);
|
||||||
updateTimer->start(DEVICE_CHECK_INTERVAL_MSECS);
|
updateTimer->start(DEVICE_CHECK_INTERVAL_MSECS);
|
||||||
|
|
||||||
|
// create GVerb filter
|
||||||
|
_gverb = createGverbFilter();
|
||||||
|
configureGverbFilter(_gverb);
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioClient::~AudioClient() {
|
AudioClient::~AudioClient() {
|
||||||
stop();
|
stop();
|
||||||
|
|
||||||
if (_gverbLocal) {
|
|
||||||
gverb_free(_gverbLocal);
|
|
||||||
}
|
|
||||||
if (_gverb) {
|
if (_gverb) {
|
||||||
gverb_free(_gverb);
|
gverb_free(_gverb);
|
||||||
}
|
}
|
||||||
|
@ -158,6 +154,8 @@ void AudioClient::reset() {
|
||||||
_toneSource.reset();
|
_toneSource.reset();
|
||||||
_sourceGain.reset();
|
_sourceGain.reset();
|
||||||
_inputGain.reset();
|
_inputGain.reset();
|
||||||
|
|
||||||
|
gverb_flush(_gverb);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioClient::audioMixerKilled() {
|
void AudioClient::audioMixerKilled() {
|
||||||
|
@ -535,38 +533,24 @@ bool AudioClient::switchOutputToAudioDevice(const QString& outputDeviceName) {
|
||||||
return switchOutputToAudioDevice(getNamedAudioDeviceForMode(QAudio::AudioOutput, outputDeviceName));
|
return switchOutputToAudioDevice(getNamedAudioDeviceForMode(QAudio::AudioOutput, outputDeviceName));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioClient::initGverb() {
|
ty_gverb* AudioClient::createGverbFilter() {
|
||||||
// Initialize a new gverb instance
|
// Initialize a new gverb instance
|
||||||
if (_gverbLocal) {
|
ty_gverb* filter = gverb_new(_outputFormat.sampleRate(), _reverbOptions->getMaxRoomSize(), _reverbOptions->getRoomSize(),
|
||||||
gverb_free(_gverbLocal);
|
|
||||||
}
|
|
||||||
_gverbLocal = gverb_new(_outputFormat.sampleRate(), _reverbOptions->getMaxRoomSize(), _reverbOptions->getRoomSize(),
|
|
||||||
_reverbOptions->getReverbTime(), _reverbOptions->getDamping(), _reverbOptions->getSpread(),
|
_reverbOptions->getReverbTime(), _reverbOptions->getDamping(), _reverbOptions->getSpread(),
|
||||||
_reverbOptions->getInputBandwidth(), _reverbOptions->getEarlyLevel(),
|
_reverbOptions->getInputBandwidth(), _reverbOptions->getEarlyLevel(),
|
||||||
_reverbOptions->getTailLevel());
|
_reverbOptions->getTailLevel());
|
||||||
|
|
||||||
if (_gverb) {
|
return filter;
|
||||||
gverb_free(_gverb);
|
|
||||||
}
|
}
|
||||||
_gverb = gverb_new(_outputFormat.sampleRate(), _reverbOptions->getMaxRoomSize(), _reverbOptions->getRoomSize(),
|
|
||||||
_reverbOptions->getReverbTime(), _reverbOptions->getDamping(), _reverbOptions->getSpread(),
|
|
||||||
_reverbOptions->getInputBandwidth(), _reverbOptions->getEarlyLevel(),
|
|
||||||
_reverbOptions->getTailLevel());
|
|
||||||
|
|
||||||
|
void AudioClient::configureGverbFilter(ty_gverb* filter) {
|
||||||
// Configure the instance (these functions are not super well named - they actually set several internal variables)
|
// Configure the instance (these functions are not super well named - they actually set several internal variables)
|
||||||
gverb_set_roomsize(_gverbLocal, _reverbOptions->getRoomSize());
|
gverb_set_roomsize(filter, _reverbOptions->getRoomSize());
|
||||||
gverb_set_revtime(_gverbLocal, _reverbOptions->getReverbTime());
|
gverb_set_revtime(filter, _reverbOptions->getReverbTime());
|
||||||
gverb_set_damping(_gverbLocal, _reverbOptions->getDamping());
|
gverb_set_damping(filter, _reverbOptions->getDamping());
|
||||||
gverb_set_inputbandwidth(_gverbLocal, _reverbOptions->getInputBandwidth());
|
gverb_set_inputbandwidth(filter, _reverbOptions->getInputBandwidth());
|
||||||
gverb_set_earlylevel(_gverbLocal, DB_CO(_reverbOptions->getEarlyLevel()));
|
gverb_set_earlylevel(filter, DB_CO(_reverbOptions->getEarlyLevel()));
|
||||||
gverb_set_taillevel(_gverbLocal, DB_CO(_reverbOptions->getTailLevel()));
|
gverb_set_taillevel(filter, DB_CO(_reverbOptions->getTailLevel()));
|
||||||
|
|
||||||
gverb_set_roomsize(_gverb, _reverbOptions->getRoomSize());
|
|
||||||
gverb_set_revtime(_gverb, _reverbOptions->getReverbTime());
|
|
||||||
gverb_set_damping(_gverb, _reverbOptions->getDamping());
|
|
||||||
gverb_set_inputbandwidth(_gverb, _reverbOptions->getInputBandwidth());
|
|
||||||
gverb_set_earlylevel(_gverb, DB_CO(_reverbOptions->getEarlyLevel()));
|
|
||||||
gverb_set_taillevel(_gverb, DB_CO(_reverbOptions->getTailLevel()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioClient::updateGverbOptions() {
|
void AudioClient::updateGverbOptions() {
|
||||||
|
@ -579,7 +563,7 @@ void AudioClient::updateGverbOptions() {
|
||||||
}
|
}
|
||||||
if (_zoneReverbOptions.getWetLevel() != _receivedAudioStream.getWetLevel()) {
|
if (_zoneReverbOptions.getWetLevel() != _receivedAudioStream.getWetLevel()) {
|
||||||
_zoneReverbOptions.setWetLevel(_receivedAudioStream.getWetLevel());
|
_zoneReverbOptions.setWetLevel(_receivedAudioStream.getWetLevel());
|
||||||
reverbChanged = true;
|
// Not part of actual filter config, no need to set reverbChanged to true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_reverbOptions != &_zoneReverbOptions) {
|
if (_reverbOptions != &_zoneReverbOptions) {
|
||||||
|
@ -592,7 +576,17 @@ void AudioClient::updateGverbOptions() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reverbChanged) {
|
if (reverbChanged) {
|
||||||
initGverb();
|
gverb_free(_gverb);
|
||||||
|
_gverb = createGverbFilter();
|
||||||
|
configureGverbFilter(_gverb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioClient::setReverb(bool reverb) {
|
||||||
|
_reverb = reverb;
|
||||||
|
|
||||||
|
if (!_reverb) {
|
||||||
|
gverb_flush(_gverb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -611,14 +605,17 @@ void AudioClient::setReverbOptions(const AudioEffectOptions* options) {
|
||||||
_scriptReverbOptions.setWetLevel(options->getWetLevel());
|
_scriptReverbOptions.setWetLevel(options->getWetLevel());
|
||||||
|
|
||||||
if (_reverbOptions == &_scriptReverbOptions) {
|
if (_reverbOptions == &_scriptReverbOptions) {
|
||||||
// Apply them to the reverb instance(s)
|
// Apply them to the reverb instances
|
||||||
initGverb();
|
gverb_free(_gverb);
|
||||||
|
_gverb = createGverbFilter();
|
||||||
|
configureGverbFilter(_gverb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioClient::addReverb(ty_gverb* gverb, int16_t* samplesData, int numSamples, QAudioFormat& audioFormat, bool noEcho) {
|
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 wetFraction = DB_CO(_reverbOptions->getWetLevel());
|
||||||
float dryFraction = (noEcho) ? 0.0f : (1.0f - wetFraction);
|
float dryFraction = 1.0f - wetFraction;
|
||||||
|
|
||||||
float lValue,rValue;
|
float lValue,rValue;
|
||||||
for (int sample = 0; sample < numSamples; sample += audioFormat.channelCount()) {
|
for (int sample = 0; sample < numSamples; sample += audioFormat.channelCount()) {
|
||||||
|
@ -633,11 +630,19 @@ void AudioClient::addReverb(ty_gverb* gverb, int16_t* samplesData, int numSample
|
||||||
int lResult = glm::clamp((int)(samplesData[j] * dryFraction + lValue * wetFraction),
|
int lResult = glm::clamp((int)(samplesData[j] * dryFraction + lValue * wetFraction),
|
||||||
AudioConstants::MIN_SAMPLE_VALUE, AudioConstants::MAX_SAMPLE_VALUE);
|
AudioConstants::MIN_SAMPLE_VALUE, AudioConstants::MAX_SAMPLE_VALUE);
|
||||||
samplesData[j] = (int16_t)lResult;
|
samplesData[j] = (int16_t)lResult;
|
||||||
|
|
||||||
|
if (noEcho) {
|
||||||
|
reverbAlone[j] = (int16_t)lValue * wetFraction;
|
||||||
|
}
|
||||||
} else if (j == (sample + 1)) {
|
} else if (j == (sample + 1)) {
|
||||||
// right channel
|
// right channel
|
||||||
int rResult = glm::clamp((int)(samplesData[j] * dryFraction + rValue * wetFraction),
|
int rResult = glm::clamp((int)(samplesData[j] * dryFraction + rValue * wetFraction),
|
||||||
AudioConstants::MIN_SAMPLE_VALUE, AudioConstants::MAX_SAMPLE_VALUE);
|
AudioConstants::MIN_SAMPLE_VALUE, AudioConstants::MAX_SAMPLE_VALUE);
|
||||||
samplesData[j] = (int16_t)rResult;
|
samplesData[j] = (int16_t)rResult;
|
||||||
|
|
||||||
|
if (noEcho) {
|
||||||
|
reverbAlone[j] = (int16_t)rValue * wetFraction;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// ignore channels above 2
|
// ignore channels above 2
|
||||||
}
|
}
|
||||||
|
@ -647,9 +652,8 @@ void AudioClient::addReverb(ty_gverb* gverb, int16_t* samplesData, int numSample
|
||||||
|
|
||||||
void AudioClient::handleLocalEchoAndReverb(QByteArray& inputByteArray) {
|
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.
|
// If there is server echo, reverb will be applied to the recieved audio stream so no need to have it here.
|
||||||
bool hasLocalReverb = (_reverb || _receivedAudioStream.hasReverb()) &&
|
bool hasReverb = _reverb || _receivedAudioStream.hasReverb();
|
||||||
!_shouldEchoToServer;
|
if (_muted || !_audioOutput || (!_shouldEchoLocally && !hasReverb)) {
|
||||||
if (_muted || !_audioOutput || (!_shouldEchoLocally && !hasLocalReverb)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -659,6 +663,10 @@ void AudioClient::handleLocalEchoAndReverb(QByteArray& inputByteArray) {
|
||||||
if (!_loopbackOutputDevice && _loopbackAudioOutput) {
|
if (!_loopbackOutputDevice && _loopbackAudioOutput) {
|
||||||
// we didn't have the loopback output device going so set that up now
|
// we didn't have the loopback output device going so set that up now
|
||||||
_loopbackOutputDevice = _loopbackAudioOutput->start();
|
_loopbackOutputDevice = _loopbackAudioOutput->start();
|
||||||
|
|
||||||
|
if (!_loopbackOutputDevice) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// do we need to setup a resampler?
|
// do we need to setup a resampler?
|
||||||
|
@ -671,27 +679,32 @@ void AudioClient::handleLocalEchoAndReverb(QByteArray& inputByteArray) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QByteArray reverbAlone; // Intermediary for local reverb with no echo
|
||||||
static QByteArray loopBackByteArray;
|
static QByteArray loopBackByteArray;
|
||||||
loopBackByteArray.resize(numDestinationSamplesRequired(_inputFormat, _outputFormat,
|
|
||||||
inputByteArray.size() / sizeof(int16_t)) * sizeof(int16_t));
|
int numInputSamples = inputByteArray.size() / sizeof(int16_t);
|
||||||
|
int numLoopbackSamples = numDestinationSamplesRequired(_inputFormat, _outputFormat, numInputSamples);
|
||||||
|
|
||||||
|
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* loopbackSamples = reinterpret_cast<int16_t*>(loopBackByteArray.data());
|
||||||
|
|
||||||
|
if (hasReverb) {
|
||||||
|
updateGverbOptions();
|
||||||
|
addReverb(_gverb, inputSamples, reverbAloneSamples, numInputSamples,
|
||||||
|
_inputFormat, !_shouldEchoLocally);
|
||||||
|
}
|
||||||
|
|
||||||
possibleResampling(_loopbackResampler,
|
possibleResampling(_loopbackResampler,
|
||||||
reinterpret_cast<int16_t*>(inputByteArray.data()),
|
(_shouldEchoLocally) ? inputSamples : reverbAloneSamples, loopbackSamples,
|
||||||
reinterpret_cast<int16_t*>(loopBackByteArray.data()),
|
numInputSamples, numLoopbackSamples,
|
||||||
inputByteArray.size() / sizeof(int16_t), loopBackByteArray.size() / sizeof(int16_t),
|
|
||||||
_inputFormat, _outputFormat);
|
_inputFormat, _outputFormat);
|
||||||
|
|
||||||
if (hasLocalReverb) {
|
|
||||||
int16_t* loopbackSamples = reinterpret_cast<int16_t*>(loopBackByteArray.data());
|
|
||||||
int numLoopbackSamples = loopBackByteArray.size() / sizeof(int16_t);
|
|
||||||
updateGverbOptions();
|
|
||||||
addReverb(_gverbLocal, loopbackSamples, numLoopbackSamples, _outputFormat, !_shouldEchoLocally);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_loopbackOutputDevice) {
|
|
||||||
_loopbackOutputDevice->write(loopBackByteArray);
|
_loopbackOutputDevice->write(loopBackByteArray);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void AudioClient::handleAudioInput() {
|
void AudioClient::handleAudioInput() {
|
||||||
static char audioDataPacket[MAX_PACKET_SIZE];
|
static char audioDataPacket[MAX_PACKET_SIZE];
|
||||||
|
@ -884,11 +897,6 @@ void AudioClient::processReceivedSamples(const QByteArray& inputBuffer, QByteArr
|
||||||
reinterpret_cast<int16_t*>(outputBuffer.data()),
|
reinterpret_cast<int16_t*>(outputBuffer.data()),
|
||||||
numNetworkOutputSamples, numDeviceOutputSamples,
|
numNetworkOutputSamples, numDeviceOutputSamples,
|
||||||
_desiredOutputFormat, _outputFormat);
|
_desiredOutputFormat, _outputFormat);
|
||||||
|
|
||||||
if(_reverb || _receivedAudioStream.hasReverb()) {
|
|
||||||
updateGverbOptions();
|
|
||||||
addReverb(_gverb, (int16_t*)outputBuffer.data(), numDeviceOutputSamples, _outputFormat);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioClient::sendMuteEnvironmentPacket() {
|
void AudioClient::sendMuteEnvironmentPacket() {
|
||||||
|
|
|
@ -166,7 +166,7 @@ public slots:
|
||||||
|
|
||||||
float getInputVolume() const { return (_audioInput) ? _audioInput->volume() : 0.0f; }
|
float getInputVolume() const { return (_audioInput) ? _audioInput->volume() : 0.0f; }
|
||||||
void setInputVolume(float volume) { if (_audioInput) _audioInput->setVolume(volume); }
|
void setInputVolume(float volume) { if (_audioInput) _audioInput->setVolume(volume); }
|
||||||
void setReverb(bool reverb) { _reverb = reverb; }
|
void setReverb(bool reverb);
|
||||||
void setReverbOptions(const AudioEffectOptions* options);
|
void setReverbOptions(const AudioEffectOptions* options);
|
||||||
|
|
||||||
void outputNotify();
|
void outputNotify();
|
||||||
|
@ -241,7 +241,6 @@ private:
|
||||||
AudioEffectOptions _scriptReverbOptions;
|
AudioEffectOptions _scriptReverbOptions;
|
||||||
AudioEffectOptions _zoneReverbOptions;
|
AudioEffectOptions _zoneReverbOptions;
|
||||||
AudioEffectOptions* _reverbOptions;
|
AudioEffectOptions* _reverbOptions;
|
||||||
ty_gverb* _gverbLocal;
|
|
||||||
ty_gverb* _gverb;
|
ty_gverb* _gverb;
|
||||||
|
|
||||||
// possible soxr streams needed for resample
|
// possible soxr streams needed for resample
|
||||||
|
@ -250,9 +249,10 @@ private:
|
||||||
soxr* _loopbackResampler;
|
soxr* _loopbackResampler;
|
||||||
|
|
||||||
// Adds Reverb
|
// Adds Reverb
|
||||||
void initGverb();
|
ty_gverb* createGverbFilter();
|
||||||
|
void configureGverbFilter(ty_gverb* filter);
|
||||||
void updateGverbOptions();
|
void updateGverbOptions();
|
||||||
void addReverb(ty_gverb* gverb, int16_t* samples, int numSamples, QAudioFormat& format, bool noEcho = false);
|
void addReverb(ty_gverb* gverb, int16_t* samples, int16_t* reverbAlone, int numSamples, QAudioFormat& format, bool noEcho = false);
|
||||||
|
|
||||||
void handleLocalEchoAndReverb(QByteArray& inputByteArray);
|
void handleLocalEchoAndReverb(QByteArray& inputByteArray);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue