add sliders for reflection, diffusion, absorption

This commit is contained in:
ZappoMan 2014-04-15 09:58:35 -07:00
parent 1ed5512925
commit 8a16986294
4 changed files with 309 additions and 38 deletions

View file

@ -14,12 +14,62 @@ var delayScale = 100.0;
var fanoutScale = 10.0;
var speedScale = 20;
var factorScale = 5.0;
var reflectiveScale = 100.0;
var diffusionScale = 100.0;
var absorptionScale = 100.0;
// these three properties are bound together, if you change one, the others will also change
var reflectiveRatio = AudioReflector.getReflectiveRatio();
var diffusionRatio = AudioReflector.getDiffusionRatio();
var absorptionRatio = AudioReflector.getAbsorptionRatio();
var reflectiveThumbX;
var diffusionThumbX;
var absorptionThumbX;
function setReflectiveRatio(reflective) {
var total = diffusionRatio + absorptionRatio + (reflective / reflectiveScale);
diffusionRatio = diffusionRatio / total;
absorptionRatio = absorptionRatio / total;
reflectiveRatio = (reflective / reflectiveScale) / total;
updateRatioValues();
}
function setDiffusionRatio(diffusion) {
var total = (diffusion / diffusionScale) + absorptionRatio + reflectiveRatio;
diffusionRatio = (diffusion / diffusionScale) / total;
absorptionRatio = absorptionRatio / total;
reflectiveRatio = reflectiveRatio / total;
updateRatioValues();
}
function setAbsorptionRatio(absorption) {
var total = diffusionRatio + (absorption / absorptionScale) + reflectiveRatio;
diffusionRatio = diffusionRatio / total;
absorptionRatio = (absorption / absorptionScale) / total;
reflectiveRatio = reflectiveRatio / total;
updateRatioValues();
}
function updateRatioSliders() {
reflectiveThumbX = reflectiveMinThumbX + ((reflectiveMaxThumbX - reflectiveMinThumbX) * reflectiveRatio);
diffusionThumbX = diffusionMinThumbX + ((diffusionMaxThumbX - diffusionMinThumbX) * diffusionRatio);
absorptionThumbX = absorptionMinThumbX + ((absorptionMaxThumbX - absorptionMinThumbX) * absorptionRatio);
Overlays.editOverlay(reflectiveThumb, { x: reflectiveThumbX } );
Overlays.editOverlay(diffusionThumb, { x: diffusionThumbX } );
Overlays.editOverlay(absorptionThumb, { x: absorptionThumbX } );
}
function updateRatioValues() {
AudioReflector.setReflectiveRatio(reflectiveRatio);
AudioReflector.setDiffusionRatio(diffusionRatio);
AudioReflector.setAbsorptionRatio(absorptionRatio);
}
var topY = 250;
var sliderHeight = 35;
// This will create a couple of image overlays that make a "slider", we will demonstrate how to trap mouse messages to
// move the slider
var delayY = topY;
topY += sliderHeight;
var delayLabel = Overlays.addOverlay("text", {
@ -28,7 +78,7 @@ var delayLabel = Overlays.addOverlay("text", {
width: 60,
height: sliderHeight,
color: { red: 0, green: 0, blue: 0},
textColor: { red: 255, green: 0, blue: 0},
textColor: { red: 255, green: 255, blue: 255},
topMargin: 12,
leftMargin: 5,
text: "Delay:"
@ -43,7 +93,7 @@ var delaySlider = Overlays.addOverlay("image", {
alpha: 1
});
// This is the thumb of our slider
var delayMinThumbX = 110;
var delayMaxThumbX = delayMinThumbX + 110;
var delayThumbX = delayMinThumbX + ((delayMaxThumbX - delayMinThumbX) * (AudioReflector.getPreDelay() / delayScale));
@ -57,8 +107,6 @@ var delayThumb = Overlays.addOverlay("image", {
alpha: 1
});
// This will create a couple of image overlays that make a "slider", we will demonstrate how to trap mouse messages to
// move the slider
var fanoutY = topY;
topY += sliderHeight;
@ -68,7 +116,7 @@ var fanoutLabel = Overlays.addOverlay("text", {
width: 60,
height: sliderHeight,
color: { red: 0, green: 0, blue: 0},
textColor: { red: 255, green: 0, blue: 0},
textColor: { red: 255, green: 255, blue: 255},
topMargin: 12,
leftMargin: 5,
text: "Fanout:"
@ -83,7 +131,7 @@ var fanoutSlider = Overlays.addOverlay("image", {
alpha: 1
});
// This is the thumb of our slider
var fanoutMinThumbX = 110;
var fanoutMaxThumbX = fanoutMinThumbX + 110;
var fanoutThumbX = fanoutMinThumbX + ((fanoutMaxThumbX - fanoutMinThumbX) * (AudioReflector.getDiffusionFanout() / fanoutScale));
@ -98,8 +146,6 @@ var fanoutThumb = Overlays.addOverlay("image", {
});
// This will create a couple of image overlays that make a "slider", we will demonstrate how to trap mouse messages to
// move the slider
var speedY = topY;
topY += sliderHeight;
@ -109,7 +155,7 @@ var speedLabel = Overlays.addOverlay("text", {
width: 60,
height: sliderHeight,
color: { red: 0, green: 0, blue: 0},
textColor: { red: 255, green: 0, blue: 0},
textColor: { red: 255, green: 255, blue: 255},
topMargin: 6,
leftMargin: 5,
text: "Speed\nin ms/m:"
@ -124,7 +170,7 @@ var speedSlider = Overlays.addOverlay("image", {
alpha: 1
});
// This is the thumb of our slider
var speedMinThumbX = 110;
var speedMaxThumbX = speedMinThumbX + 110;
var speedThumbX = speedMinThumbX + ((speedMaxThumbX - speedMinThumbX) * (AudioReflector.getSoundMsPerMeter() / speedScale));
@ -138,8 +184,6 @@ var speedThumb = Overlays.addOverlay("image", {
alpha: 1
});
// This will create a couple of image overlays that make a "slider", we will demonstrate how to trap mouse messages to
// move the slider
var factorY = topY;
topY += sliderHeight;
@ -149,7 +193,7 @@ var factorLabel = Overlays.addOverlay("text", {
width: 60,
height: sliderHeight,
color: { red: 0, green: 0, blue: 0},
textColor: { red: 255, green: 0, blue: 0},
textColor: { red: 255, green: 255, blue: 255},
topMargin: 6,
leftMargin: 5,
text: "Attenuation\nFactor:"
@ -165,7 +209,7 @@ var factorSlider = Overlays.addOverlay("image", {
alpha: 1
});
// This is the thumb of our slider
var factorMinThumbX = 110;
var factorMaxThumbX = factorMinThumbX + 110;
var factorThumbX = factorMinThumbX + ((factorMaxThumbX - factorMinThumbX) * (AudioReflector.getDistanceAttenuationScalingFactor() / factorScale));
@ -179,6 +223,123 @@ var factorThumb = Overlays.addOverlay("image", {
alpha: 1
});
var reflectiveY = topY;
topY += sliderHeight;
var reflectiveLabel = Overlays.addOverlay("text", {
x: 40,
y: reflectiveY,
width: 60,
height: sliderHeight,
color: { red: 0, green: 0, blue: 0},
textColor: { red: 255, green: 255, blue: 255},
topMargin: 6,
leftMargin: 5,
text: "Reflective\nRatio:"
});
var reflectiveSlider = Overlays.addOverlay("image", {
// alternate form of expressing bounds
bounds: { x: 100, y: reflectiveY, width: 150, height: sliderHeight},
subImage: { x: 46, y: 0, width: 200, height: 71 },
imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/slider.png",
color: { red: 255, green: 255, blue: 255},
alpha: 1
});
var reflectiveMinThumbX = 110;
var reflectiveMaxThumbX = reflectiveMinThumbX + 110;
reflectiveThumbX = reflectiveMinThumbX + ((reflectiveMaxThumbX - reflectiveMinThumbX) * AudioReflector.getReflectiveRatio());
var reflectiveThumb = Overlays.addOverlay("image", {
x: reflectiveThumbX,
y: reflectiveY+9,
width: 18,
height: 17,
imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/thumb.png",
color: { red: 255, green: 255, blue: 255},
alpha: 1
});
var diffusionY = topY;
topY += sliderHeight;
var diffusionLabel = Overlays.addOverlay("text", {
x: 40,
y: diffusionY,
width: 60,
height: sliderHeight,
color: { red: 0, green: 0, blue: 0},
textColor: { red: 255, green: 255, blue: 255},
topMargin: 6,
leftMargin: 5,
text: "Diffusion\nRatio:"
});
var diffusionSlider = Overlays.addOverlay("image", {
// alternate form of expressing bounds
bounds: { x: 100, y: diffusionY, width: 150, height: sliderHeight},
subImage: { x: 46, y: 0, width: 200, height: 71 },
imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/slider.png",
color: { red: 255, green: 255, blue: 255},
alpha: 1
});
var diffusionMinThumbX = 110;
var diffusionMaxThumbX = diffusionMinThumbX + 110;
diffusionThumbX = diffusionMinThumbX + ((diffusionMaxThumbX - diffusionMinThumbX) * AudioReflector.getDiffusionRatio());
var diffusionThumb = Overlays.addOverlay("image", {
x: diffusionThumbX,
y: diffusionY+9,
width: 18,
height: 17,
imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/thumb.png",
color: { red: 0, green: 255, blue: 255},
alpha: 1
});
var absorptionY = topY;
topY += sliderHeight;
var absorptionLabel = Overlays.addOverlay("text", {
x: 40,
y: absorptionY,
width: 60,
height: sliderHeight,
color: { red: 0, green: 0, blue: 0},
textColor: { red: 255, green: 255, blue: 255},
topMargin: 6,
leftMargin: 5,
text: "Absorption\nRatio:"
});
var absorptionSlider = Overlays.addOverlay("image", {
// alternate form of expressing bounds
bounds: { x: 100, y: absorptionY, width: 150, height: sliderHeight},
subImage: { x: 46, y: 0, width: 200, height: 71 },
imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/slider.png",
color: { red: 255, green: 255, blue: 255},
alpha: 1
});
var absorptionMinThumbX = 110;
var absorptionMaxThumbX = absorptionMinThumbX + 110;
absorptionThumbX = absorptionMinThumbX + ((absorptionMaxThumbX - absorptionMinThumbX) * AudioReflector.getAbsorptionRatio());
var absorptionThumb = Overlays.addOverlay("image", {
x: absorptionThumbX,
y: absorptionY+9,
width: 18,
height: 17,
imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/thumb.png",
color: { red: 255, green: 0, blue: 255},
alpha: 1
});
// When our script shuts down, we should clean up all of our overlays
function scriptEnding() {
@ -197,6 +358,19 @@ function scriptEnding() {
Overlays.deleteOverlay(fanoutLabel);
Overlays.deleteOverlay(fanoutThumb);
Overlays.deleteOverlay(fanoutSlider);
Overlays.deleteOverlay(reflectiveLabel);
Overlays.deleteOverlay(reflectiveThumb);
Overlays.deleteOverlay(reflectiveSlider);
Overlays.deleteOverlay(diffusionLabel);
Overlays.deleteOverlay(diffusionThumb);
Overlays.deleteOverlay(diffusionSlider);
Overlays.deleteOverlay(absorptionLabel);
Overlays.deleteOverlay(absorptionThumb);
Overlays.deleteOverlay(absorptionSlider);
}
Script.scriptEnding.connect(scriptEnding);
@ -215,6 +389,10 @@ var movingSliderDelay = false;
var movingSliderFanout = false;
var movingSliderSpeed = false;
var movingSliderFactor = false;
var movingSliderReflective = false;
var movingSliderDiffusion = false;
var movingSliderAbsorption = false;
var thumbClickOffsetX = 0;
function mouseMoveEvent(event) {
if (movingSliderDelay) {
@ -227,7 +405,6 @@ function mouseMoveEvent(event) {
}
Overlays.editOverlay(delayThumb, { x: newThumbX } );
var delay = ((newThumbX - delayMinThumbX) / (delayMaxThumbX - delayMinThumbX)) * delayScale;
print("delay="+delay);
AudioReflector.setPreDelay(delay);
}
if (movingSliderFanout) {
@ -240,7 +417,6 @@ function mouseMoveEvent(event) {
}
Overlays.editOverlay(fanoutThumb, { x: newThumbX } );
var fanout = Math.round(((newThumbX - fanoutMinThumbX) / (fanoutMaxThumbX - fanoutMinThumbX)) * fanoutScale);
print("fanout="+fanout);
AudioReflector.setDiffusionFanout(fanout);
}
if (movingSliderSpeed) {
@ -267,47 +443,90 @@ function mouseMoveEvent(event) {
var factor = ((newThumbX - factorMinThumbX) / (factorMaxThumbX - factorMinThumbX)) * factorScale;
AudioReflector.setDistanceAttenuationScalingFactor(factor);
}
if (movingSliderAbsorption) {
newThumbX = event.x - thumbClickOffsetX;
if (newThumbX < absorptionMinThumbX) {
newThumbX = absorptionMminThumbX;
}
if (newThumbX > absorptionMaxThumbX) {
newThumbX = absorptionMaxThumbX;
}
Overlays.editOverlay(absorptionThumb, { x: newThumbX } );
var absorption = ((newThumbX - absorptionMinThumbX) / (absorptionMaxThumbX - absorptionMinThumbX)) * absorptionScale;
setAbsorptionRatio(absorption);
}
if (movingSliderReflective) {
newThumbX = event.x - thumbClickOffsetX;
if (newThumbX < reflectiveMinThumbX) {
newThumbX = reflectiveMminThumbX;
}
if (newThumbX > reflectiveMaxThumbX) {
newThumbX = reflectiveMaxThumbX;
}
Overlays.editOverlay(reflectiveThumb, { x: newThumbX } );
var reflective = ((newThumbX - reflectiveMinThumbX) / (reflectiveMaxThumbX - reflectiveMinThumbX)) * reflectiveScale;
setReflectiveRatio(reflective);
}
if (movingSliderDiffusion) {
newThumbX = event.x - thumbClickOffsetX;
if (newThumbX < diffusionMinThumbX) {
newThumbX = diffusionMminThumbX;
}
if (newThumbX > diffusionMaxThumbX) {
newThumbX = diffusionMaxThumbX;
}
Overlays.editOverlay(diffusionThumb, { x: newThumbX } );
var diffusion = ((newThumbX - diffusionMinThumbX) / (diffusionMaxThumbX - diffusionMinThumbX)) * diffusionScale;
setDiffusionRatio(diffusion);
}
}
// we also handle click detection in our mousePressEvent()
function mousePressEvent(event) {
var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y});
// If the user clicked on the thumb, handle the slider logic
if (clickedOverlay == delayThumb) {
movingSliderDelay = true;
thumbClickOffsetX = event.x - delayThumbX;
}
// If the user clicked on the thumb, handle the slider logic
if (clickedOverlay == fanoutThumb) {
movingSliderFanout = true;
thumbClickOffsetX = event.x - fanoutThumbX;
}
// If the user clicked on the thumb, handle the slider logic
if (clickedOverlay == speedThumb) {
movingSliderSpeed = true;
thumbClickOffsetX = event.x - speedThumbX;
}
// If the user clicked on the thumb, handle the slider logic
if (clickedOverlay == factorThumb) {
print("movingSliderFactor...");
movingSliderFactor = true;
thumbClickOffsetX = event.x - factorThumbX;
}
if (clickedOverlay == diffusionThumb) {
movingSliderDiffusion = true;
thumbClickOffsetX = event.x - diffusionThumbX;
}
if (clickedOverlay == absorptionThumb) {
movingSliderAbsorption = true;
thumbClickOffsetX = event.x - absorptionThumbX;
}
if (clickedOverlay == reflectiveThumb) {
movingSliderReflective = true;
thumbClickOffsetX = event.x - reflectiveThumbX;
}
}
function mouseReleaseEvent(event) {
if (movingSliderDelay) {
movingSliderDelay = false;
var delay = ((newThumbX - delayMinThumbX) / (delayMaxThumbX - delayMinThumbX)) * delayScale;
print("delay="+delay);
AudioReflector.setPreDelay(delay);
delayThumbX = newThumbX;
}
if (movingSliderFanout) {
movingSliderFanout = false;
var fanout = Math.round(((newThumbX - fanoutMinThumbX) / (fanoutMaxThumbX - fanoutMinThumbX)) * fanoutScale);
print("fanout="+fanout);
AudioReflector.setDiffusionFanout(fanout);
fanoutThumbX = newThumbX;
}
@ -323,6 +542,30 @@ function mouseReleaseEvent(event) {
AudioReflector.setDistanceAttenuationScalingFactor(factor);
factorThumbX = newThumbX;
}
if (movingSliderReflective) {
movingSliderReflective = false;
var reflective = ((newThumbX - reflectiveMinThumbX) / (reflectiveMaxThumbX - reflectiveMinThumbX)) * reflectiveScale;
setReflectiveRatio(reflective);
reflectiveThumbX = newThumbX;
updateRatioSliders();
}
if (movingSliderDiffusion) {
movingSliderDiffusion = false;
var diffusion = ((newThumbX - diffusionMinThumbX) / (diffusionMaxThumbX - diffusionMinThumbX)) * diffusionScale;
setDiffusionRatio(diffusion);
diffusionThumbX = newThumbX;
updateRatioSliders();
}
if (movingSliderAbsorption) {
movingSliderAbsorption = false;
var absorption = ((newThumbX - absorptionMinThumbX) / (absorptionMaxThumbX - absorptionMinThumbX)) * absorptionScale;
setAbsorptionRatio(absorption);
absorptionThumbX = newThumbX;
updateRatioSliders();
}
}
Controller.mouseMoveEvent.connect(mouseMoveEvent);

View file

@ -11,7 +11,6 @@
#include "AudioReflector.h"
#include "Menu.h"
const float DEFAULT_PRE_DELAY = 20.0f; // this delay in msecs will always be added to all reflections
const float DEFAULT_MS_DELAY_PER_METER = 3.0f;
const float MINIMUM_ATTENUATION_TO_REFLECT = 1.0f / 256.0f;
@ -45,7 +44,6 @@ AudioReflector::AudioReflector(QObject* parent) :
_minDelay = 0;
}
void AudioReflector::render() {
// if we're not set up yet, or we're not processing spatial audio, then exit early
@ -159,8 +157,11 @@ void AudioReflector::injectAudiblePoint(const AudiblePoint& audiblePoint,
int rightEarDelay = rightEarDelayMsecs * sampleRate / MSECS_PER_SECOND;
int leftEarDelay = leftEarDelayMsecs * sampleRate / MSECS_PER_SECOND;
float rightEarAttenuation = audiblePoint.attenuation * getDistanceAttenuationCoefficient(rightEarDistance + audiblePoint.distance);
float leftEarAttenuation = audiblePoint.attenuation * getDistanceAttenuationCoefficient(leftEarDistance + audiblePoint.distance);
float rightEarAttenuation = audiblePoint.attenuation *
getDistanceAttenuationCoefficient(rightEarDistance + audiblePoint.distance);
float leftEarAttenuation = audiblePoint.attenuation *
getDistanceAttenuationCoefficient(leftEarDistance + audiblePoint.distance);
_totalAttenuation += rightEarAttenuation + leftEarAttenuation;
_attenuationCount += 2;
@ -423,7 +424,12 @@ int AudioReflector::analyzePathsSingleStep() {
if (path->bounceCount > ABSOLUTE_MAXIMUM_BOUNCE_COUNT) {
path->finalized = true;
} else if (_voxels->findRayIntersection(start, direction, elementHit, distance, face, Octree::Lock)) {
} else if (_voxels->findRayIntersection(start, direction, elementHit, distance, face)) {
// TODO: we need to decide how we want to handle locking on the ray intersection, if we force lock,
// we get an accurate picture, but it could prevent rendering of the voxels. If we trylock (default),
// we might not get ray intersections where they may exist, but we can't really detect that case...
// add last parameter of Octree::Lock to force locking
glm::vec3 end = start + (direction * (distance * SLIGHTLY_SHORT));
pathDistance += glm::distance(start, end);
@ -525,9 +531,15 @@ int AudioReflector::analyzePathsSingleStep() {
}
SurfaceCharacteristics AudioReflector::getSurfaceCharacteristics(OctreeElement* elementHit) {
float reflectiveRatio = (1.0f - (_absorptionRatio + _diffusionRatio));
SurfaceCharacteristics result = { reflectiveRatio, _absorptionRatio, _diffusionRatio };
SurfaceCharacteristics result = { getReflectiveRatio(), _absorptionRatio, _diffusionRatio };
return result;
}
void AudioReflector::setReflectiveRatio(float ratio) {
float currentReflectiveRatio = (1.0f - (_absorptionRatio + _diffusionRatio));
float halfDifference = (ratio - currentReflectiveRatio) / 2.0f;
// evenly distribute the difference between the two other ratios
_absorptionRatio -= halfDifference;
_diffusionRatio -= halfDifference;
}

View file

@ -84,10 +84,16 @@ public slots:
void setSoundMsPerMeter(float soundMsPerMeter) { _soundMsPerMeter = soundMsPerMeter; }
float getDistanceAttenuationScalingFactor() const { return _distanceAttenuationScalingFactor; } /// ms per meter, larger means slower
void setDistanceAttenuationScalingFactor(float factor) { _distanceAttenuationScalingFactor = factor; }
int getDiffusionFanout() const { return _diffusionFanout; } /// number of points of diffusion from each reflection point
void setDiffusionFanout(int fanout) { _diffusionFanout = fanout; } /// number of points of diffusion from each reflection point
float getAbsorptionRatio() const { return _absorptionRatio; }
void setAbsorptionRatio(float ratio) { _absorptionRatio = ratio; }
float getDiffusionRatio() const { return _diffusionRatio; }
void setDiffusionRatio(float ratio) { _diffusionRatio = ratio; }
float getReflectiveRatio() const { return (1.0f - (_absorptionRatio + _diffusionRatio)); }
void setReflectiveRatio(float ratio);
signals:
private:

View file

@ -343,7 +343,7 @@ void Stats::display(
lines = _expanded ? 12 : 3;
if (_expanded && Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessing)) {
lines += 5; // spatial audio processing adds 1 spacing line and 4 extra lines of info
lines += 6; // spatial audio processing adds 1 spacing line and 5 extra lines of info
}
drawBackground(backgroundColor, horizontalOffset, 0, glWidget->width() - horizontalOffset, lines * STATS_PELS_PER_LINE + 10);
@ -541,7 +541,7 @@ void Stats::display(
verticalOffset += STATS_PELS_PER_LINE;
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, reflectionsStatus, color);
sprintf(reflectionsStatus, "Attenuation: average %5.3f, max %5.3f, min %5.3f, distance scale: %5.3f",
sprintf(reflectionsStatus, "Attenuation: average %5.3f, max %5.3f, min %5.3f, Factor: %5.3f",
audioReflector->getAverageAttenuation(),
audioReflector->getMaxAttenuation(),
audioReflector->getMinAttenuation(),
@ -559,6 +559,16 @@ void Stats::display(
verticalOffset += STATS_PELS_PER_LINE;
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, reflectionsStatus, color);
const float AS_PERCENT = 100.0f;
float reflectiveRatio = audioReflector->getReflectiveRatio() * AS_PERCENT;
float diffusionRatio = audioReflector->getDiffusionRatio() * AS_PERCENT;
float absorptionRatio = audioReflector->getAbsorptionRatio() * AS_PERCENT;
sprintf(reflectionsStatus, "Ratios: Reflective: %5.3f, Diffusion: %5.3f, Absorption: %5.3f",
reflectiveRatio, diffusionRatio, absorptionRatio);
verticalOffset += STATS_PELS_PER_LINE;
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, reflectionsStatus, color);
}
}