mirror of
https://github.com/lubosz/overte.git
synced 2025-04-09 05:03:52 +02:00
first pass audio mixer automatic muting of noisy streams, tour guide improvements, new lightExample.js, hair hangs over cone 'body'
This commit is contained in:
parent
a6c8fb7449
commit
688bd0f34f
12 changed files with 121 additions and 26 deletions
|
@ -61,8 +61,7 @@
|
|||
|
||||
const float LOUDNESS_TO_DISTANCE_RATIO = 0.00001f;
|
||||
const float DEFAULT_ATTENUATION_PER_DOUBLING_IN_DISTANCE = 0.18;
|
||||
const float DEFAULT_NOISE_MUTING_THRESHOLD = 100.0f;
|
||||
|
||||
const float DEFAULT_NOISE_MUTING_THRESHOLD = 0.003f;
|
||||
const QString AUDIO_MIXER_LOGGING_TARGET_NAME = "audio-mixer";
|
||||
const QString AUDIO_ENV_GROUP_KEY = "audio_env";
|
||||
const QString AUDIO_BUFFER_GROUP_KEY = "audio_buffer";
|
||||
|
@ -81,7 +80,6 @@ bool AudioMixer::_enableFilter = true;
|
|||
|
||||
bool AudioMixer::shouldMute(float quietestFrame, float loudestFrame) {
|
||||
return (quietestFrame > _noiseMutingThreshold);
|
||||
qDebug() << "Muting, quiestest frame = " << quietestFrame;
|
||||
}
|
||||
|
||||
AudioMixer::AudioMixer(const QByteArray& packet) :
|
||||
|
@ -1015,7 +1013,17 @@ void AudioMixer::parseSettingsObject(const QJsonObject &settingsObject) {
|
|||
qDebug() << "Attenuation per doubling in distance changed to" << _attenuationPerDoublingInDistance;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const QString NOISE_MUTING_THRESHOLD = "noise_muting_threshold";
|
||||
if (audioEnvGroupObject[NOISE_MUTING_THRESHOLD].isString()) {
|
||||
bool ok = false;
|
||||
float noiseMutingThreshold = audioEnvGroupObject[NOISE_MUTING_THRESHOLD].toString().toFloat(&ok);
|
||||
if (ok) {
|
||||
_noiseMutingThreshold = noiseMutingThreshold;
|
||||
qDebug() << "Noise muting threshold changed to" << _noiseMutingThreshold;
|
||||
}
|
||||
}
|
||||
|
||||
const QString FILTER_KEY = "enable_filter";
|
||||
if (audioEnvGroupObject[FILTER_KEY].isBool()) {
|
||||
_enableFilter = audioEnvGroupObject[FILTER_KEY].toBool();
|
||||
|
|
|
@ -89,6 +89,14 @@
|
|||
"default": "0.18",
|
||||
"advanced": false
|
||||
},
|
||||
{
|
||||
"name": "noise_muting_threshold",
|
||||
"label": "Noise Muting Threshold",
|
||||
"help": "Loudness value for noise background between 0 and 1.0 (0: mute everyone, 1.0: never mute)",
|
||||
"placeholder": "0.003",
|
||||
"default": "0.003",
|
||||
"advanced": false
|
||||
},
|
||||
{
|
||||
"name": "enable_filter",
|
||||
"type": "checkbox",
|
||||
|
|
|
@ -12,6 +12,8 @@ var MIN_CHANGE = 2.0;
|
|||
var LANDING_DISTANCE = 2.0;
|
||||
var LANDING_RANDOM = 0.2;
|
||||
|
||||
var relativePosition;
|
||||
|
||||
function update(deltaTime) {
|
||||
|
||||
if (Math.random() < deltaTime) {
|
||||
|
@ -26,20 +28,15 @@ function update(deltaTime) {
|
|||
}
|
||||
|
||||
if (guide) {
|
||||
relativePosition = Vec3.subtract(MyAvatar.position, lastGuidePosition);
|
||||
// Check whether guide has moved, update if so
|
||||
if (Vec3.length(lastGuidePosition) == 0.0) {
|
||||
lastGuidePosition = guide.position;
|
||||
} else {
|
||||
if (Vec3.length(Vec3.subtract(lastGuidePosition, guide.position)) > MIN_CHANGE) {
|
||||
var meToGuide = Vec3.multiply(Vec3.normalize(Vec3.subtract(guide.position, MyAvatar.position)), LANDING_DISTANCE);
|
||||
var newPosition = Vec3.subtract(guide.position, meToGuide);
|
||||
newPosition = Vec3.sum(newPosition, { x: Math.random() * LANDING_RANDOM - LANDING_RANDOM / 2.0,
|
||||
y: 0,
|
||||
z: Math.random() * LANDING_RANDOM - LANDING_RANDOM / 2.0 });
|
||||
var newPosition = Vec3.sum(guide.position, relativePosition);
|
||||
MyAvatar.position = newPosition;
|
||||
|
||||
lastGuidePosition = guide.position;
|
||||
MyAvatar.orientation = guide.orientation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
46
examples/lightExample.js
Normal file
46
examples/lightExample.js
Normal file
|
@ -0,0 +1,46 @@
|
|||
//
|
||||
// spotlightExample.js
|
||||
// examples
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 10/28/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// This is an example script that demonstrates creating and editing a particle
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
var position = Vec3.sum(MyAvatar.position, Quat.getFront(Camera.getOrientation()));
|
||||
|
||||
var sphereID = Entities.addEntity({
|
||||
type: "Sphere",
|
||||
position: position,
|
||||
dimensions: { x: 0.1, y: 0.1, z: 0.1 },
|
||||
color: { red: 255, green: 255, blue: 0 }
|
||||
});
|
||||
|
||||
var lightID = Entities.addEntity({
|
||||
type: "Light",
|
||||
position: position,
|
||||
dimensions: { x: 1, y: 1, z: 1 },
|
||||
angularVelocity: { x: 0, y: 0, z: 0 },
|
||||
angularDamping: 0,
|
||||
|
||||
isSpotlight: false,
|
||||
diffuseColor: { red: 255, green: 255, blue: 0 },
|
||||
ambientColor: { red: 0, green: 0, blue: 0 },
|
||||
specularColor: { red: 255, green: 255, blue: 255 },
|
||||
|
||||
constantAttenuation: 0,
|
||||
linearAttenuation: 1,
|
||||
quadraticAttenuation: 0,
|
||||
exponent: 0,
|
||||
cutoff: 180, // in degrees
|
||||
});
|
||||
|
||||
Script.scriptEnding.connect(function() {
|
||||
print("Deleted sphere and light");
|
||||
Entities.deleteEntity(sphereID);
|
||||
Entities.deleteEntity(lightID);
|
||||
});
|
|
@ -728,9 +728,8 @@ void Audio::handleAudioInput() {
|
|||
_loudestFrame = _lastInputLoudness;
|
||||
}
|
||||
|
||||
const int FRAMES_FOR_NOISE_DETECTION = 300;
|
||||
const int FRAMES_FOR_NOISE_DETECTION = 400;
|
||||
if (_inputFrameCounter++ > FRAMES_FOR_NOISE_DETECTION) {
|
||||
qDebug() << "Quietest/loudest frame: " << _quietestFrame << " / " << _loudestFrame << " NGfloor: " << _noiseGateMeasuredFloor;
|
||||
_quietestFrame = std::numeric_limits<float>::max();
|
||||
_loudestFrame = 0.0f;
|
||||
_inputFrameCounter = 0;
|
||||
|
|
|
@ -52,12 +52,10 @@ Hair::Hair(int strands,
|
|||
glm::vec3 thisVertex;
|
||||
for (int strand = 0; strand < _strands; strand++) {
|
||||
float strandAngle = randFloat() * PI;
|
||||
float azimuth;
|
||||
float elevation = - (randFloat() * PI);
|
||||
azimuth = PI_OVER_TWO;
|
||||
if (randFloat() < 0.5f) {
|
||||
azimuth *= -1.0f;
|
||||
}
|
||||
|
||||
float azimuth = (float)strand / (float)_strands * PI * 2.0f;
|
||||
float elevation = 0.0f;
|
||||
|
||||
glm::vec3 thisStrand(sinf(azimuth) * cosf(elevation), sinf(elevation), -cosf(azimuth) * cosf(elevation));
|
||||
thisStrand *= _radius;
|
||||
|
||||
|
@ -115,11 +113,22 @@ void Hair::simulate(float deltaTime) {
|
|||
glm::vec3 diff = thisPosition - _hairLastPosition[vertexIndex];
|
||||
_hairPosition[vertexIndex] += diff * HAIR_DAMPING;
|
||||
|
||||
/*
|
||||
// Resolve collisions with sphere
|
||||
if (glm::length(_hairPosition[vertexIndex]) < _radius) {
|
||||
_hairPosition[vertexIndex] += glm::normalize(_hairPosition[vertexIndex]) *
|
||||
(_radius - glm::length(_hairPosition[vertexIndex]));
|
||||
} */
|
||||
|
||||
// Collide with a conical body descending from the root of the hair
|
||||
glm::vec3 thisVertex = _hairPosition[vertexIndex];
|
||||
float depth = -thisVertex.y;
|
||||
thisVertex.y = 0.0f;
|
||||
const float BODY_CONE_ANGLE = 0.30;
|
||||
if (glm::length(thisVertex) < depth * BODY_CONE_ANGLE) {
|
||||
_hairPosition[vertexIndex] += glm::normalize(thisVertex) * (depth * BODY_CONE_ANGLE - glm::length(thisVertex));
|
||||
}
|
||||
|
||||
// Add random thing driven by loudness
|
||||
float loudnessFactor = (_loudness > SOUND_THRESHOLD) ? logf(_loudness - SOUND_THRESHOLD) / 2000.0f : 0.0f;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//
|
||||
//
|
||||
// EntityTreeRenderer.cpp
|
||||
// interface/src
|
||||
//
|
||||
|
|
|
@ -26,7 +26,8 @@ AudioInjector::AudioInjector(QObject* parent) :
|
|||
_sound(NULL),
|
||||
_options(),
|
||||
_shouldStop(false),
|
||||
_currentSendPosition(0)
|
||||
_currentSendPosition(0),
|
||||
_loudness(0.0f)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -34,7 +35,8 @@ AudioInjector::AudioInjector(Sound* sound, const AudioInjectorOptions& injectorO
|
|||
_sound(sound),
|
||||
_options(injectorOptions),
|
||||
_shouldStop(false),
|
||||
_currentSendPosition(0)
|
||||
_currentSendPosition(0),
|
||||
_loudness(0.0f)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -42,6 +44,10 @@ void AudioInjector::setOptions(AudioInjectorOptions& options) {
|
|||
_options = options;
|
||||
}
|
||||
|
||||
float AudioInjector::getLoudness() {
|
||||
return _loudness;
|
||||
}
|
||||
|
||||
const uchar MAX_INJECTOR_VOLUME = 0xFF;
|
||||
|
||||
void AudioInjector::injectAudio() {
|
||||
|
@ -113,6 +119,15 @@ void AudioInjector::injectAudio() {
|
|||
|
||||
int bytesToCopy = std::min(((_options.isStereo()) ? 2 : 1) * NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL,
|
||||
soundByteArray.size() - _currentSendPosition);
|
||||
|
||||
// Measure the loudness of this frame
|
||||
_loudness = 0.0f;
|
||||
for (int i = 0; i < bytesToCopy; i += sizeof(int16_t)) {
|
||||
_loudness += abs(*reinterpret_cast<int16_t*>(soundByteArray.data() + _currentSendPosition + i)) /
|
||||
(MAX_SAMPLE_VALUE / 2.0f);
|
||||
}
|
||||
_loudness /= (float)(bytesToCopy / sizeof(int16_t));
|
||||
|
||||
memcpy(injectAudioPacket.data() + positionOptionOffset,
|
||||
&_options.getPosition(),
|
||||
sizeof(_options.getPosition()));
|
||||
|
|
|
@ -33,6 +33,8 @@ public slots:
|
|||
void stop() { _shouldStop = true; }
|
||||
void setOptions(AudioInjectorOptions& options);
|
||||
void setCurrentSendPosition(int currentSendPosition) { _currentSendPosition = currentSendPosition; }
|
||||
float getLoudness();
|
||||
|
||||
signals:
|
||||
void finished();
|
||||
private:
|
||||
|
@ -40,6 +42,7 @@ private:
|
|||
AudioInjectorOptions _options;
|
||||
bool _shouldStop;
|
||||
int _currentSendPosition;
|
||||
float _loudness;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(AudioInjector*)
|
||||
|
|
|
@ -45,7 +45,15 @@ bool AudioScriptingInterface::isInjectorPlaying(AudioInjector* injector) {
|
|||
return (injector != NULL);
|
||||
}
|
||||
|
||||
void AudioScriptingInterface::startDrumSound(float volume, float frequency, float duration, float decay,
|
||||
float AudioScriptingInterface::getLoudness(AudioInjector* injector) {
|
||||
if (injector) {
|
||||
return injector->getLoudness();
|
||||
} else {
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioScriptingInterface::startDrumSound(float volume, float frequency, float duration, float decay,
|
||||
const AudioInjectorOptions* injectorOptions) {
|
||||
|
||||
Sound* sound = new Sound(volume, frequency, duration, decay);
|
||||
|
|
|
@ -23,6 +23,7 @@ public slots:
|
|||
static AudioInjector* playSound(Sound* sound, const AudioInjectorOptions* injectorOptions = NULL);
|
||||
static void stopInjector(AudioInjector* injector);
|
||||
static bool isInjectorPlaying(AudioInjector* injector);
|
||||
static float getLoudness(AudioInjector* injector);
|
||||
static void startDrumSound(float volume, float frequency, float duration, float decay,
|
||||
const AudioInjectorOptions* injectorOptions = NULL);
|
||||
|
||||
|
|
|
@ -45,8 +45,9 @@ void PositionalAudioStream::resetStats() {
|
|||
void PositionalAudioStream::updateLastPopOutputLoudnessAndTrailingLoudness() {
|
||||
_lastPopOutputLoudness = _ringBuffer.getFrameLoudness(_lastPopOutput);
|
||||
|
||||
const int TRAILING_AVERAGE_FRAMES = 100;
|
||||
const float CURRENT_FRAME_RATIO = 1.0f / TRAILING_AVERAGE_FRAMES;
|
||||
const int TRAILING_MUTE_THRESHOLD_FRAMES = 400;
|
||||
const int TRAILING_LOUDNESS_FRAMES = 200;
|
||||
const float CURRENT_FRAME_RATIO = 1.0f / TRAILING_LOUDNESS_FRAMES;
|
||||
const float PREVIOUS_FRAMES_RATIO = 1.0f - CURRENT_FRAME_RATIO;
|
||||
const float LOUDNESS_EPSILON = 0.000001f;
|
||||
|
||||
|
@ -59,7 +60,7 @@ void PositionalAudioStream::updateLastPopOutputLoudnessAndTrailingLoudness() {
|
|||
_lastPopOutputTrailingLoudness = 0;
|
||||
}
|
||||
}
|
||||
if (_frameCounter++ == TRAILING_AVERAGE_FRAMES) {
|
||||
if (_frameCounter++ == TRAILING_MUTE_THRESHOLD_FRAMES) {
|
||||
_frameCounter = 0;
|
||||
_quietestTrailingFrameLoudness = std::numeric_limits<float>::max();
|
||||
_loudestTrailingFrameLoudness = 0.0f;
|
||||
|
|
Loading…
Reference in a new issue