mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 15:23:56 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into stretchableEntities
This commit is contained in:
commit
3cb1d29cf4
39 changed files with 1021 additions and 233 deletions
|
@ -13,4 +13,5 @@ Script.load("editVoxels.js");
|
|||
Script.load("editModels.js");
|
||||
Script.load("selectAudioDevice.js");
|
||||
Script.load("hydraMove.js");
|
||||
Script.load("headMove.js");
|
||||
Script.load("inspect.js");
|
||||
|
|
|
@ -1147,10 +1147,10 @@ var toolBar = (function () {
|
|||
}, true, false);
|
||||
|
||||
browseModelsButton = toolBar.addTool({
|
||||
imageURL: toolIconUrl + "list-icon.png",
|
||||
imageURL: toolIconUrl + "list-icon.svg",
|
||||
width: toolWidth,
|
||||
height: toolHeight,
|
||||
alpha: 0.7,
|
||||
alpha: 0.9,
|
||||
visible: true
|
||||
});
|
||||
|
||||
|
|
77
examples/headMove.js
Normal file
77
examples/headMove.js
Normal file
|
@ -0,0 +1,77 @@
|
|||
//
|
||||
// headMove.js
|
||||
// examples
|
||||
//
|
||||
// Created by Philip Rosedale on September 8, 2014
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Press the spacebar and move/turn your head to move around.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
var debug = false;
|
||||
|
||||
var movingWithHead = false;
|
||||
var headStartPosition, headStartDeltaPitch, headStartFinalPitch, headStartRoll, headStartYaw;
|
||||
|
||||
var HEAD_MOVE_DEAD_ZONE = 0.0;
|
||||
var HEAD_STRAFE_DEAD_ZONE = 0.0;
|
||||
var HEAD_ROTATE_DEAD_ZONE = 0.0;
|
||||
var HEAD_THRUST_FWD_SCALE = 12000.0;
|
||||
var HEAD_THRUST_STRAFE_SCALE = 1000.0;
|
||||
var HEAD_YAW_RATE = 2.0;
|
||||
var HEAD_PITCH_RATE = 1.0;
|
||||
var HEAD_ROLL_THRUST_SCALE = 75.0;
|
||||
var HEAD_PITCH_LIFT_THRUST = 3.0;
|
||||
|
||||
function moveWithHead(deltaTime) {
|
||||
if (movingWithHead) {
|
||||
var deltaYaw = MyAvatar.getHeadFinalYaw() - headStartYaw;
|
||||
var deltaPitch = MyAvatar.getHeadDeltaPitch() - headStartDeltaPitch;
|
||||
|
||||
var bodyLocalCurrentHeadVector = Vec3.subtract(MyAvatar.getHeadPosition(), MyAvatar.position);
|
||||
bodyLocalCurrentHeadVector = Vec3.multiplyQbyV(Quat.angleAxis(-deltaYaw, {x:0, y: 1, z:0}), bodyLocalCurrentHeadVector);
|
||||
var headDelta = Vec3.subtract(bodyLocalCurrentHeadVector, headStartPosition);
|
||||
headDelta = Vec3.multiplyQbyV(Quat.inverse(Camera.getOrientation()), headDelta);
|
||||
headDelta.y = 0.0; // Don't respond to any of the vertical component of head motion
|
||||
|
||||
// Thrust based on leaning forward and side-to-side
|
||||
if (Math.abs(headDelta.z) > HEAD_MOVE_DEAD_ZONE) {
|
||||
MyAvatar.addThrust(Vec3.multiply(Quat.getFront(Camera.getOrientation()), -headDelta.z * HEAD_THRUST_FWD_SCALE * deltaTime));
|
||||
}
|
||||
if (Math.abs(headDelta.x) > HEAD_STRAFE_DEAD_ZONE) {
|
||||
MyAvatar.addThrust(Vec3.multiply(Quat.getRight(Camera.getOrientation()), headDelta.x * HEAD_THRUST_STRAFE_SCALE * deltaTime));
|
||||
}
|
||||
if (Math.abs(deltaYaw) > HEAD_ROTATE_DEAD_ZONE) {
|
||||
var orientation = Quat.multiply(Quat.angleAxis(deltaYaw * HEAD_YAW_RATE * deltaTime, {x:0, y: 1, z:0}), MyAvatar.orientation);
|
||||
MyAvatar.orientation = orientation;
|
||||
}
|
||||
// Thrust Up/Down based on head pitch
|
||||
MyAvatar.addThrust(Vec3.multiply({ x:0, y:1, z:0 }, (MyAvatar.getHeadFinalPitch() - headStartFinalPitch) * HEAD_PITCH_LIFT_THRUST * deltaTime));
|
||||
// For head trackers, adjust pitch by head pitch
|
||||
MyAvatar.headPitch += deltaPitch * HEAD_PITCH_RATE * deltaTime;
|
||||
// Thrust strafe based on roll ange
|
||||
MyAvatar.addThrust(Vec3.multiply(Quat.getRight(Camera.getOrientation()), -(MyAvatar.getHeadFinalRoll() - headStartRoll) * HEAD_ROLL_THRUST_SCALE * deltaTime));
|
||||
}
|
||||
}
|
||||
|
||||
Controller.keyPressEvent.connect(function(event) {
|
||||
if (event.text == "SPACE" && !movingWithHead) {
|
||||
movingWithHead = true;
|
||||
headStartPosition = Vec3.subtract(MyAvatar.getHeadPosition(), MyAvatar.position);
|
||||
headStartDeltaPitch = MyAvatar.getHeadDeltaPitch();
|
||||
headStartFinalPitch = MyAvatar.getHeadFinalPitch();
|
||||
headStartRoll = MyAvatar.getHeadFinalRoll();
|
||||
headStartYaw = MyAvatar.getHeadFinalYaw();
|
||||
}
|
||||
});
|
||||
Controller.keyReleaseEvent.connect(function(event) {
|
||||
if (event.text == "SPACE") {
|
||||
movingWithHead = false;
|
||||
}
|
||||
});
|
||||
|
||||
Script.update.connect(moveWithHead);
|
||||
|
|
@ -2,7 +2,9 @@
|
|||
// hydraMove.js
|
||||
// examples
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 2/10/14.
|
||||
// Created by Brad Hefta-Gaub on February 10, 2014
|
||||
// Updated by Philip Rosedale on September 8, 2014
|
||||
//
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// This is an example script that demonstrates use of the Controller and MyAvatar classes to implement
|
||||
|
@ -34,8 +36,7 @@ var grabbingWithRightHand = false;
|
|||
var wasGrabbingWithRightHand = false;
|
||||
var grabbingWithLeftHand = false;
|
||||
var wasGrabbingWithLeftHand = false;
|
||||
var movingWithHead = false;
|
||||
var headStartPosition, headStartDeltaPitch, headStartFinalPitch, headStartRoll, headStartYaw;
|
||||
|
||||
var EPSILON = 0.000001;
|
||||
var velocity = { x: 0, y: 0, z: 0};
|
||||
var THRUST_MAG_UP = 100.0;
|
||||
|
@ -243,47 +244,6 @@ function handleGrabBehavior(deltaTime) {
|
|||
wasGrabbingWithLeftHand = grabbingWithLeftHand;
|
||||
}
|
||||
|
||||
var HEAD_MOVE_DEAD_ZONE = 0.0;
|
||||
var HEAD_STRAFE_DEAD_ZONE = 0.0;
|
||||
var HEAD_ROTATE_DEAD_ZONE = 0.0;
|
||||
var HEAD_THRUST_FWD_SCALE = 12000.0;
|
||||
var HEAD_THRUST_STRAFE_SCALE = 1000.0;
|
||||
var HEAD_YAW_RATE = 2.0;
|
||||
var HEAD_PITCH_RATE = 1.0;
|
||||
var HEAD_ROLL_THRUST_SCALE = 75.0;
|
||||
var HEAD_PITCH_LIFT_THRUST = 3.0;
|
||||
|
||||
function moveWithHead(deltaTime) {
|
||||
if (movingWithHead) {
|
||||
var deltaYaw = MyAvatar.getHeadFinalYaw() - headStartYaw;
|
||||
var deltaPitch = MyAvatar.getHeadDeltaPitch() - headStartDeltaPitch;
|
||||
|
||||
var bodyLocalCurrentHeadVector = Vec3.subtract(MyAvatar.getHeadPosition(), MyAvatar.position);
|
||||
bodyLocalCurrentHeadVector = Vec3.multiplyQbyV(Quat.angleAxis(-deltaYaw, {x:0, y: 1, z:0}), bodyLocalCurrentHeadVector);
|
||||
var headDelta = Vec3.subtract(bodyLocalCurrentHeadVector, headStartPosition);
|
||||
headDelta = Vec3.multiplyQbyV(Quat.inverse(Camera.getOrientation()), headDelta);
|
||||
headDelta.y = 0.0; // Don't respond to any of the vertical component of head motion
|
||||
|
||||
// Thrust based on leaning forward and side-to-side
|
||||
if (Math.abs(headDelta.z) > HEAD_MOVE_DEAD_ZONE) {
|
||||
MyAvatar.addThrust(Vec3.multiply(Quat.getFront(Camera.getOrientation()), -headDelta.z * HEAD_THRUST_FWD_SCALE * deltaTime));
|
||||
}
|
||||
if (Math.abs(headDelta.x) > HEAD_STRAFE_DEAD_ZONE) {
|
||||
MyAvatar.addThrust(Vec3.multiply(Quat.getRight(Camera.getOrientation()), headDelta.x * HEAD_THRUST_STRAFE_SCALE * deltaTime));
|
||||
}
|
||||
if (Math.abs(deltaYaw) > HEAD_ROTATE_DEAD_ZONE) {
|
||||
var orientation = Quat.multiply(Quat.angleAxis(deltaYaw * HEAD_YAW_RATE * deltaTime, {x:0, y: 1, z:0}), MyAvatar.orientation);
|
||||
MyAvatar.orientation = orientation;
|
||||
}
|
||||
// Thrust Up/Down based on head pitch
|
||||
MyAvatar.addThrust(Vec3.multiply({ x:0, y:1, z:0 }, (MyAvatar.getHeadFinalPitch() - headStartFinalPitch) * HEAD_PITCH_LIFT_THRUST * deltaTime));
|
||||
// For head trackers, adjust pitch by head pitch
|
||||
MyAvatar.headPitch += deltaPitch * HEAD_PITCH_RATE * deltaTime;
|
||||
// Thrust strafe based on roll ange
|
||||
MyAvatar.addThrust(Vec3.multiply(Quat.getRight(Camera.getOrientation()), -(MyAvatar.getHeadFinalRoll() - headStartRoll) * HEAD_ROLL_THRUST_SCALE * deltaTime));
|
||||
}
|
||||
}
|
||||
|
||||
// Update for joysticks and move button
|
||||
function flyWithHydra(deltaTime) {
|
||||
var thrustJoystickPosition = Controller.getJoystickPosition(THRUST_CONTROLLER);
|
||||
|
@ -318,12 +278,10 @@ function flyWithHydra(deltaTime) {
|
|||
MyAvatar.orientation = Quat.multiply(orientation, deltaOrientation);
|
||||
|
||||
// change the headPitch based on our x controller
|
||||
//pitch += viewJoystickPosition.y * JOYSTICK_PITCH_MAG * deltaTime;
|
||||
var newPitch = MyAvatar.headPitch + (viewJoystickPosition.y * JOYSTICK_PITCH_MAG * deltaTime);
|
||||
MyAvatar.headPitch = newPitch;
|
||||
}
|
||||
handleGrabBehavior(deltaTime);
|
||||
moveWithHead(deltaTime);
|
||||
displayDebug();
|
||||
|
||||
}
|
||||
|
@ -340,19 +298,4 @@ function scriptEnding() {
|
|||
}
|
||||
Script.scriptEnding.connect(scriptEnding);
|
||||
|
||||
Controller.keyPressEvent.connect(function(event) {
|
||||
if (event.text == "SPACE" && !movingWithHead) {
|
||||
movingWithHead = true;
|
||||
headStartPosition = Vec3.subtract(MyAvatar.getHeadPosition(), MyAvatar.position);
|
||||
headStartDeltaPitch = MyAvatar.getHeadDeltaPitch();
|
||||
headStartFinalPitch = MyAvatar.getHeadFinalPitch();
|
||||
headStartRoll = MyAvatar.getHeadFinalRoll();
|
||||
headStartYaw = MyAvatar.getHeadFinalYaw();
|
||||
}
|
||||
});
|
||||
Controller.keyReleaseEvent.connect(function(event) {
|
||||
if (event.text == "SPACE") {
|
||||
movingWithHead = false;
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include <QShortcut>
|
||||
#include <QTimer>
|
||||
#include <QUrl>
|
||||
#include <QWindow>
|
||||
#include <QtDebug>
|
||||
#include <QFileDialog>
|
||||
#include <QDesktopServices>
|
||||
|
@ -1152,8 +1153,7 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) {
|
|||
showMouse = false;
|
||||
}
|
||||
|
||||
QMouseEvent deviceEvent = getDeviceEvent(event, deviceID);
|
||||
_controllerScriptingInterface.emitMouseMoveEvent(&deviceEvent, deviceID); // send events to any registered scripts
|
||||
_controllerScriptingInterface.emitMouseMoveEvent(event, deviceID); // send events to any registered scripts
|
||||
|
||||
// if one of our scripts have asked to capture this event, then stop processing it
|
||||
if (_controllerScriptingInterface.isMouseCaptured()) {
|
||||
|
@ -1168,13 +1168,12 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) {
|
|||
_seenMouseMove = true;
|
||||
}
|
||||
|
||||
_mouseX = deviceEvent.x();
|
||||
_mouseY = deviceEvent.y();
|
||||
_mouseX = event->x();
|
||||
_mouseY = event->y();
|
||||
}
|
||||
|
||||
void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) {
|
||||
QMouseEvent deviceEvent = getDeviceEvent(event, deviceID);
|
||||
_controllerScriptingInterface.emitMousePressEvent(&deviceEvent); // send events to any registered scripts
|
||||
_controllerScriptingInterface.emitMousePressEvent(event); // send events to any registered scripts
|
||||
|
||||
// if one of our scripts have asked to capture this event, then stop processing it
|
||||
if (_controllerScriptingInterface.isMouseCaptured()) {
|
||||
|
@ -1184,8 +1183,8 @@ void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) {
|
|||
|
||||
if (activeWindow() == _window) {
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
_mouseX = deviceEvent.x();
|
||||
_mouseY = deviceEvent.y();
|
||||
_mouseX = event->x();
|
||||
_mouseY = event->y();
|
||||
_mouseDragStartedX = _mouseX;
|
||||
_mouseDragStartedY = _mouseY;
|
||||
_mousePressed = true;
|
||||
|
@ -1207,8 +1206,7 @@ void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) {
|
|||
}
|
||||
|
||||
void Application::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) {
|
||||
QMouseEvent deviceEvent = getDeviceEvent(event, deviceID);
|
||||
_controllerScriptingInterface.emitMouseReleaseEvent(&deviceEvent); // send events to any registered scripts
|
||||
_controllerScriptingInterface.emitMouseReleaseEvent(event); // send events to any registered scripts
|
||||
|
||||
// if one of our scripts have asked to capture this event, then stop processing it
|
||||
if (_controllerScriptingInterface.isMouseCaptured()) {
|
||||
|
@ -1217,8 +1215,8 @@ void Application::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) {
|
|||
|
||||
if (activeWindow() == _window) {
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
_mouseX = deviceEvent.x();
|
||||
_mouseY = deviceEvent.y();
|
||||
_mouseX = event->x();
|
||||
_mouseY = event->y();
|
||||
_mousePressed = false;
|
||||
checkBandwidthMeterClick();
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Stats)) {
|
||||
|
@ -1417,7 +1415,7 @@ void Application::checkBandwidthMeterClick() {
|
|||
if (Menu::getInstance()->isOptionChecked(MenuOption::Bandwidth) &&
|
||||
glm::compMax(glm::abs(glm::ivec2(_mouseX - _mouseDragStartedX, _mouseY - _mouseDragStartedY)))
|
||||
<= BANDWIDTH_METER_CLICK_MAX_DRAG_LENGTH
|
||||
&& _bandwidthMeter.isWithinArea(_mouseX, _mouseY, _glWidget->getDeviceWidth(), _glWidget->getDeviceHeight())) {
|
||||
&& _bandwidthMeter.isWithinArea(_mouseX, _mouseY, _glWidget->width(), _glWidget->height())) {
|
||||
|
||||
// The bandwidth meter is visible, the click didn't get dragged too far and
|
||||
// we actually hit the bandwidth meter
|
||||
|
@ -1735,8 +1733,8 @@ void Application::init() {
|
|||
_voxelShader.init();
|
||||
_pointShader.init();
|
||||
|
||||
_mouseX = _glWidget->getDeviceWidth() / 2;
|
||||
_mouseY = _glWidget->getDeviceHeight() / 2;
|
||||
_mouseX = _glWidget->width() / 2;
|
||||
_mouseY = _glWidget->height() / 2;
|
||||
QCursor::setPos(_mouseX, _mouseY);
|
||||
|
||||
// TODO: move _myAvatar out of Application. Move relevant code to MyAvataar or AvatarManager
|
||||
|
@ -1891,8 +1889,8 @@ void Application::updateMouseRay() {
|
|||
// if the mouse pointer isn't visible, act like it's at the center of the screen
|
||||
float x = 0.5f, y = 0.5f;
|
||||
if (!_mouseHidden) {
|
||||
x = _mouseX / (float)_glWidget->getDeviceWidth();
|
||||
y = _mouseY / (float)_glWidget->getDeviceHeight();
|
||||
x = _mouseX / (float)_glWidget->width();
|
||||
y = _mouseY / (float)_glWidget->height();
|
||||
}
|
||||
_viewFrustum.computePickRay(x, y, _mouseRayOrigin, _mouseRayDirection);
|
||||
|
||||
|
@ -2332,14 +2330,6 @@ int Application::sendNackPackets() {
|
|||
return packetsSent;
|
||||
}
|
||||
|
||||
QMouseEvent Application::getDeviceEvent(QMouseEvent* event, unsigned int deviceID) {
|
||||
if (deviceID > 0) {
|
||||
return *event;
|
||||
}
|
||||
return QMouseEvent(event->type(), QPointF(_glWidget->getDeviceX(event->x()), _glWidget->getDeviceY(event->y())),
|
||||
event->windowPos(), event->screenPos(), event->button(), event->buttons(), event->modifiers());
|
||||
}
|
||||
|
||||
void Application::queryOctree(NodeType_t serverType, PacketType packetType, NodeToJurisdictionMap& jurisdictions) {
|
||||
|
||||
//qDebug() << ">>> inside... queryOctree()... _viewFrustum.getFieldOfView()=" << _viewFrustum.getFieldOfView();
|
||||
|
@ -3041,8 +3031,16 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) {
|
|||
_mirrorCamera.update(1.0f/_fps);
|
||||
|
||||
// set the bounds of rear mirror view
|
||||
glViewport(region.x(), _glWidget->getDeviceHeight() - region.y() - region.height(), region.width(), region.height());
|
||||
glScissor(region.x(), _glWidget->getDeviceHeight() - region.y() - region.height(), region.width(), region.height());
|
||||
if (billboard) {
|
||||
glViewport(region.x(), _glWidget->getDeviceHeight() - region.y() - region.height(), region.width(), region.height());
|
||||
glScissor(region.x(), _glWidget->getDeviceHeight() - region.y() - region.height(), region.width(), region.height());
|
||||
} else {
|
||||
// if not rendering the billboard, the region is in device independent coordinates; must convert to device
|
||||
float ratio = QApplication::desktop()->windowHandle()->devicePixelRatio();
|
||||
int x = region.x() * ratio, y = region.y() * ratio, width = region.width() * ratio, height = region.height() * ratio;
|
||||
glViewport(x, _glWidget->getDeviceHeight() - y - height, width, height);
|
||||
glScissor(x, _glWidget->getDeviceHeight() - y - height, width, height);
|
||||
}
|
||||
bool updateViewFrustum = false;
|
||||
updateProjectionMatrix(_mirrorCamera, updateViewFrustum);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
|
@ -3291,8 +3289,8 @@ void Application::deleteVoxelAt(const VoxelDetail& voxel) {
|
|||
|
||||
|
||||
void Application::resetSensors() {
|
||||
_mouseX = _glWidget->getDeviceWidth() / 2;
|
||||
_mouseY = _glWidget->getDeviceHeight() / 2;
|
||||
_mouseX = _glWidget->width() / 2;
|
||||
_mouseY = _glWidget->height() / 2;
|
||||
|
||||
_faceplus.reset();
|
||||
_faceshift.reset();
|
||||
|
|
|
@ -436,8 +436,6 @@ private:
|
|||
|
||||
int sendNackPackets();
|
||||
|
||||
QMouseEvent getDeviceEvent(QMouseEvent* event, unsigned int deviceID);
|
||||
|
||||
MainWindow* _window;
|
||||
GLCanvas* _glWidget; // our GLCanvas has a couple extra features
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include <glm/glm.hpp>
|
||||
|
||||
#include "Audio.h"
|
||||
|
||||
#include "Menu.h"
|
||||
#include "Util.h"
|
||||
#include "PositionalAudioStream.h"
|
||||
|
@ -82,7 +83,7 @@ Audio::Audio(QObject* parent) :
|
|||
_noiseGateSampleCounter(0),
|
||||
_noiseGateOpen(false),
|
||||
_noiseGateEnabled(true),
|
||||
_toneInjectionEnabled(false),
|
||||
_audioSourceInjectEnabled(false),
|
||||
_noiseGateFramesToClose(0),
|
||||
_totalInputAudioSamples(0),
|
||||
_collisionSoundMagnitude(0.0f),
|
||||
|
@ -102,6 +103,8 @@ Audio::Audio(QObject* parent) :
|
|||
_framesPerScope(DEFAULT_FRAMES_PER_SCOPE),
|
||||
_samplesPerScope(NETWORK_SAMPLES_PER_FRAME * _framesPerScope),
|
||||
_peqEnabled(false),
|
||||
_noiseSourceEnabled(false),
|
||||
_toneSourceEnabled(true),
|
||||
_scopeInput(0),
|
||||
_scopeOutputLeft(0),
|
||||
_scopeOutputRight(0),
|
||||
|
@ -137,6 +140,10 @@ void Audio::reset() {
|
|||
_receivedAudioStream.reset();
|
||||
resetStats();
|
||||
_peq.reset();
|
||||
_noiseSource.reset();
|
||||
_toneSource.reset();
|
||||
_sourceGain.reset();
|
||||
_inputGain.reset();
|
||||
}
|
||||
|
||||
void Audio::resetStats() {
|
||||
|
@ -424,14 +431,25 @@ void Audio::start() {
|
|||
qDebug() << "Unable to set up audio output because of a problem with output format.";
|
||||
}
|
||||
|
||||
_peq.initialize( _inputFormat.sampleRate(), _audioInput->bufferSize() );
|
||||
|
||||
_inputFrameBuffer.initialize( _inputFormat.channelCount(), _audioInput->bufferSize() * 4 );
|
||||
_peq.initialize( _inputFormat.sampleRate() );
|
||||
_inputGain.initialize();
|
||||
_sourceGain.initialize();
|
||||
_noiseSource.initialize();
|
||||
_toneSource.initialize();
|
||||
_sourceGain.setParameters(0.25f,0.0f);
|
||||
_inputGain.setParameters(1.0f,0.0f);
|
||||
}
|
||||
|
||||
void Audio::stop() {
|
||||
|
||||
_inputFrameBuffer.finalize();
|
||||
_peq.finalize();
|
||||
|
||||
_inputGain.finalize();
|
||||
_sourceGain.finalize();
|
||||
_noiseSource.finalize();
|
||||
_toneSource.finalize();
|
||||
|
||||
// "switch" to invalid devices in order to shut down the state
|
||||
switchInputToAudioDevice(QAudioDeviceInfo());
|
||||
switchOutputToAudioDevice(QAudioDeviceInfo());
|
||||
|
@ -477,14 +495,30 @@ void Audio::handleAudioInput() {
|
|||
|
||||
QByteArray inputByteArray = _inputDevice->readAll();
|
||||
|
||||
int16_t* inputFrameData = (int16_t*)inputByteArray.data();
|
||||
const int inputFrameCount = inputByteArray.size() / sizeof(int16_t);
|
||||
|
||||
_inputFrameBuffer.copyFrames(1, inputFrameCount, inputFrameData, false /*copy in*/);
|
||||
|
||||
_inputGain.render(_inputFrameBuffer); // input/mic gain+mute
|
||||
|
||||
// Add audio source injection if enabled
|
||||
if (_audioSourceInjectEnabled && !_muted) {
|
||||
|
||||
if (_toneSourceEnabled) { // sine generator
|
||||
_toneSource.render(_inputFrameBuffer);
|
||||
}
|
||||
else if(_noiseSourceEnabled) { // pink noise generator
|
||||
_noiseSource.render(_inputFrameBuffer);
|
||||
}
|
||||
_sourceGain.render(_inputFrameBuffer); // post gain
|
||||
}
|
||||
if (_peqEnabled && !_muted) {
|
||||
// we wish to pre-filter our captured input, prior to loopback
|
||||
|
||||
int16_t* ioBuffer = (int16_t*)inputByteArray.data();
|
||||
|
||||
_peq.render(ioBuffer, ioBuffer, inputByteArray.size() / sizeof(int16_t));
|
||||
_peq.render(_inputFrameBuffer); // 3-band parametric eq
|
||||
}
|
||||
|
||||
_inputFrameBuffer.copyFrames(1, inputFrameCount, inputFrameData, true /*copy out*/);
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::EchoLocalAudio) && !_muted && _audioOutput) {
|
||||
// if this person wants local loopback add that to the locally injected audio
|
||||
|
||||
|
@ -522,7 +556,7 @@ void Audio::handleAudioInput() {
|
|||
|
||||
int16_t* inputAudioSamples = new int16_t[inputSamplesRequired];
|
||||
_inputRingBuffer.readSamples(inputAudioSamples, inputSamplesRequired);
|
||||
|
||||
|
||||
const int numNetworkBytes = _isStereoInput ? NETWORK_BUFFER_LENGTH_BYTES_STEREO : NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL;
|
||||
const int numNetworkSamples = _isStereoInput ? NETWORK_BUFFER_LENGTH_SAMPLES_STEREO : NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL;
|
||||
|
||||
|
@ -599,20 +633,8 @@ void Audio::handleAudioInput() {
|
|||
_dcOffset = DC_OFFSET_AVERAGING * _dcOffset + (1.0f - DC_OFFSET_AVERAGING) * measuredDcOffset;
|
||||
}
|
||||
|
||||
// Add tone injection if enabled
|
||||
const float TONE_FREQ = 220.0f / SAMPLE_RATE * TWO_PI;
|
||||
const float QUARTER_VOLUME = 8192.0f;
|
||||
if (_toneInjectionEnabled) {
|
||||
loudness = 0.0f;
|
||||
for (int i = 0; i < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; i++) {
|
||||
networkAudioSamples[i] = QUARTER_VOLUME * sinf(TONE_FREQ * (float)(i + _proceduralEffectSample));
|
||||
loudness += fabsf(networkAudioSamples[i]);
|
||||
}
|
||||
}
|
||||
_lastInputLoudness = fabs(loudness / NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL);
|
||||
|
||||
// If Noise Gate is enabled, check and turn the gate on and off
|
||||
if (!_toneInjectionEnabled && _noiseGateEnabled) {
|
||||
if (!_audioSourceInjectEnabled && _noiseGateEnabled) {
|
||||
float averageOfAllSampleFrames = 0.0f;
|
||||
_noiseSampleFrames[_noiseGateSampleCounter++] = _lastInputLoudness;
|
||||
if (_noiseGateSampleCounter == NUMBER_OF_NOISE_SAMPLE_FRAMES) {
|
||||
|
@ -1041,8 +1063,18 @@ void Audio::processProceduralAudio(int16_t* monoInput, int numSamples) {
|
|||
}
|
||||
}
|
||||
|
||||
void Audio::toggleToneInjection() {
|
||||
_toneInjectionEnabled = !_toneInjectionEnabled;
|
||||
void Audio::toggleAudioSourceInject() {
|
||||
_audioSourceInjectEnabled = !_audioSourceInjectEnabled;
|
||||
}
|
||||
|
||||
void Audio::selectAudioSourcePinkNoise() {
|
||||
_noiseSourceEnabled = Menu::getInstance()->isOptionChecked(MenuOption::AudioSourcePinkNoise);
|
||||
_toneSourceEnabled = !_noiseSourceEnabled;
|
||||
}
|
||||
|
||||
void Audio::selectAudioSourceSine440() {
|
||||
_toneSourceEnabled = Menu::getInstance()->isOptionChecked(MenuOption::AudioSourceSine440);
|
||||
_noiseSourceEnabled = !_toneSourceEnabled;
|
||||
}
|
||||
|
||||
void Audio::toggleAudioSpatialProcessing() {
|
||||
|
|
|
@ -20,6 +20,12 @@
|
|||
#include "Recorder.h"
|
||||
#include "RingBufferHistory.h"
|
||||
#include "MovingMinMaxAvg.h"
|
||||
#include "AudioRingBuffer.h"
|
||||
#include "AudioFormat.h"
|
||||
#include "AudioBuffer.h"
|
||||
#include "AudioSourceTone.h"
|
||||
#include "AudioSourceNoise.h"
|
||||
#include "AudioGain.h"
|
||||
#include "AudioFilter.h"
|
||||
#include "AudioFilterBank.h"
|
||||
|
||||
|
@ -116,7 +122,9 @@ public slots:
|
|||
void audioMixerKilled();
|
||||
void toggleMute();
|
||||
void toggleAudioNoiseReduction();
|
||||
void toggleToneInjection();
|
||||
void toggleAudioSourceInject();
|
||||
void selectAudioSourcePinkNoise();
|
||||
void selectAudioSourceSine440();
|
||||
void toggleScope();
|
||||
void toggleScopePause();
|
||||
void toggleStats();
|
||||
|
@ -199,7 +207,8 @@ private:
|
|||
int _noiseGateSampleCounter;
|
||||
bool _noiseGateOpen;
|
||||
bool _noiseGateEnabled;
|
||||
bool _toneInjectionEnabled;
|
||||
bool _audioSourceInjectEnabled;
|
||||
|
||||
int _noiseGateFramesToClose;
|
||||
int _totalInputAudioSamples;
|
||||
|
||||
|
@ -282,10 +291,27 @@ private:
|
|||
int _framesPerScope;
|
||||
int _samplesPerScope;
|
||||
|
||||
// Multi-band parametric EQ
|
||||
bool _peqEnabled;
|
||||
AudioFilterPEQ3m _peq;
|
||||
// Input framebuffer
|
||||
AudioBufferFloat32 _inputFrameBuffer;
|
||||
|
||||
// Input gain
|
||||
AudioGain _inputGain;
|
||||
|
||||
// Post tone/pink noise generator gain
|
||||
AudioGain _sourceGain;
|
||||
|
||||
// Pink noise source
|
||||
bool _noiseSourceEnabled;
|
||||
AudioSourcePinkNoise _noiseSource;
|
||||
|
||||
// Tone source
|
||||
bool _toneSourceEnabled;
|
||||
AudioSourceTone _toneSource;
|
||||
|
||||
// Multi-band parametric EQ
|
||||
bool _peqEnabled;
|
||||
AudioFilterPEQ3m _peq;
|
||||
|
||||
QMutex _guard;
|
||||
QByteArray* _scopeInput;
|
||||
QByteArray* _scopeOutputLeft;
|
||||
|
|
|
@ -262,8 +262,8 @@ CameraScriptableObject::CameraScriptableObject(Camera* camera, ViewFrustum* view
|
|||
}
|
||||
|
||||
PickRay CameraScriptableObject::computePickRay(float x, float y) {
|
||||
float screenWidth = Application::getInstance()->getGLWidget()->getDeviceWidth();
|
||||
float screenHeight = Application::getInstance()->getGLWidget()->getDeviceHeight();
|
||||
float screenWidth = Application::getInstance()->getGLWidget()->width();
|
||||
float screenHeight = Application::getInstance()->getGLWidget()->height();
|
||||
PickRay result;
|
||||
if (OculusManager::isConnected()) {
|
||||
result.origin = _camera->getPosition();
|
||||
|
|
|
@ -43,14 +43,6 @@ int GLCanvas::getDeviceHeight() const {
|
|||
return height() * (windowHandle() ? windowHandle()->devicePixelRatio() : 1.0f);
|
||||
}
|
||||
|
||||
int GLCanvas::getDeviceX(int x) const {
|
||||
return x * getDeviceWidth() / width();
|
||||
}
|
||||
|
||||
int GLCanvas::getDeviceY(int y) const {
|
||||
return y * getDeviceHeight() / height();
|
||||
}
|
||||
|
||||
void GLCanvas::initializeGL() {
|
||||
Application::getInstance()->initializeGL();
|
||||
setAttribute(Qt::WA_AcceptTouchEvents);
|
||||
|
|
|
@ -26,9 +26,6 @@ public:
|
|||
int getDeviceHeight() const;
|
||||
QSize getDeviceSize() const { return QSize(getDeviceWidth(), getDeviceHeight()); }
|
||||
|
||||
int getDeviceX(int x) const;
|
||||
int getDeviceY(int y) const;
|
||||
|
||||
protected:
|
||||
|
||||
QTimer _frameTimer;
|
||||
|
|
|
@ -545,11 +545,31 @@ Menu::Menu() :
|
|||
0,
|
||||
this,
|
||||
SLOT(muteEnvironment()));
|
||||
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioToneInjection,
|
||||
|
||||
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioSourceInject,
|
||||
0,
|
||||
false,
|
||||
appInstance->getAudio(),
|
||||
SLOT(toggleToneInjection()));
|
||||
SLOT(toggleAudioSourceInject()));
|
||||
QMenu* audioSourceMenu = audioDebugMenu->addMenu("Generated Audio Source");
|
||||
{
|
||||
QAction *pinkNoise = addCheckableActionToQMenuAndActionHash(audioSourceMenu, MenuOption::AudioSourcePinkNoise,
|
||||
0,
|
||||
false,
|
||||
appInstance->getAudio(),
|
||||
SLOT(selectAudioSourcePinkNoise()));
|
||||
|
||||
QAction *sine440 = addCheckableActionToQMenuAndActionHash(audioSourceMenu, MenuOption::AudioSourceSine440,
|
||||
0,
|
||||
true,
|
||||
appInstance->getAudio(),
|
||||
SLOT(selectAudioSourceSine440()));
|
||||
|
||||
QActionGroup* audioSourceGroup = new QActionGroup(audioSourceMenu);
|
||||
audioSourceGroup->addAction(pinkNoise);
|
||||
audioSourceGroup->addAction(sine440);
|
||||
}
|
||||
|
||||
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioScope,
|
||||
Qt::CTRL | Qt::Key_P, false,
|
||||
appInstance->getAudio(),
|
||||
|
|
|
@ -347,7 +347,9 @@ namespace MenuOption {
|
|||
const QString AudioSpatialProcessingSlightlyRandomSurfaces = "Slightly Random Surfaces";
|
||||
const QString AudioSpatialProcessingStereoSource = "Stereo Source";
|
||||
const QString AudioSpatialProcessingWithDiffusions = "With Diffusions";
|
||||
const QString AudioToneInjection = "Inject Test Tone";
|
||||
const QString AudioSourceInject = "Generated Audio";
|
||||
const QString AudioSourcePinkNoise = "Pink Noise";
|
||||
const QString AudioSourceSine440 = "Sine 440hz";
|
||||
const QString Avatars = "Avatars";
|
||||
const QString AvatarsReceiveShadows = "Avatars Receive Shadows";
|
||||
const QString Bandwidth = "Bandwidth Display";
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
|
||||
#include <vector>
|
||||
|
||||
#include <QDesktopWidget>
|
||||
#include <QWindow>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
#include <glm/gtx/vector_angle.hpp>
|
||||
|
@ -50,7 +53,7 @@ Avatar::Avatar() :
|
|||
AvatarData(),
|
||||
_skeletonModel(this),
|
||||
_bodyYawDelta(0.0f),
|
||||
_lastPosition(0.0f),
|
||||
_lastPosition(_position),
|
||||
_velocity(0.0f),
|
||||
_lastVelocity(0.0f),
|
||||
_acceleration(0.0f),
|
||||
|
@ -204,7 +207,9 @@ void Avatar::simulate(float deltaTime) {
|
|||
_displayNameAlpha = abs(_displayNameAlpha - _displayNameTargetAlpha) < 0.01f ? _displayNameTargetAlpha : _displayNameAlpha;
|
||||
}
|
||||
|
||||
_position += _velocity * deltaTime;
|
||||
// NOTE: we shouldn't extrapolate an Avatar instance forward in time...
|
||||
// until velocity is in AvatarData update message.
|
||||
//_position += _velocity * deltaTime;
|
||||
measureMotionDerivatives(deltaTime);
|
||||
}
|
||||
|
||||
|
@ -223,20 +228,6 @@ void Avatar::measureMotionDerivatives(float deltaTime) {
|
|||
_lastOrientation = getOrientation();
|
||||
}
|
||||
|
||||
void Avatar::setPosition(const glm::vec3 position, bool overideReferential) {
|
||||
AvatarData::setPosition(position, overideReferential);
|
||||
_lastPosition = position;
|
||||
_velocity = glm::vec3(0.0f);
|
||||
_lastVelocity = glm::vec3(0.0f);
|
||||
}
|
||||
|
||||
void Avatar::slamPosition(const glm::vec3& newPosition) {
|
||||
_position = newPosition;
|
||||
_lastPosition = newPosition;
|
||||
_velocity = glm::vec3(0.0f);
|
||||
_lastVelocity = glm::vec3(0.0f);
|
||||
}
|
||||
|
||||
void Avatar::setMouseRay(const glm::vec3 &origin, const glm::vec3 &direction) {
|
||||
_mouseRayOrigin = origin;
|
||||
_mouseRayDirection = direction;
|
||||
|
@ -667,7 +658,8 @@ void Avatar::renderDisplayName() {
|
|||
|
||||
if (success) {
|
||||
double textWindowHeight = abs(result1[1] - result0[1]);
|
||||
float scaleFactor = (textWindowHeight > EPSILON) ? 1.0f / textWindowHeight : 1.0f;
|
||||
float scaleFactor = QApplication::desktop()->windowHandle()->devicePixelRatio() *
|
||||
((textWindowHeight > EPSILON) ? 1.0f / textWindowHeight : 1.0f);
|
||||
glScalef(scaleFactor, scaleFactor, 1.0);
|
||||
|
||||
glScalef(1.0f, -1.0f, 1.0f); // TextRenderer::draw paints the text upside down in y axis
|
||||
|
|
|
@ -161,9 +161,6 @@ public:
|
|||
/// \param vector position to be scaled. Will store the result
|
||||
void scaleVectorRelativeToPosition(glm::vec3 &positionToScale) const;
|
||||
|
||||
void setPosition(const glm::vec3 position, bool overideReferential = false);
|
||||
void slamPosition(const glm::vec3& newPosition);
|
||||
|
||||
public slots:
|
||||
void updateCollisionGroups();
|
||||
|
||||
|
|
|
@ -609,6 +609,13 @@ void MyAvatar::setGravity(const glm::vec3& gravity) {
|
|||
// so it continues to point opposite to the previous gravity setting.
|
||||
}
|
||||
|
||||
void MyAvatar::slamPosition(const glm::vec3& newPosition) {
|
||||
AvatarData::setPosition(newPosition);
|
||||
_lastPosition = _position;
|
||||
_velocity = glm::vec3(0.0f);
|
||||
_lastVelocity = glm::vec3(0.0f);
|
||||
}
|
||||
|
||||
AnimationHandlePointer MyAvatar::addAnimationHandle() {
|
||||
AnimationHandlePointer handle = _skeletonModel.createAnimationHandle();
|
||||
_animationHandles.append(handle);
|
||||
|
@ -797,9 +804,11 @@ void MyAvatar::loadData(QSettings* settings) {
|
|||
|
||||
getHead()->setBasePitch(loadSetting(settings, "headPitch", 0.0f));
|
||||
|
||||
_position.x = loadSetting(settings, "position_x", START_LOCATION.x);
|
||||
_position.y = loadSetting(settings, "position_y", START_LOCATION.y);
|
||||
_position.z = loadSetting(settings, "position_z", START_LOCATION.z);
|
||||
glm::vec3 newPosition;
|
||||
newPosition.x = loadSetting(settings, "position_x", START_LOCATION.x);
|
||||
newPosition.y = loadSetting(settings, "position_y", START_LOCATION.y);
|
||||
newPosition.z = loadSetting(settings, "position_z", START_LOCATION.z);
|
||||
slamPosition(newPosition);
|
||||
|
||||
getHead()->setPupilDilation(loadSetting(settings, "pupilDilation", 0.0f));
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ public:
|
|||
void setLeanScale(float scale) { _leanScale = scale; }
|
||||
void setLocalGravity(glm::vec3 gravity);
|
||||
void setShouldRenderLocally(bool shouldRender) { _shouldRender = shouldRender; }
|
||||
void slamPosition(const glm::vec3& position);
|
||||
|
||||
// getters
|
||||
float getLeanScale() const { return _leanScale; }
|
||||
|
|
|
@ -209,8 +209,8 @@ void PrioVR::renderCalibrationCountdown() {
|
|||
}
|
||||
static TextRenderer textRenderer(MONO_FONT_FAMILY, 18, QFont::Bold, false, TextRenderer::OUTLINE_EFFECT, 2);
|
||||
QByteArray text = "Assume T-Pose in " + QByteArray::number(secondsRemaining) + "...";
|
||||
textRenderer.draw((Application::getInstance()->getGLWidget()->getDeviceWidth() -
|
||||
textRenderer.computeWidth(text.constData())) / 2, Application::getInstance()->getGLWidget()->getDeviceHeight() / 2,
|
||||
textRenderer.draw((Application::getInstance()->getGLWidget()->width() -
|
||||
textRenderer.computeWidth(text.constData())) / 2, Application::getInstance()->getGLWidget()->height() / 2,
|
||||
text);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -396,10 +396,10 @@ void SixenseManager::emulateMouse(PalmData* palm, int index) {
|
|||
float yAngle = 0.5f - ((atan2(direction.z, direction.y) + M_PI_2));
|
||||
|
||||
// Get the pixel range over which the xAngle and yAngle are scaled
|
||||
float cursorRange = widget->getDeviceWidth() * getCursorPixelRangeMult();
|
||||
float cursorRange = widget->width() * getCursorPixelRangeMult();
|
||||
|
||||
pos.setX(widget->getDeviceWidth() / 2.0f + cursorRange * xAngle);
|
||||
pos.setY(widget->getDeviceHeight() / 2.0f + cursorRange * yAngle);
|
||||
pos.setX(widget->width() / 2.0f + cursorRange * xAngle);
|
||||
pos.setY(widget->height() / 2.0f + cursorRange * yAngle);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -205,7 +205,7 @@ bool LocationManager::goToDestination(QString destination) {
|
|||
MyAvatar::sendKillAvatar();
|
||||
|
||||
qDebug("Going To Location: %f, %f, %f...", x, y, z);
|
||||
myAvatar->setPosition(newAvatarPos);
|
||||
myAvatar->slamPosition(newAvatarPos);
|
||||
emit myAvatar->transformChanged();
|
||||
}
|
||||
|
||||
|
|
|
@ -257,7 +257,7 @@ void ControllerScriptingInterface::releaseJoystick(int joystickIndex) {
|
|||
|
||||
glm::vec2 ControllerScriptingInterface::getViewportDimensions() const {
|
||||
GLCanvas* widget = Application::getInstance()->getGLWidget();
|
||||
return glm::vec2(widget->getDeviceWidth(), widget->getDeviceHeight());
|
||||
return glm::vec2(widget->width(), widget->height());
|
||||
}
|
||||
|
||||
AbstractInputController* ControllerScriptingInterface::createInputController(const QString& deviceName, const QString& tracker) {
|
||||
|
|
|
@ -99,14 +99,14 @@ void ApplicationOverlay::renderOverlay(bool renderToTexture) {
|
|||
glPushMatrix();
|
||||
|
||||
glLoadIdentity();
|
||||
gluOrtho2D(0, glWidget->getDeviceWidth(), glWidget->getDeviceHeight(), 0);
|
||||
gluOrtho2D(0, glWidget->width(), glWidget->height(), 0);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
renderAudioMeter();
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::HeadMouse)) {
|
||||
myAvatar->renderHeadMouse(glWidget->getDeviceWidth(), glWidget->getDeviceHeight());
|
||||
myAvatar->renderHeadMouse(glWidget->width(), glWidget->height());
|
||||
}
|
||||
|
||||
renderStatsAndLogs();
|
||||
|
@ -305,8 +305,8 @@ QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const {
|
|||
float u = asin(collisionPos.x) / (_textureFov)+0.5f;
|
||||
float v = 1.0 - (asin(collisionPos.y) / (_textureFov)+0.5f);
|
||||
|
||||
rv.setX(u * glWidget->getDeviceWidth());
|
||||
rv.setY(v * glWidget->getDeviceHeight());
|
||||
rv.setX(u * glWidget->width());
|
||||
rv.setY(v * glWidget->height());
|
||||
}
|
||||
} else {
|
||||
//if they did not click on the overlay, just set the coords to INT_MAX
|
||||
|
@ -323,8 +323,8 @@ QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const {
|
|||
ndcSpacePos = glm::vec3(clipSpacePos) / clipSpacePos.w;
|
||||
}
|
||||
|
||||
rv.setX(((ndcSpacePos.x + 1.0) / 2.0) * glWidget->getDeviceWidth());
|
||||
rv.setY((1.0 - ((ndcSpacePos.y + 1.0) / 2.0)) * glWidget->getDeviceHeight());
|
||||
rv.setX(((ndcSpacePos.x + 1.0) / 2.0) * glWidget->width());
|
||||
rv.setY((1.0 - ((ndcSpacePos.y + 1.0) / 2.0)) * glWidget->height());
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
@ -496,11 +496,11 @@ void ApplicationOverlay::displayOverlayTexture3DTV(Camera& whichCamera, float as
|
|||
//draw the mouse pointer
|
||||
glBindTexture(GL_TEXTURE_2D, _crosshairTexture);
|
||||
|
||||
const float reticleSize = 40.0f / application->getGLWidget()->getDeviceWidth() * quadWidth;
|
||||
const float reticleSize = 40.0f / application->getGLWidget()->width() * quadWidth;
|
||||
x -= reticleSize / 2.0f;
|
||||
y += reticleSize / 2.0f;
|
||||
const float mouseX = (application->getMouseX() / (float)application->getGLWidget()->getDeviceWidth()) * quadWidth;
|
||||
const float mouseY = (1.0 - (application->getMouseY() / (float)application->getGLWidget()->getDeviceHeight())) * quadHeight;
|
||||
const float mouseX = (application->getMouseX() / (float)application->getGLWidget()->width()) * quadWidth;
|
||||
const float mouseY = (1.0 - (application->getMouseY() / (float)application->getGLWidget()->height())) * quadHeight;
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
|
||||
|
@ -671,14 +671,14 @@ void ApplicationOverlay::renderControllerPointers() {
|
|||
float yAngle = 0.5f - ((atan2(direction.z, direction.y) + M_PI_2));
|
||||
|
||||
// Get the pixel range over which the xAngle and yAngle are scaled
|
||||
float cursorRange = glWidget->getDeviceWidth() * application->getSixenseManager()->getCursorPixelRangeMult();
|
||||
float cursorRange = glWidget->width() * application->getSixenseManager()->getCursorPixelRangeMult();
|
||||
|
||||
mouseX = (glWidget->getDeviceWidth() / 2.0f + cursorRange * xAngle);
|
||||
mouseY = (glWidget->getDeviceHeight() / 2.0f + cursorRange * yAngle);
|
||||
mouseX = (glWidget->width() / 2.0f + cursorRange * xAngle);
|
||||
mouseY = (glWidget->height() / 2.0f + cursorRange * yAngle);
|
||||
}
|
||||
|
||||
//If the cursor is out of the screen then don't render it
|
||||
if (mouseX < 0 || mouseX >= glWidget->getDeviceWidth() || mouseY < 0 || mouseY >= glWidget->getDeviceHeight()) {
|
||||
if (mouseX < 0 || mouseX >= glWidget->width() || mouseY < 0 || mouseY >= glWidget->height()) {
|
||||
_reticleActive[index] = false;
|
||||
continue;
|
||||
}
|
||||
|
@ -709,8 +709,8 @@ void ApplicationOverlay::renderPointersOculus(const glm::vec3& eyePos) {
|
|||
GLCanvas* glWidget = application->getGLWidget();
|
||||
glm::vec3 cursorVerts[4];
|
||||
|
||||
const int widgetWidth = glWidget->getDeviceWidth();
|
||||
const int widgetHeight = glWidget->getDeviceHeight();
|
||||
const int widgetWidth = glWidget->width();
|
||||
const int widgetHeight = glWidget->height();
|
||||
|
||||
const float reticleSize = 50.0f;
|
||||
|
||||
|
@ -850,8 +850,8 @@ void ApplicationOverlay::renderMagnifier(int mouseX, int mouseY, float sizeMult,
|
|||
Application* application = Application::getInstance();
|
||||
GLCanvas* glWidget = application->getGLWidget();
|
||||
|
||||
const int widgetWidth = glWidget->getDeviceWidth();
|
||||
const int widgetHeight = glWidget->getDeviceHeight();
|
||||
const int widgetWidth = glWidget->width();
|
||||
const int widgetHeight = glWidget->height();
|
||||
|
||||
const float magnifyWidth = MAGNIFY_WIDTH * sizeMult;
|
||||
const float magnifyHeight = MAGNIFY_HEIGHT * sizeMult;
|
||||
|
@ -968,7 +968,7 @@ void ApplicationOverlay::renderAudioMeter() {
|
|||
float collisionSoundMagnitude = audio->getCollisionSoundMagnitude();
|
||||
const float VISIBLE_COLLISION_SOUND_MAGNITUDE = 0.5f;
|
||||
if (collisionSoundMagnitude > VISIBLE_COLLISION_SOUND_MAGNITUDE) {
|
||||
renderCollisionOverlay(glWidget->getDeviceWidth(), glWidget->getDeviceHeight(),
|
||||
renderCollisionOverlay(glWidget->width(), glWidget->height(),
|
||||
audio->getCollisionSoundMagnitude());
|
||||
}
|
||||
}
|
||||
|
@ -1019,16 +1019,16 @@ void ApplicationOverlay::renderAudioMeter() {
|
|||
if ((audio->getTimeSinceLastClip() > 0.f) && (audio->getTimeSinceLastClip() < CLIPPING_INDICATOR_TIME)) {
|
||||
const float MAX_MAGNITUDE = 0.7f;
|
||||
float magnitude = MAX_MAGNITUDE * (1 - audio->getTimeSinceLastClip() / CLIPPING_INDICATOR_TIME);
|
||||
renderCollisionOverlay(glWidget->getDeviceWidth(), glWidget->getDeviceHeight(), magnitude, 1.0f);
|
||||
renderCollisionOverlay(glWidget->width(), glWidget->height(), magnitude, 1.0f);
|
||||
}
|
||||
|
||||
audio->renderToolBox(MIRROR_VIEW_LEFT_PADDING + AUDIO_METER_GAP,
|
||||
audioMeterY,
|
||||
Menu::getInstance()->isOptionChecked(MenuOption::Mirror));
|
||||
|
||||
audio->renderScope(glWidget->getDeviceWidth(), glWidget->getDeviceHeight());
|
||||
audio->renderScope(glWidget->width(), glWidget->height());
|
||||
|
||||
audio->renderStats(WHITE_TEXT, glWidget->getDeviceWidth(), glWidget->getDeviceHeight());
|
||||
audio->renderStats(WHITE_TEXT, glWidget->width(), glWidget->height());
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
if (isClipping) {
|
||||
|
@ -1108,8 +1108,8 @@ void ApplicationOverlay::renderStatsAndLogs() {
|
|||
application->getPacketsPerSecond(), application->getBytesPerSecond(), voxelPacketsToProcess);
|
||||
// Bandwidth meter
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Bandwidth)) {
|
||||
Stats::drawBackground(0x33333399, glWidget->getDeviceWidth() - 296, glWidget->getDeviceHeight() - 68, 296, 68);
|
||||
bandwidthMeter->render(glWidget->getDeviceWidth(), glWidget->getDeviceHeight());
|
||||
Stats::drawBackground(0x33333399, glWidget->width() - 296, glWidget->height() - 68, 296, 68);
|
||||
bandwidthMeter->render(glWidget->width(), glWidget->height());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1122,7 +1122,7 @@ void ApplicationOverlay::renderStatsAndLogs() {
|
|||
(Menu::getInstance()->isOptionChecked(MenuOption::Stats) &&
|
||||
Menu::getInstance()->isOptionChecked(MenuOption::Bandwidth))
|
||||
? 80 : 20;
|
||||
drawText(glWidget->getDeviceWidth() - 100, glWidget->getDeviceHeight() - timerBottom,
|
||||
drawText(glWidget->width() - 100, glWidget->height() - timerBottom,
|
||||
0.30f, 0.0f, 0, frameTimer, WHITE_TEXT);
|
||||
}
|
||||
nodeBoundsDisplay.drawOverlay();
|
||||
|
@ -1247,8 +1247,8 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder() {
|
|||
|
||||
if (nodeList && !nodeList->getDomainHandler().isConnected()) {
|
||||
GLCanvas* glWidget = Application::getInstance()->getGLWidget();
|
||||
int right = glWidget->getDeviceWidth();
|
||||
int bottom = glWidget->getDeviceHeight();
|
||||
int right = glWidget->width();
|
||||
int bottom = glWidget->height();
|
||||
|
||||
glColor3f(CONNECTION_STATUS_BORDER_COLOR[0],
|
||||
CONNECTION_STATUS_BORDER_COLOR[1],
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <limits>
|
||||
|
||||
// include this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
|
@ -37,6 +39,8 @@
|
|||
#include "Application.h"
|
||||
#include "MetavoxelEditor.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
enum GridPlane {
|
||||
GRID_PLANE_XY, GRID_PLANE_XZ, GRID_PLANE_YZ
|
||||
};
|
||||
|
@ -959,7 +963,8 @@ void HeightfieldTool::render() {
|
|||
}
|
||||
|
||||
ImportHeightfieldTool::ImportHeightfieldTool(MetavoxelEditor* editor) :
|
||||
HeightfieldTool(editor, "Import Heightfield") {
|
||||
HeightfieldTool(editor, "Import Heightfield"),
|
||||
_loadingImage(false) {
|
||||
|
||||
_form->addRow("Block Size:", _blockSize = new QSpinBox());
|
||||
_blockSize->setPrefix("2^");
|
||||
|
@ -970,6 +975,32 @@ ImportHeightfieldTool::ImportHeightfieldTool(MetavoxelEditor* editor) :
|
|||
&ImportHeightfieldTool::updatePreview);
|
||||
_form->addRow("Height:", _height = new QPushButton());
|
||||
connect(_height, &QAbstractButton::clicked, this, &ImportHeightfieldTool::selectHeightFile);
|
||||
|
||||
_form->addRow(_rawOptions = new QWidget());
|
||||
QHBoxLayout* rawLayout = new QHBoxLayout();
|
||||
_rawOptions->setLayout(rawLayout);
|
||||
_rawOptions->setVisible(false);
|
||||
|
||||
rawLayout->addStretch(1);
|
||||
rawLayout->addWidget(new QLabel("Scale:"));
|
||||
rawLayout->addWidget(_heightScale = new QDoubleSpinBox());
|
||||
const double MAX_OFFSET_SCALE = 100000.0;
|
||||
_heightScale->setMaximum(MAX_OFFSET_SCALE);
|
||||
_heightScale->setSingleStep(0.0001);
|
||||
_heightScale->setDecimals(4);
|
||||
_heightScale->setValue(1.0);
|
||||
connect(_heightScale, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), this,
|
||||
&ImportHeightfieldTool::updateHeightImage);
|
||||
|
||||
rawLayout->addSpacing(15);
|
||||
rawLayout->addWidget(new QLabel("Offset:"));
|
||||
rawLayout->addWidget(_heightOffset = new QDoubleSpinBox());
|
||||
_heightOffset->setMinimum(-MAX_OFFSET_SCALE);
|
||||
_heightOffset->setMaximum(MAX_OFFSET_SCALE);
|
||||
_heightOffset->setDecimals(4);
|
||||
connect(_heightOffset, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), this,
|
||||
&ImportHeightfieldTool::updateHeightImage);
|
||||
|
||||
_form->addRow("Color:", _color = new QPushButton());
|
||||
connect(_color, &QAbstractButton::clicked, this, &ImportHeightfieldTool::selectColorFile);
|
||||
|
||||
|
@ -1012,22 +1043,50 @@ void ImportHeightfieldTool::apply() {
|
|||
}
|
||||
}
|
||||
|
||||
const float EIGHT_BIT_MAXIMUM = 255.0f;
|
||||
|
||||
void ImportHeightfieldTool::selectHeightFile() {
|
||||
QString filename = QFileDialog::getOpenFileName(this, "Select Height Image", QString(), "Images (*.png *.jpg)");
|
||||
QString filename = QFileDialog::getOpenFileName(this, "Select Height Image", QString(),
|
||||
"Images (*.png *.jpg *.bmp *.raw)");
|
||||
if (filename.isNull()) {
|
||||
return;
|
||||
}
|
||||
if (filename.toLower().endsWith(".raw")) {
|
||||
QFile input(filename);
|
||||
input.open(QIODevice::ReadOnly);
|
||||
QDataStream in(&input);
|
||||
in.setByteOrder(QDataStream::LittleEndian);
|
||||
_rawHeight.clear();
|
||||
int minHeight = numeric_limits<quint16>::max();
|
||||
int maxHeight = numeric_limits<quint16>::min();
|
||||
while (!in.atEnd()) {
|
||||
quint16 height;
|
||||
in >> height;
|
||||
_rawHeight.append(height);
|
||||
minHeight = qMin(minHeight, (int)height);
|
||||
maxHeight = qMax(maxHeight, (int)height);
|
||||
}
|
||||
_height->setText(filename);
|
||||
_rawOptions->setVisible(true);
|
||||
_loadingImage = true;
|
||||
_heightScale->setValue((EIGHT_BIT_MAXIMUM - 1.0f) / (maxHeight - minHeight));
|
||||
_heightOffset->setValue(-minHeight * _heightScale->value() + 1.0);
|
||||
_loadingImage = false;
|
||||
updateHeightImage();
|
||||
return;
|
||||
}
|
||||
if (!_heightImage.load(filename)) {
|
||||
QMessageBox::warning(this, "Invalid Image", "The selected image could not be read.");
|
||||
return;
|
||||
}
|
||||
_rawOptions->setVisible(false);
|
||||
_heightImage = _heightImage.convertToFormat(QImage::Format_RGB888);
|
||||
_height->setText(filename);
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void ImportHeightfieldTool::selectColorFile() {
|
||||
QString filename = QFileDialog::getOpenFileName(this, "Select Color Image", QString(), "Images (*.png *.jpg)");
|
||||
QString filename = QFileDialog::getOpenFileName(this, "Select Color Image", QString(), "Images (*.png *.jpg *.bmp)");
|
||||
if (filename.isNull()) {
|
||||
return;
|
||||
}
|
||||
|
@ -1040,6 +1099,26 @@ void ImportHeightfieldTool::selectColorFile() {
|
|||
updatePreview();
|
||||
}
|
||||
|
||||
void ImportHeightfieldTool::updateHeightImage() {
|
||||
if (_loadingImage) {
|
||||
return;
|
||||
}
|
||||
int size = glm::sqrt(_rawHeight.size());
|
||||
_heightImage = QImage(size, size, QImage::Format_RGB888);
|
||||
const quint16* src = _rawHeight.constData();
|
||||
float scale = _heightScale->value(), offset = _heightOffset->value();
|
||||
for (int y = 0; y < size; y++) {
|
||||
uchar* dest = _heightImage.scanLine(y);
|
||||
for (const quint16* end = src + size; src != end; src++) {
|
||||
uchar height = glm::clamp(*src * scale + offset, 1.0f, EIGHT_BIT_MAXIMUM);
|
||||
*dest++ = height;
|
||||
*dest++ = height;
|
||||
*dest++ = height;
|
||||
}
|
||||
}
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void ImportHeightfieldTool::updatePreview() {
|
||||
QVector<BufferDataPointer> buffers;
|
||||
if (_heightImage.width() > 0 && _heightImage.height() > 0) {
|
||||
|
@ -1061,7 +1140,7 @@ void ImportHeightfieldTool::updatePreview() {
|
|||
uchar* src = _heightImage.scanLine(extendedI + y) + extendedJ * DataBlock::COLOR_BYTES;
|
||||
char* dest = height.data() + (y + offsetY) * heightSize + offsetX;
|
||||
for (int x = 0; x < columns; x++) {
|
||||
*dest++ = *src;
|
||||
*dest++ = qMax((uchar)1, *src);
|
||||
src += DataBlock::COLOR_BYTES;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -291,6 +291,7 @@ private slots:
|
|||
|
||||
void selectHeightFile();
|
||||
void selectColorFile();
|
||||
void updateHeightImage();
|
||||
void updatePreview();
|
||||
void renderPreview();
|
||||
|
||||
|
@ -299,8 +300,14 @@ private:
|
|||
QSpinBox* _blockSize;
|
||||
|
||||
QPushButton* _height;
|
||||
QWidget* _rawOptions;
|
||||
QDoubleSpinBox* _heightScale;
|
||||
QDoubleSpinBox* _heightOffset;
|
||||
bool _loadingImage;
|
||||
|
||||
QPushButton* _color;
|
||||
|
||||
QVector<quint16> _rawHeight;
|
||||
QImage _heightImage;
|
||||
QImage _colorImage;
|
||||
|
||||
|
|
|
@ -41,8 +41,8 @@ void NodeBounds::draw() {
|
|||
// itself after the cursor disappears.
|
||||
Application* application = Application::getInstance();
|
||||
GLCanvas* glWidget = application->getGLWidget();
|
||||
float mouseX = application->getMouseX() / (float)glWidget->getDeviceWidth();
|
||||
float mouseY = application->getMouseY() / (float)glWidget->getDeviceHeight();
|
||||
float mouseX = application->getMouseX() / (float)glWidget->width();
|
||||
float mouseY = application->getMouseY() / (float)glWidget->height();
|
||||
glm::vec3 mouseRayOrigin;
|
||||
glm::vec3 mouseRayDirection;
|
||||
application->getViewFrustum()->computePickRay(mouseX, mouseY, mouseRayOrigin, mouseRayDirection);
|
||||
|
|
|
@ -57,7 +57,7 @@ Stats::Stats():
|
|||
_metavoxelReceiveTotal(0)
|
||||
{
|
||||
GLCanvas* glWidget = Application::getInstance()->getGLWidget();
|
||||
resetWidth(glWidget->getDeviceWidth(), 0);
|
||||
resetWidth(glWidget->width(), 0);
|
||||
}
|
||||
|
||||
void Stats::toggleExpanded() {
|
||||
|
@ -114,7 +114,7 @@ void Stats::checkClick(int mouseX, int mouseY, int mouseDragStartedX, int mouseD
|
|||
// top-right stats click
|
||||
lines = _expanded ? 11 : 3;
|
||||
statsHeight = lines * STATS_PELS_PER_LINE + 10;
|
||||
statsWidth = glWidget->getDeviceWidth() - statsX;
|
||||
statsWidth = glWidget->width() - statsX;
|
||||
if (mouseX > statsX && mouseX < statsX + statsWidth && mouseY > statsY && mouseY < statsY + statsHeight) {
|
||||
toggleExpanded();
|
||||
return;
|
||||
|
@ -123,7 +123,7 @@ void Stats::checkClick(int mouseX, int mouseY, int mouseDragStartedX, int mouseD
|
|||
|
||||
void Stats::resetWidth(int width, int horizontalOffset) {
|
||||
GLCanvas* glWidget = Application::getInstance()->getGLWidget();
|
||||
int extraSpace = glWidget->getDeviceWidth() - horizontalOffset -2
|
||||
int extraSpace = glWidget->width() - horizontalOffset -2
|
||||
- STATS_GENERAL_MIN_WIDTH
|
||||
- (Menu::getInstance()->isOptionChecked(MenuOption::TestPing) ? STATS_PING_MIN_WIDTH -1 : 0)
|
||||
- STATS_GEO_MIN_WIDTH
|
||||
|
@ -147,7 +147,7 @@ void Stats::resetWidth(int width, int horizontalOffset) {
|
|||
_pingStatsWidth += (int) extraSpace / panels;
|
||||
}
|
||||
_geoStatsWidth += (int) extraSpace / panels;
|
||||
_voxelStatsWidth += glWidget->getDeviceWidth() - (_generalStatsWidth + _pingStatsWidth + _geoStatsWidth + 3);
|
||||
_voxelStatsWidth += glWidget->width() - (_generalStatsWidth + _pingStatsWidth + _geoStatsWidth + 3);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -210,7 +210,7 @@ void Stats::display(
|
|||
std::stringstream voxelStats;
|
||||
|
||||
if (_lastHorizontalOffset != horizontalOffset) {
|
||||
resetWidth(glWidget->getDeviceWidth(), horizontalOffset);
|
||||
resetWidth(glWidget->width(), horizontalOffset);
|
||||
_lastHorizontalOffset = horizontalOffset;
|
||||
}
|
||||
|
||||
|
@ -410,7 +410,7 @@ void Stats::display(
|
|||
}
|
||||
}
|
||||
|
||||
drawBackground(backgroundColor, horizontalOffset, 0, glWidget->getDeviceWidth() - horizontalOffset,
|
||||
drawBackground(backgroundColor, horizontalOffset, 0, glWidget->width() - horizontalOffset,
|
||||
lines * STATS_PELS_PER_LINE + 10);
|
||||
horizontalOffset += 5;
|
||||
|
||||
|
|
|
@ -9,11 +9,14 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDesktopWidget>
|
||||
#include <QFont>
|
||||
#include <QPaintEngine>
|
||||
#include <QtDebug>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QWindow>
|
||||
|
||||
#include "InterfaceConfig.h"
|
||||
#include "TextRenderer.h"
|
||||
|
@ -25,10 +28,17 @@ Glyph::Glyph(int textureID, const QPoint& location, const QRect& bounds, int wid
|
|||
_textureID(textureID), _location(location), _bounds(bounds), _width(width) {
|
||||
}
|
||||
|
||||
TextRenderer::TextRenderer(const char* family, int pointSize, int weight,
|
||||
bool italic, EffectType effectType, int effectThickness, QColor color)
|
||||
: _font(family, pointSize, weight, italic), _metrics(_font), _effectType(effectType),
|
||||
_effectThickness(effectThickness), _x(IMAGE_SIZE), _y(IMAGE_SIZE), _rowHeight(0), _color(color) {
|
||||
TextRenderer::TextRenderer(const char* family, int pointSize, int weight, bool italic,
|
||||
EffectType effectType, int effectThickness, QColor color) :
|
||||
_font(family, pointSize, weight, italic),
|
||||
_metrics(_font),
|
||||
_effectType(effectType),
|
||||
_effectThickness(effectThickness),
|
||||
_x(IMAGE_SIZE),
|
||||
_y(IMAGE_SIZE),
|
||||
_rowHeight(0),
|
||||
_color(color) {
|
||||
|
||||
_font.setKerning(false);
|
||||
}
|
||||
|
||||
|
@ -73,7 +83,7 @@ int TextRenderer::draw(int x, int y, const char* str) {
|
|||
int bottom = y + glyph.bounds().y();
|
||||
int top = y + glyph.bounds().y() + glyph.bounds().height();
|
||||
|
||||
float scale = 1.0 / IMAGE_SIZE;
|
||||
float scale = QApplication::desktop()->windowHandle()->devicePixelRatio() / IMAGE_SIZE;
|
||||
float ls = glyph.location().x() * scale;
|
||||
float rs = (glyph.location().x() + glyph.bounds().width()) * scale;
|
||||
float bt = glyph.location().y() * scale;
|
||||
|
@ -119,21 +129,25 @@ const Glyph& TextRenderer::getGlyph(char c) {
|
|||
}
|
||||
// we use 'J' as a representative size for the solid block character
|
||||
QChar ch = (c == SOLID_BLOCK_CHAR) ? QChar('J') : QChar(c);
|
||||
QRect bounds = _metrics.boundingRect(ch);
|
||||
if (bounds.isEmpty()) {
|
||||
QRect baseBounds = _metrics.boundingRect(ch);
|
||||
if (baseBounds.isEmpty()) {
|
||||
glyph = Glyph(0, QPoint(), QRect(), _metrics.width(ch));
|
||||
return glyph;
|
||||
}
|
||||
// grow the bounds to account for effect, if any
|
||||
if (_effectType == SHADOW_EFFECT) {
|
||||
bounds.adjust(-_effectThickness, 0, 0, _effectThickness);
|
||||
baseBounds.adjust(-_effectThickness, 0, 0, _effectThickness);
|
||||
|
||||
} else if (_effectType == OUTLINE_EFFECT) {
|
||||
bounds.adjust(-_effectThickness, -_effectThickness, _effectThickness, _effectThickness);
|
||||
baseBounds.adjust(-_effectThickness, -_effectThickness, _effectThickness, _effectThickness);
|
||||
}
|
||||
|
||||
// grow the bounds to account for antialiasing
|
||||
bounds.adjust(-1, -1, 1, 1);
|
||||
baseBounds.adjust(-1, -1, 1, 1);
|
||||
|
||||
// adjust bounds for device pixel scaling
|
||||
float ratio = QApplication::desktop()->windowHandle()->devicePixelRatio();
|
||||
QRect bounds(baseBounds.x() * ratio, baseBounds.y() * ratio, baseBounds.width() * ratio, baseBounds.height() * ratio);
|
||||
|
||||
if (_x + bounds.width() > IMAGE_SIZE) {
|
||||
// we can't fit it on the current row; move to next
|
||||
|
@ -162,9 +176,16 @@ const Glyph& TextRenderer::getGlyph(char c) {
|
|||
} else {
|
||||
image.fill(0);
|
||||
QPainter painter(&image);
|
||||
painter.setFont(_font);
|
||||
QFont font = _font;
|
||||
if (ratio == 1.0f) {
|
||||
painter.setFont(_font);
|
||||
} else {
|
||||
QFont enlargedFont = _font;
|
||||
enlargedFont.setPointSize(_font.pointSize() * ratio);
|
||||
painter.setFont(enlargedFont);
|
||||
}
|
||||
if (_effectType == SHADOW_EFFECT) {
|
||||
for (int i = 0; i < _effectThickness; i++) {
|
||||
for (int i = 0; i < _effectThickness * ratio; i++) {
|
||||
painter.drawText(-bounds.x() - 1 - i, -bounds.y() + 1 + i, ch);
|
||||
}
|
||||
} else if (_effectType == OUTLINE_EFFECT) {
|
||||
|
@ -173,7 +194,7 @@ const Glyph& TextRenderer::getGlyph(char c) {
|
|||
font.setStyleStrategy(QFont::ForceOutline);
|
||||
path.addText(-bounds.x() - 0.5, -bounds.y() + 0.5, font, ch);
|
||||
QPen pen;
|
||||
pen.setWidth(_effectThickness);
|
||||
pen.setWidth(_effectThickness * ratio);
|
||||
pen.setJoinStyle(Qt::RoundJoin);
|
||||
pen.setCapStyle(Qt::RoundCap);
|
||||
painter.setPen(pen);
|
||||
|
@ -185,7 +206,7 @@ const Glyph& TextRenderer::getGlyph(char c) {
|
|||
}
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, _x, _y, bounds.width(), bounds.height(), GL_RGBA, GL_UNSIGNED_BYTE, image.constBits());
|
||||
|
||||
glyph = Glyph(_currentTextureID, QPoint(_x, _y), bounds, _metrics.width(ch));
|
||||
glyph = Glyph(_currentTextureID, QPoint(_x / ratio, _y / ratio), baseBounds, _metrics.width(ch));
|
||||
_x += bounds.width();
|
||||
_rowHeight = qMax(_rowHeight, bounds.height());
|
||||
|
||||
|
|
180
libraries/audio/src/AudioBuffer.h
Normal file
180
libraries/audio/src/AudioBuffer.h
Normal file
|
@ -0,0 +1,180 @@
|
|||
//
|
||||
// AudioBuffer.h
|
||||
// hifi
|
||||
//
|
||||
// Created by Craig Hansen-Sturm on 8/29/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_AudioBuffer_h
|
||||
#define hifi_AudioBuffer_h
|
||||
|
||||
#include <typeinfo>
|
||||
|
||||
template< typename T >
|
||||
class AudioFrameBuffer {
|
||||
|
||||
uint16_t _channelCount;
|
||||
uint16_t _channelCountMax;
|
||||
uint16_t _frameCount;
|
||||
uint16_t _frameCountMax;
|
||||
|
||||
T** _frameBuffer;
|
||||
|
||||
void allocateFrames() {
|
||||
_frameBuffer = new T*[_channelCountMax];
|
||||
if (_frameBuffer) {
|
||||
for (uint16_t i = 0; i < _channelCountMax; ++i) {
|
||||
_frameBuffer[i] = new T[_frameCountMax];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void deallocateFrames() {
|
||||
if (_frameBuffer) {
|
||||
for (uint16_t i = 0; i < _channelCountMax; ++i) {
|
||||
delete _frameBuffer[i];
|
||||
}
|
||||
delete _frameBuffer;
|
||||
}
|
||||
_frameBuffer = NULL;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
AudioFrameBuffer() :
|
||||
_channelCount(0),
|
||||
_frameCount(0),
|
||||
_frameCountMax(0),
|
||||
_frameBuffer(NULL) {
|
||||
}
|
||||
|
||||
AudioFrameBuffer(const uint16_t channelCount, const uint16_t frameCount) :
|
||||
_channelCount(channelCount),
|
||||
_channelCountMax(channelCount),
|
||||
_frameCount(frameCount),
|
||||
_frameCountMax(frameCount),
|
||||
_frameBuffer(NULL) {
|
||||
allocateFrames();
|
||||
}
|
||||
|
||||
~AudioFrameBuffer() {
|
||||
finalize();
|
||||
}
|
||||
|
||||
void initialize(const uint16_t channelCount, const uint16_t frameCount) {
|
||||
if (_frameBuffer) {
|
||||
finalize();
|
||||
}
|
||||
_channelCount = channelCount;
|
||||
_channelCountMax = channelCount;
|
||||
_frameCount = frameCount;
|
||||
_frameCountMax = frameCount;
|
||||
allocateFrames();
|
||||
}
|
||||
|
||||
void finalize() {
|
||||
deallocateFrames();
|
||||
_channelCount = 0;
|
||||
_channelCountMax = 0;
|
||||
_frameCount = 0;
|
||||
_frameCountMax = 0;
|
||||
}
|
||||
|
||||
T**& getFrameData() {
|
||||
return _frameBuffer;
|
||||
}
|
||||
|
||||
uint16_t getChannelCount() {
|
||||
return _channelCount;
|
||||
}
|
||||
|
||||
uint16_t getFrameCount() {
|
||||
return _frameCount;
|
||||
}
|
||||
|
||||
void zeroFrames() {
|
||||
if (!_frameBuffer) {
|
||||
return;
|
||||
}
|
||||
for (uint16_t i = 0; i < _channelCountMax; ++i) {
|
||||
memset(_frameBuffer[i], 0, sizeof(T)*_frameCountMax);
|
||||
}
|
||||
}
|
||||
|
||||
template< typename S >
|
||||
void copyFrames(uint16_t channelCount, const uint16_t frameCount, S* frames, const bool copyOut = false) {
|
||||
if ( !_frameBuffer || !frames) {
|
||||
return;
|
||||
}
|
||||
assert(channelCount <= _channelCountMax);
|
||||
assert(frameCount <= _frameCountMax);
|
||||
|
||||
_frameCount = frameCount; // we allow copying fewer frames than we've allocated
|
||||
_channelCount = channelCount; // we allow copying fewer channels that we've allocated
|
||||
|
||||
if (copyOut) {
|
||||
S* dst = frames;
|
||||
|
||||
if(typeid(T) == typeid(S)) { // source and destination types are the same
|
||||
for (int i = 0; i < _frameCount; ++i) {
|
||||
for (int j = 0; j < _channelCount; ++j) {
|
||||
*dst++ = _frameBuffer[j][i];
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(typeid(T) == typeid(float32_t) &&
|
||||
typeid(S) == typeid(int16_t)) {
|
||||
|
||||
const int scale = (2 << ((8 * sizeof(S)) - 1));
|
||||
|
||||
for (int i = 0; i < _frameCount; ++i) {
|
||||
for (int j = 0; j < _channelCount; ++j) {
|
||||
*dst++ = (S)(_frameBuffer[j][i] * scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert(0); // currently unsupported conversion
|
||||
}
|
||||
}
|
||||
}
|
||||
else { // copyIn
|
||||
S* src = frames;
|
||||
|
||||
if(typeid(T) == typeid(S)) { // source and destination types are the same
|
||||
for (int i = 0; i < _frameCount; ++i) {
|
||||
for (int j = 0; j < _channelCount; ++j) {
|
||||
_frameBuffer[j][i] = *src++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(typeid(T) == typeid(float32_t) &&
|
||||
typeid(S) == typeid(int16_t)) {
|
||||
|
||||
const int scale = (2 << ((8 * sizeof(S)) - 1));
|
||||
|
||||
for (int i = 0; i < _frameCount; ++i) {
|
||||
for (int j = 0; j < _channelCount; ++j) {
|
||||
_frameBuffer[j][i] = ((T)(*src++)) / scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert(0); // currently unsupported conversion
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
typedef AudioFrameBuffer< float32_t > AudioBufferFloat32;
|
||||
typedef AudioFrameBuffer< int32_t > AudioBufferSInt32;
|
||||
|
||||
#endif // hifi_AudioBuffer_h
|
||||
|
|
@ -37,11 +37,11 @@ public:
|
|||
//
|
||||
// ctor/dtor
|
||||
//
|
||||
AudioBiquad()
|
||||
: _xm1(0.)
|
||||
, _xm2(0.)
|
||||
, _ym1(0.)
|
||||
, _ym2(0.) {
|
||||
AudioBiquad() :
|
||||
_xm1(0.),
|
||||
_xm2(0.),
|
||||
_ym1(0.),
|
||||
_ym2(0.) {
|
||||
setParameters(0.,0.,0.,0.,0.);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,9 +9,12 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <SharedUtil.h>
|
||||
#include "AudioRingBuffer.h"
|
||||
#include "AudioFormat.h"
|
||||
#include "AudioBuffer.h"
|
||||
#include "AudioFilter.h"
|
||||
#include "AudioFilterBank.h"
|
||||
|
||||
|
|
|
@ -49,9 +49,9 @@ public:
|
|||
//
|
||||
// ctor/dtor
|
||||
//
|
||||
AudioFilterBank()
|
||||
: _sampleRate(0.)
|
||||
, _frameCount(0) {
|
||||
AudioFilterBank() :
|
||||
_sampleRate(0.0f),
|
||||
_frameCount(0) {
|
||||
for (int i = 0; i < _channelCount; ++i) {
|
||||
_buffer[ i ] = NULL;
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ public:
|
|||
//
|
||||
// public interface
|
||||
//
|
||||
void initialize(const float sampleRate, const int frameCount) {
|
||||
void initialize(const float sampleRate, const int frameCount = 0) {
|
||||
finalize();
|
||||
|
||||
for (int i = 0; i < _channelCount; ++i) {
|
||||
|
@ -141,6 +141,16 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void render(AudioBufferFloat32& frameBuffer) {
|
||||
|
||||
float32_t** samples = frameBuffer.getFrameData();
|
||||
for (uint16_t j = 0; j < frameBuffer.getChannelCount(); ++j) {
|
||||
for (int i = 0; i < _filterCount; ++i) {
|
||||
_filters[i][j].render( samples[j], samples[j], frameBuffer.getFrameCount() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void reset() {
|
||||
for (int i = 0; i < _filterCount; ++i) {
|
||||
for (int j = 0; j < _channelCount; ++j) {
|
||||
|
|
85
libraries/audio/src/AudioFormat.h
Normal file
85
libraries/audio/src/AudioFormat.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
//
|
||||
// AudioFormat.h
|
||||
// hifi
|
||||
//
|
||||
// Created by Craig Hansen-Sturm on 8/28/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_AudioFormat_h
|
||||
#define hifi_AudioFormat_h
|
||||
|
||||
#ifndef _FLOAT32_T
|
||||
#define _FLOAT32_T
|
||||
typedef float float32_t;
|
||||
#endif
|
||||
|
||||
#ifndef _FLOAT64_T
|
||||
#define _FLOAT64_T
|
||||
typedef double float64_t;
|
||||
#endif
|
||||
|
||||
//
|
||||
// Audio format structure (currently for uncompressed streams only)
|
||||
//
|
||||
|
||||
struct AudioFormat {
|
||||
|
||||
struct Flags {
|
||||
uint32_t _isFloat : 1;
|
||||
uint32_t _isSigned : 1;
|
||||
uint32_t _isInterleaved : 1;
|
||||
uint32_t _isBigEndian : 1;
|
||||
uint32_t _isPacked : 1;
|
||||
uint32_t _reserved : 27;
|
||||
} _flags;
|
||||
|
||||
uint32_t _bytesPerFrame;
|
||||
uint32_t _channelsPerFrame;
|
||||
uint32_t _bitsPerChannel;
|
||||
float64_t _sampleRate;
|
||||
|
||||
|
||||
AudioFormat() {
|
||||
memset(this, 0, sizeof(*this));
|
||||
}
|
||||
~AudioFormat() { }
|
||||
|
||||
AudioFormat& operator=(const AudioFormat& fmt) {
|
||||
memcpy(this, &fmt, sizeof(*this));
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const AudioFormat& fmt) {
|
||||
return memcmp(this, &fmt, sizeof(*this)) == 0;
|
||||
}
|
||||
|
||||
bool operator!=(const AudioFormat& fmt) {
|
||||
return memcmp(this, &fmt, sizeof(*this)) != 0;
|
||||
}
|
||||
|
||||
void setCanonicalFloat32(uint32_t channels) {
|
||||
assert(channels > 0 && channels <= 2);
|
||||
_sampleRate = SAMPLE_RATE; // todo: create audio constants header
|
||||
_bitsPerChannel = sizeof(float32_t) * 8;
|
||||
_channelsPerFrame = channels;
|
||||
_bytesPerFrame = _channelsPerFrame * _bitsPerChannel / 8;
|
||||
_flags._isFloat = true;
|
||||
_flags._isInterleaved = _channelsPerFrame > 1;
|
||||
}
|
||||
|
||||
void setCanonicalInt16(uint32_t channels) {
|
||||
assert(channels > 0 && channels <= 2);
|
||||
_sampleRate = SAMPLE_RATE; // todo: create audio constants header
|
||||
_bitsPerChannel = sizeof(int16_t) * 8;
|
||||
_channelsPerFrame = channels;
|
||||
_bytesPerFrame = _channelsPerFrame * _bitsPerChannel / 8;
|
||||
_flags._isSigned = true;
|
||||
_flags._isInterleaved = _channelsPerFrame > 1;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // hifi_AudioFormat_h
|
99
libraries/audio/src/AudioGain.h
Normal file
99
libraries/audio/src/AudioGain.h
Normal file
|
@ -0,0 +1,99 @@
|
|||
//
|
||||
// AudioGain.h
|
||||
// hifi
|
||||
//
|
||||
// Created by Craig Hansen-Sturm on 9/1/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_AudioGain_h
|
||||
#define hifi_AudioGain_h
|
||||
|
||||
class AudioGain
|
||||
{
|
||||
float32_t _gain;
|
||||
bool _mute;
|
||||
|
||||
public:
|
||||
AudioGain() {
|
||||
initialize();
|
||||
}
|
||||
|
||||
~AudioGain() {
|
||||
finalize();
|
||||
}
|
||||
|
||||
void initialize() {
|
||||
setParameters(1.0f,0.0f);
|
||||
}
|
||||
|
||||
void finalize() {
|
||||
}
|
||||
|
||||
void reset() {
|
||||
initialize();
|
||||
}
|
||||
|
||||
void setParameters(const float gain, const float mute) {
|
||||
_gain = std::min(std::max(gain, 0.0f), 1.0f);
|
||||
_mute = mute != 0.0f;
|
||||
|
||||
}
|
||||
|
||||
void getParameters(float& gain, float& mute) {
|
||||
gain = _gain;
|
||||
mute = _mute ? 1.0f : 0.0f;
|
||||
}
|
||||
|
||||
void render(AudioBufferFloat32& frameBuffer) {
|
||||
if (_mute) {
|
||||
frameBuffer.zeroFrames();
|
||||
return;
|
||||
}
|
||||
|
||||
float32_t** samples = frameBuffer.getFrameData();
|
||||
for (uint16_t j = 0; j < frameBuffer.getChannelCount(); ++j) {
|
||||
for (uint16_t i = 0; i < frameBuffer.getFrameCount(); i += 32) {
|
||||
samples[j][i + 0] *= _gain;
|
||||
samples[j][i + 1] *= _gain;
|
||||
samples[j][i + 2] *= _gain;
|
||||
samples[j][i + 3] *= _gain;
|
||||
samples[j][i + 4] *= _gain;
|
||||
samples[j][i + 5] *= _gain;
|
||||
samples[j][i + 6] *= _gain;
|
||||
samples[j][i + 7] *= _gain;
|
||||
samples[j][i + 8] *= _gain;
|
||||
samples[j][i + 9] *= _gain;
|
||||
samples[j][i + 10] *= _gain;
|
||||
samples[j][i + 11] *= _gain;
|
||||
samples[j][i + 12] *= _gain;
|
||||
samples[j][i + 13] *= _gain;
|
||||
samples[j][i + 14] *= _gain;
|
||||
samples[j][i + 15] *= _gain;
|
||||
samples[j][i + 16] *= _gain;
|
||||
samples[j][i + 17] *= _gain;
|
||||
samples[j][i + 18] *= _gain;
|
||||
samples[j][i + 19] *= _gain;
|
||||
samples[j][i + 20] *= _gain;
|
||||
samples[j][i + 21] *= _gain;
|
||||
samples[j][i + 22] *= _gain;
|
||||
samples[j][i + 23] *= _gain;
|
||||
samples[j][i + 24] *= _gain;
|
||||
samples[j][i + 25] *= _gain;
|
||||
samples[j][i + 26] *= _gain;
|
||||
samples[j][i + 27] *= _gain;
|
||||
samples[j][i + 28] *= _gain;
|
||||
samples[j][i + 29] *= _gain;
|
||||
samples[j][i + 30] *= _gain;
|
||||
samples[j][i + 31] *= _gain;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // AudioGain_h
|
||||
|
||||
|
21
libraries/audio/src/AudioSourceNoise.cpp
Normal file
21
libraries/audio/src/AudioSourceNoise.cpp
Normal file
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// AudioSourceNoise.cpp
|
||||
// hifi
|
||||
//
|
||||
// Created by Craig Hansen-Sturm on 8/10/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <SharedUtil.h>
|
||||
#include "AudioRingBuffer.h"
|
||||
#include "AudioFormat.h"
|
||||
#include "AudioBuffer.h"
|
||||
#include "AudioSourceNoise.h"
|
||||
|
||||
template<>
|
||||
uint32_t AudioSourcePinkNoise::_randomSeed = 1974; // a truly random number
|
103
libraries/audio/src/AudioSourceNoise.h
Normal file
103
libraries/audio/src/AudioSourceNoise.h
Normal file
|
@ -0,0 +1,103 @@
|
|||
//
|
||||
// AudioSourceNoise.h
|
||||
// hifi
|
||||
//
|
||||
// Created by Craig Hansen-Sturm on 9/1/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
// Adapted from code by Phil Burk http://www.firstpr.com.au/dsp/pink-noise/
|
||||
//
|
||||
|
||||
#ifndef hifi_AudioSourceNoise_h
|
||||
#define hifi_AudioSourceNoise_h
|
||||
|
||||
template< const uint16_t N = 30>
|
||||
class AudioSourceNoise
|
||||
{
|
||||
static const uint16_t _randomRows = N;
|
||||
static const uint16_t _randomBits = 24;
|
||||
static const uint16_t _randomShift = (sizeof(int32_t) * 8) - _randomBits;
|
||||
|
||||
static uint32_t _randomSeed;
|
||||
|
||||
int32_t _rows[_randomRows];
|
||||
int32_t _runningSum; // used to optimize summing of generators.
|
||||
uint16_t _index; // incremented each sample.
|
||||
uint16_t _indexMask; // index wrapped by ANDing with this mask.
|
||||
float32_t _scale; // used to scale within range of -1.0 to +1.0
|
||||
|
||||
static uint32_t generateRandomNumber() {
|
||||
_randomSeed = (_randomSeed * 196314165) + 907633515;
|
||||
return _randomSeed >> _randomShift;
|
||||
}
|
||||
|
||||
public:
|
||||
AudioSourceNoise() {
|
||||
initialize();
|
||||
}
|
||||
|
||||
~AudioSourceNoise() {
|
||||
finalize();
|
||||
}
|
||||
|
||||
void initialize() {
|
||||
memset(_rows, 0, _randomRows * sizeof(int32_t));
|
||||
|
||||
_runningSum = 0;
|
||||
_index = 0;
|
||||
_indexMask = (1 << _randomRows) - 1;
|
||||
_scale = 1.0f / ((_randomRows + 1) * (1 << (_randomBits - 1)));
|
||||
}
|
||||
|
||||
void finalize() {
|
||||
}
|
||||
|
||||
void reset() {
|
||||
initialize();
|
||||
}
|
||||
|
||||
void setParameters(void) {
|
||||
}
|
||||
|
||||
void getParameters(void) {
|
||||
}
|
||||
|
||||
void render(AudioBufferFloat32& frameBuffer) {
|
||||
|
||||
uint32_t randomNumber;
|
||||
|
||||
float32_t** samples = frameBuffer.getFrameData();
|
||||
for (uint16_t i = 0; i < frameBuffer.getFrameCount(); ++i) {
|
||||
for (uint16_t j = 0; j < frameBuffer.getChannelCount(); ++j) {
|
||||
|
||||
_index = (_index + 1) & _indexMask; // increment and mask index.
|
||||
if (_index != 0) { // if index is zero, don't update any random values.
|
||||
|
||||
uint32_t numZeros = 0; // determine how many trailing zeros in _index
|
||||
uint32_t tmp = _index;
|
||||
while ((tmp & 1) == 0) {
|
||||
tmp >>= 1;
|
||||
numZeros++;
|
||||
}
|
||||
// replace the indexed _rows random value. subtract and add back to _runningSum instead
|
||||
// of adding all the random values together. only one value changes each time.
|
||||
_runningSum -= _rows[numZeros];
|
||||
randomNumber = generateRandomNumber();
|
||||
_runningSum += randomNumber;
|
||||
_rows[numZeros] = randomNumber;
|
||||
}
|
||||
|
||||
// add extra white noise value and scale between -1.0 and +1.0
|
||||
samples[j][i] = (_runningSum + generateRandomNumber()) * _scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
typedef AudioSourceNoise<> AudioSourcePinkNoise;
|
||||
|
||||
#endif // AudioSourceNoise_h
|
||||
|
20
libraries/audio/src/AudioSourceTone.cpp
Normal file
20
libraries/audio/src/AudioSourceTone.cpp
Normal file
|
@ -0,0 +1,20 @@
|
|||
//
|
||||
// AudioSourceTone.cpp
|
||||
// hifi
|
||||
//
|
||||
// Created by Craig Hansen-Sturm on 8/10/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <SharedUtil.h>
|
||||
#include "AudioRingBuffer.h"
|
||||
#include "AudioFormat.h"
|
||||
#include "AudioBuffer.h"
|
||||
#include "AudioSourceTone.h"
|
||||
|
||||
uint32_t AudioSourceTone::_frameOffset = 0;
|
72
libraries/audio/src/AudioSourceTone.h
Normal file
72
libraries/audio/src/AudioSourceTone.h
Normal file
|
@ -0,0 +1,72 @@
|
|||
//
|
||||
// AudioSourceTone.h
|
||||
// hifi
|
||||
//
|
||||
// Created by Craig Hansen-Sturm on 9/1/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_AudioSourceTone_h
|
||||
#define hifi_AudioSourceTone_h
|
||||
|
||||
class AudioSourceTone
|
||||
{
|
||||
static uint32_t _frameOffset;
|
||||
float32_t _frequency;
|
||||
float32_t _amplitude;
|
||||
float32_t _sampleRate;
|
||||
float32_t _omega;
|
||||
|
||||
public:
|
||||
AudioSourceTone() {
|
||||
initialize();
|
||||
}
|
||||
|
||||
~AudioSourceTone() {
|
||||
finalize();
|
||||
}
|
||||
|
||||
void initialize() {
|
||||
_frameOffset = 0;
|
||||
setParameters(SAMPLE_RATE, 220.0f, 0.9f);
|
||||
}
|
||||
|
||||
void finalize() {
|
||||
}
|
||||
|
||||
void reset() {
|
||||
_frameOffset = 0;
|
||||
}
|
||||
|
||||
void setParameters(const float32_t sampleRate, const float32_t frequency, const float32_t amplitude) {
|
||||
_sampleRate = std::max(sampleRate, 1.0f);
|
||||
_frequency = std::max(frequency, 1.0f);
|
||||
_amplitude = std::max(amplitude, 1.0f);
|
||||
_omega = _frequency / _sampleRate * TWO_PI;
|
||||
}
|
||||
|
||||
void getParameters(float32_t& sampleRate, float32_t& frequency, float32_t& amplitude) {
|
||||
sampleRate = _sampleRate;
|
||||
frequency = _frequency;
|
||||
amplitude = _amplitude;
|
||||
}
|
||||
|
||||
void render(AudioBufferFloat32& frameBuffer) {
|
||||
|
||||
// note: this is a placeholder implementation. final version will not include any transcendental ops in our render loop
|
||||
|
||||
float32_t** samples = frameBuffer.getFrameData();
|
||||
for (uint16_t i = 0; i < frameBuffer.getFrameCount(); ++i) {
|
||||
for (uint16_t j = 0; j < frameBuffer.getChannelCount(); ++j) {
|
||||
samples[j][i] = sinf((i + _frameOffset) * _omega);
|
||||
}
|
||||
}
|
||||
_frameOffset += frameBuffer.getFrameCount();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -16,6 +16,8 @@
|
|||
#include <AABox.h>
|
||||
|
||||
#include "InboundAudioStream.h"
|
||||
#include "AudioFormat.h"
|
||||
#include "AudioBuffer.h"
|
||||
#include "AudioFilter.h"
|
||||
#include "AudioFilterBank.h"
|
||||
|
||||
|
|
|
@ -35,7 +35,8 @@ using namespace std;
|
|||
|
||||
AvatarData::AvatarData() :
|
||||
_sessionUUID(),
|
||||
_handPosition(0,0,0),
|
||||
_position(0.0f),
|
||||
_handPosition(0.0f),
|
||||
_referential(NULL),
|
||||
_bodyYaw(-90.f),
|
||||
_bodyPitch(0.0f),
|
||||
|
@ -326,7 +327,7 @@ int AvatarData::parseDataAtOffset(const QByteArray& packet, int offset) {
|
|||
}
|
||||
return maxAvailableSize;
|
||||
}
|
||||
_position = position;
|
||||
setPosition(position);
|
||||
|
||||
// rotation (NOTE: This needs to become a quaternion to save two bytes)
|
||||
float yaw, pitch, roll;
|
||||
|
|
Loading…
Reference in a new issue