mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 12:28:02 +02:00
Merge remote-tracking branch 'origin'
This commit is contained in:
commit
ccd60fa07f
15 changed files with 269 additions and 107 deletions
15
README.md
15
README.md
|
@ -1,4 +1,17 @@
|
||||||
interface
|
interface
|
||||||
=========
|
=========
|
||||||
|
|
||||||
Test platform for various render and interface tests for next-gen VR system
|
Test platform for various render and interface tests for next-gen VR system.
|
||||||
|
|
||||||
|
CMake
|
||||||
|
=====
|
||||||
|
|
||||||
|
This project uses CMake to generate build files and project files for your platform.
|
||||||
|
|
||||||
|
Create a build directory in the root of your checkout and then run the CMake build from there. This will keep the rest of the directory clean, and makes the gitignore a little easier to handle (since we can just ignore build).
|
||||||
|
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake .. -GXCode
|
||||||
|
|
||||||
|
Those are the commands used on OS X to run CMake from the build folder and generate XCode project files.
|
BIN
interface/resources/images/green_eye.png
Normal file
BIN
interface/resources/images/green_eye.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 66 KiB |
|
@ -12,10 +12,11 @@
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <SharedUtil.h>
|
||||||
|
#include <StdDev.h>
|
||||||
|
#include <UDPSocket.h>
|
||||||
#include "Audio.h"
|
#include "Audio.h"
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
#include <SharedUtil.h>
|
|
||||||
#include "UDPSocket.h"
|
|
||||||
|
|
||||||
Oscilloscope * scope;
|
Oscilloscope * scope;
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,6 @@ public:
|
||||||
bool terminate();
|
bool terminate();
|
||||||
private:
|
private:
|
||||||
bool initialized;
|
bool initialized;
|
||||||
|
|
||||||
AudioData *audioData;
|
AudioData *audioData;
|
||||||
|
|
||||||
// protects constructor so that public init method is used
|
// protects constructor so that public init method is used
|
||||||
|
|
|
@ -27,6 +27,25 @@ Hand::Hand(glm::vec3 initcolor)
|
||||||
renderPointer = true;
|
renderPointer = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Hand::Hand(const Hand &otherHand) {
|
||||||
|
color = otherHand.color;
|
||||||
|
noise = otherHand.noise;
|
||||||
|
scale = otherHand.scale;
|
||||||
|
position = otherHand.position;
|
||||||
|
target = otherHand.target;
|
||||||
|
velocity = otherHand.color;
|
||||||
|
pitch = otherHand.pitch;
|
||||||
|
yaw = otherHand.yaw;
|
||||||
|
roll = otherHand.roll;
|
||||||
|
pitchRate = otherHand.pitchRate;
|
||||||
|
yawRate = otherHand.yawRate;
|
||||||
|
rollRate = otherHand.rollRate;
|
||||||
|
transmitterTimer = otherHand.transmitterTimer;
|
||||||
|
transmitterHz = otherHand.transmitterHz;
|
||||||
|
transmitterPackets = otherHand.transmitterPackets;
|
||||||
|
renderPointer = otherHand.renderPointer;
|
||||||
|
}
|
||||||
|
|
||||||
void Hand::reset()
|
void Hand::reset()
|
||||||
{
|
{
|
||||||
position.x = DEFAULT_X;
|
position.x = DEFAULT_X;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
class Hand {
|
class Hand {
|
||||||
public:
|
public:
|
||||||
Hand(glm::vec3 color);
|
Hand(glm::vec3 color);
|
||||||
|
Hand(const Hand &otherHand);
|
||||||
void simulate (float deltaTime);
|
void simulate (float deltaTime);
|
||||||
void render (int isMine);
|
void render (int isMine);
|
||||||
void reset ();
|
void reset ();
|
||||||
|
|
|
@ -8,10 +8,13 @@
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <cstring>
|
|
||||||
#include "Head.h"
|
#include "Head.h"
|
||||||
#include "Util.h"
|
#include <vector>
|
||||||
#include "SerialInterface.h"
|
#include <lodepng.h>
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
float skinColor[] = {1.0, 0.84, 0.66};
|
float skinColor[] = {1.0, 0.84, 0.66};
|
||||||
float browColor[] = {210.0/255.0, 105.0/255.0, 30.0/255.0};
|
float browColor[] = {210.0/255.0, 105.0/255.0, 30.0/255.0};
|
||||||
|
@ -28,6 +31,14 @@ float browThickness = 0.16;
|
||||||
|
|
||||||
const float DECAY = 0.1;
|
const float DECAY = 0.1;
|
||||||
|
|
||||||
|
char iris_texture_file[] = "interface.app/Contents/Resources/images/green_eye.png";
|
||||||
|
|
||||||
|
vector<unsigned char> iris_texture;
|
||||||
|
unsigned int iris_texture_width = 512;
|
||||||
|
unsigned int iris_texture_height = 256;
|
||||||
|
|
||||||
|
GLUquadric *sphere = gluNewQuadric();
|
||||||
|
|
||||||
Head::Head()
|
Head::Head()
|
||||||
{
|
{
|
||||||
position.x = position.y = position.z = 0;
|
position.x = position.y = position.z = 0;
|
||||||
|
@ -61,13 +72,66 @@ Head::Head()
|
||||||
averageLoudness = 0.0;
|
averageLoudness = 0.0;
|
||||||
lastLoudness = 0.0;
|
lastLoudness = 0.0;
|
||||||
browAudioLift = 0.0;
|
browAudioLift = 0.0;
|
||||||
|
noise = 0;
|
||||||
|
|
||||||
setNoise(0);
|
|
||||||
hand = new Hand(glm::vec3(skinColor[0], skinColor[1], skinColor[2]));
|
hand = new Hand(glm::vec3(skinColor[0], skinColor[1], skinColor[2]));
|
||||||
|
|
||||||
|
if (iris_texture.size() == 0) {
|
||||||
|
unsigned error = lodepng::decode(iris_texture, iris_texture_width, iris_texture_height, iris_texture_file);
|
||||||
|
if (error != 0) {
|
||||||
|
std::cout << "error " << error << ": " << lodepng_error_text(error) << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Head::Head(const Head &otherHead) {
|
||||||
|
position = otherHead.position;
|
||||||
|
PupilSize = otherHead.PupilSize;
|
||||||
|
interPupilDistance = otherHead.interPupilDistance;
|
||||||
|
interBrowDistance = otherHead.interBrowDistance;
|
||||||
|
NominalPupilSize = otherHead.NominalPupilSize;
|
||||||
|
Yaw = otherHead.Yaw;
|
||||||
|
EyebrowPitch[0] = otherHead.EyebrowPitch[0];
|
||||||
|
EyebrowPitch[1] = otherHead.EyebrowPitch[1];
|
||||||
|
EyebrowRoll[0] = otherHead.EyebrowRoll[0];
|
||||||
|
EyebrowRoll[1] = otherHead.EyebrowRoll[1];
|
||||||
|
MouthPitch = otherHead.MouthPitch;
|
||||||
|
MouthYaw = otherHead.MouthYaw;
|
||||||
|
MouthWidth = otherHead.MouthWidth;
|
||||||
|
MouthHeight = otherHead.MouthHeight;
|
||||||
|
EyeballPitch[0] = otherHead.EyeballPitch[0];
|
||||||
|
EyeballPitch[1] = otherHead.EyeballPitch[1];
|
||||||
|
EyeballScaleX = otherHead.EyeballScaleX;
|
||||||
|
EyeballScaleY = otherHead.EyeballScaleY;
|
||||||
|
EyeballScaleZ = otherHead.EyeballScaleZ;
|
||||||
|
EyeballYaw[0] = otherHead.EyeballYaw[0];
|
||||||
|
EyeballYaw[1] = otherHead.EyeballYaw[1];
|
||||||
|
PitchTarget = otherHead.PitchTarget;
|
||||||
|
YawTarget = otherHead.YawTarget;
|
||||||
|
NoiseEnvelope = otherHead.NoiseEnvelope;
|
||||||
|
PupilConverge = otherHead.PupilConverge;
|
||||||
|
leanForward = otherHead.leanForward;
|
||||||
|
leanSideways = otherHead.leanSideways;
|
||||||
|
eyeContact = otherHead.eyeContact;
|
||||||
|
eyeContactTarget = otherHead.eyeContactTarget;
|
||||||
|
scale = otherHead.scale;
|
||||||
|
renderYaw = otherHead.renderYaw;
|
||||||
|
renderPitch = otherHead.renderPitch;
|
||||||
|
audioAttack = otherHead.audioAttack;
|
||||||
|
loudness = otherHead.loudness;
|
||||||
|
averageLoudness = otherHead.averageLoudness;
|
||||||
|
lastLoudness = otherHead.lastLoudness;
|
||||||
|
browAudioLift = otherHead.browAudioLift;
|
||||||
|
noise = otherHead.noise;
|
||||||
|
|
||||||
|
Hand newHand = Hand(*otherHead.hand);
|
||||||
|
hand = &newHand;
|
||||||
}
|
}
|
||||||
|
|
||||||
Head::~Head() {
|
Head::~Head() {
|
||||||
// all data is primitive, do nothing
|
if (sphere) {
|
||||||
|
gluDeleteQuadric(sphere);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Head* Head::clone() const {
|
Head* Head::clone() const {
|
||||||
|
@ -341,14 +405,29 @@ void Head::render(int faceToFace, int isMine, float * myLocation)
|
||||||
glutSolidSphere(0.25, 30, 30);
|
glutSolidSphere(0.25, 30, 30);
|
||||||
}
|
}
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
|
||||||
// Right Pupil
|
// Right Pupil
|
||||||
|
if (!sphere) {
|
||||||
|
sphere = gluNewQuadric();
|
||||||
|
gluQuadricTexture(sphere, GL_TRUE);
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
gluQuadricOrientation(sphere, GLU_OUTSIDE);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, iris_texture_width, iris_texture_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &iris_texture[0]);
|
||||||
|
}
|
||||||
|
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
|
{
|
||||||
glRotatef(EyeballPitch[1], 1, 0, 0);
|
glRotatef(EyeballPitch[1], 1, 0, 0);
|
||||||
glRotatef(EyeballYaw[1] + PupilConverge, 0, 1, 0);
|
glRotatef(EyeballYaw[1] + PupilConverge, 0, 1, 0);
|
||||||
glTranslatef(0,0,.35);
|
glTranslatef(0,0,.35);
|
||||||
if (!eyeContact) glColor3f(0,0,0); else glColor3f(0.3,0.3,0.3);
|
glRotatef(-75,1,0,0);
|
||||||
//glRotatef(90,0,1,0);
|
glScalef(1.0, 0.4, 1.0);
|
||||||
glutSolidSphere(PupilSize, 15, 15);
|
|
||||||
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
gluSphere(sphere, PupilSize, 15, 15);
|
||||||
|
glDisable(GL_TEXTURE_2D);
|
||||||
|
}
|
||||||
|
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
// Left Eye
|
// Left Eye
|
||||||
|
@ -364,14 +443,19 @@ void Head::render(int faceToFace, int isMine, float * myLocation)
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
// Left Pupil
|
// Left Pupil
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
|
{
|
||||||
glRotatef(EyeballPitch[0], 1, 0, 0);
|
glRotatef(EyeballPitch[0], 1, 0, 0);
|
||||||
glRotatef(EyeballYaw[0] - PupilConverge, 0, 1, 0);
|
glRotatef(EyeballYaw[0] - PupilConverge, 0, 1, 0);
|
||||||
glTranslatef(0,0,.35);
|
glTranslatef(0, 0, .35);
|
||||||
if (!eyeContact) glColor3f(0,0,0); else glColor3f(0.3,0.3,0.3);
|
glRotatef(-75, 1, 0, 0);
|
||||||
//glRotatef(90,0,1,0);
|
glScalef(1.0, 0.4, 1.0);
|
||||||
glutSolidSphere(PupilSize, 15, 15);
|
|
||||||
glPopMatrix();
|
|
||||||
|
|
||||||
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
gluSphere(sphere, PupilSize, 15, 15);
|
||||||
|
glDisable(GL_TEXTURE_2D);
|
||||||
|
}
|
||||||
|
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
}
|
}
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
|
|
@ -24,6 +24,7 @@ class Head : public AgentData {
|
||||||
public:
|
public:
|
||||||
Head();
|
Head();
|
||||||
~Head();
|
~Head();
|
||||||
|
Head(const Head &otherHead);
|
||||||
Head* clone() const;
|
Head* clone() const;
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#include "Texture.h"
|
#include "Texture.h"
|
||||||
|
|
||||||
#include "InterfaceConfig.h"
|
#include "InterfaceConfig.h"
|
||||||
#include <LodePNG/lodepng.h>
|
#include <lodepng.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
|
|
|
@ -13,48 +13,6 @@
|
||||||
#include "world.h"
|
#include "world.h"
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
|
|
||||||
//
|
|
||||||
// Standard Deviation Object
|
|
||||||
//
|
|
||||||
|
|
||||||
const int MAX_STDEV_SAMPLES = 1000; // Don't add more than this number of samples.
|
|
||||||
|
|
||||||
StDev::StDev() {
|
|
||||||
data = new float[MAX_STDEV_SAMPLES];
|
|
||||||
sampleCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void StDev::reset() {
|
|
||||||
sampleCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void StDev::addValue(float v) {
|
|
||||||
data[sampleCount++] = v;
|
|
||||||
if (sampleCount == MAX_STDEV_SAMPLES) sampleCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
float StDev::getAverage() {
|
|
||||||
float average = 0;
|
|
||||||
for (int i = 0; i < sampleCount; i++) {
|
|
||||||
average += data[i];
|
|
||||||
}
|
|
||||||
if (sampleCount > 0)
|
|
||||||
return average/(float)sampleCount;
|
|
||||||
else return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
float StDev::getStDev() {
|
|
||||||
float average = getAverage();
|
|
||||||
float stdev = 0;
|
|
||||||
for (int i = 0; i < sampleCount; i++) {
|
|
||||||
stdev += powf(data[i] - average, 2);
|
|
||||||
}
|
|
||||||
if (sampleCount > 1)
|
|
||||||
return sqrt(stdev/(float)(sampleCount - 1.0));
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the azimuth angle in degrees between two points.
|
// Return the azimuth angle in degrees between two points.
|
||||||
float azimuth_to(glm::vec3 head_pos, glm::vec3 source_pos) {
|
float azimuth_to(glm::vec3 head_pos, glm::vec3 source_pos) {
|
||||||
return atan2(head_pos.x - source_pos.x, head_pos.z - source_pos.z) * 180 / PI;
|
return atan2(head_pos.x - source_pos.x, head_pos.z - source_pos.z) * 180 / PI;
|
||||||
|
|
|
@ -24,17 +24,5 @@ void drawvec3(int x, int y, float scale, float rotate, float thick, int mono, gl
|
||||||
float r=1.0, float g=1.0, float b=1.0);
|
float r=1.0, float g=1.0, float b=1.0);
|
||||||
double diffclock(timeval *clock1,timeval *clock2);
|
double diffclock(timeval *clock1,timeval *clock2);
|
||||||
|
|
||||||
class StDev {
|
|
||||||
public:
|
|
||||||
StDev();
|
|
||||||
void reset();
|
|
||||||
void addValue(float v);
|
|
||||||
float getAverage();
|
|
||||||
float getStDev();
|
|
||||||
int getSamples() {return sampleCount;};
|
|
||||||
private:
|
|
||||||
float * data;
|
|
||||||
int sampleCount;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -916,30 +916,6 @@ int main(int argc, char** argv)
|
||||||
}
|
}
|
||||||
} else printf("Using static domainserver IP: %s\n", DOMAIN_IP);
|
} else printf("Using static domainserver IP: %s\n", DOMAIN_IP);
|
||||||
|
|
||||||
printf("Testing stats math... ");
|
|
||||||
StDev stdevtest;
|
|
||||||
stdevtest.reset();
|
|
||||||
stdevtest.addValue(1345);
|
|
||||||
stdevtest.addValue(1301);
|
|
||||||
stdevtest.addValue(1368);
|
|
||||||
stdevtest.addValue(1322);
|
|
||||||
stdevtest.addValue(1310);
|
|
||||||
stdevtest.addValue(1370);
|
|
||||||
stdevtest.addValue(1318);
|
|
||||||
stdevtest.addValue(1350);
|
|
||||||
stdevtest.addValue(1303);
|
|
||||||
stdevtest.addValue(1299);
|
|
||||||
|
|
||||||
if (stdevtest.getSamples() != 10)
|
|
||||||
printf("Samples=FAIL ");
|
|
||||||
|
|
||||||
if (floor(stdevtest.getAverage()*100.0) != 132859.0)
|
|
||||||
printf("Average=FAIL ");
|
|
||||||
|
|
||||||
if (floor(stdevtest.getStDev()*100.0) != 2746.0)
|
|
||||||
printf("Stdev=FAIL ");
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
// the callback for our instance of AgentList is attachNewHeadToAgent
|
// the callback for our instance of AgentList is attachNewHeadToAgent
|
||||||
agentList.linkedDataCreateCallback = &attachNewHeadToAgent;
|
agentList.linkedDataCreateCallback = &attachNewHeadToAgent;
|
||||||
agentList.audioMixerSocketUpdate = &audioMixerUpdate;
|
agentList.audioMixerSocketUpdate = &audioMixerUpdate;
|
||||||
|
|
|
@ -12,9 +12,10 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include "AudioRingBuffer.h"
|
|
||||||
#include <AgentList.h>
|
#include <AgentList.h>
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
|
#include <StdDev.h>
|
||||||
|
#include "AudioRingBuffer.h"
|
||||||
|
|
||||||
const unsigned short MIXER_LISTEN_PORT = 55443;
|
const unsigned short MIXER_LISTEN_PORT = 55443;
|
||||||
|
|
||||||
|
@ -39,11 +40,14 @@ const int PHASE_DELAY_AT_90 = 20;
|
||||||
|
|
||||||
const int AGENT_LOOPBACK_MODIFIER = 307;
|
const int AGENT_LOOPBACK_MODIFIER = 307;
|
||||||
|
|
||||||
|
const int LOOPBACK_SANITY_CHECK = 0;
|
||||||
|
|
||||||
char DOMAIN_HOSTNAME[] = "highfidelity.below92.com";
|
char DOMAIN_HOSTNAME[] = "highfidelity.below92.com";
|
||||||
char DOMAIN_IP[100] = ""; // IP Address will be re-set by lookup on startup
|
char DOMAIN_IP[100] = ""; // IP Address will be re-set by lookup on startup
|
||||||
const int DOMAINSERVER_PORT = 40102;
|
const int DOMAINSERVER_PORT = 40102;
|
||||||
|
|
||||||
AgentList agentList(MIXER_LISTEN_PORT);
|
AgentList agentList(MIXER_LISTEN_PORT);
|
||||||
|
StDev stdev;
|
||||||
|
|
||||||
void plateauAdditionOfSamples(int16_t &mixSample, int16_t sampleToAdd) {
|
void plateauAdditionOfSamples(int16_t &mixSample, int16_t sampleToAdd) {
|
||||||
long sumSample = sampleToAdd + mixSample;
|
long sumSample = sampleToAdd + mixSample;
|
||||||
|
@ -58,17 +62,13 @@ void *sendBuffer(void *args)
|
||||||
{
|
{
|
||||||
int sentBytes;
|
int sentBytes;
|
||||||
int nextFrame = 0;
|
int nextFrame = 0;
|
||||||
timeval startTime, lastSend;
|
timeval startTime;
|
||||||
|
|
||||||
gettimeofday(&startTime, NULL);
|
gettimeofday(&startTime, NULL);
|
||||||
gettimeofday(&lastSend, NULL);
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
sentBytes = 0;
|
sentBytes = 0;
|
||||||
|
|
||||||
printf("Last send was %f ms ago\n", (usecTimestampNow() - usecTimestamp(&lastSend)) / 1000);
|
|
||||||
gettimeofday(&lastSend, NULL);
|
|
||||||
|
|
||||||
for (int i = 0; i < agentList.getAgents().size(); i++) {
|
for (int i = 0; i < agentList.getAgents().size(); i++) {
|
||||||
AudioRingBuffer *agentBuffer = (AudioRingBuffer *) agentList.getAgents()[i].getLinkedData();
|
AudioRingBuffer *agentBuffer = (AudioRingBuffer *) agentList.getAgents()[i].getLinkedData();
|
||||||
|
|
||||||
|
@ -81,6 +81,22 @@ void *sendBuffer(void *args)
|
||||||
printf("Buffer %d starved.\n", i);
|
printf("Buffer %d starved.\n", i);
|
||||||
agentBuffer->setStarted(false);
|
agentBuffer->setStarted(false);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
// check if we have more than we need to play out
|
||||||
|
int thresholdFrames = ceilf((BUFFER_LENGTH_SAMPLES_PER_CHANNEL + JITTER_BUFFER_SAMPLES) / (float)BUFFER_LENGTH_SAMPLES_PER_CHANNEL);
|
||||||
|
int thresholdSamples = thresholdFrames * BUFFER_LENGTH_SAMPLES_PER_CHANNEL;
|
||||||
|
|
||||||
|
if (agentBuffer->diffLastWriteNextOutput() > thresholdSamples) {
|
||||||
|
// we need to push the next output forwards
|
||||||
|
int samplesToPush = agentBuffer->diffLastWriteNextOutput() - thresholdSamples;
|
||||||
|
|
||||||
|
if (agentBuffer->getNextOutput() + samplesToPush > agentBuffer->getBuffer()) {
|
||||||
|
agentBuffer->setNextOutput(agentBuffer->getBuffer() + (samplesToPush - (agentBuffer->getBuffer() + RING_BUFFER_SAMPLES - agentBuffer->getNextOutput())));
|
||||||
|
} else {
|
||||||
|
agentBuffer->setNextOutput(agentBuffer->getNextOutput() + samplesToPush);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// good buffer, add this to the mix
|
// good buffer, add this to the mix
|
||||||
agentBuffer->setStarted(true);
|
agentBuffer->setStarted(true);
|
||||||
agentBuffer->setAddedToMix(true);
|
agentBuffer->setAddedToMix(true);
|
||||||
|
@ -283,14 +299,45 @@ int main(int argc, const char * argv[])
|
||||||
pthread_t sendBufferThread;
|
pthread_t sendBufferThread;
|
||||||
pthread_create(&sendBufferThread, NULL, sendBuffer, NULL);
|
pthread_create(&sendBufferThread, NULL, sendBuffer, NULL);
|
||||||
|
|
||||||
|
int16_t *loopbackAudioPacket;
|
||||||
|
if (LOOPBACK_SANITY_CHECK) {
|
||||||
|
loopbackAudioPacket = new int16_t[1024];
|
||||||
|
}
|
||||||
|
|
||||||
sockaddr *agentAddress = new sockaddr;
|
sockaddr *agentAddress = new sockaddr;
|
||||||
|
timeval lastReceive;
|
||||||
|
gettimeofday(&lastReceive, NULL);
|
||||||
|
|
||||||
|
bool firstSample = true;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if(agentList.getAgentSocket().receive(agentAddress, packetData, &receivedBytes)) {
|
if(agentList.getAgentSocket().receive(agentAddress, packetData, &receivedBytes)) {
|
||||||
if (packetData[0] == 'I') {
|
if (packetData[0] == 'I') {
|
||||||
|
|
||||||
|
// Compute and report standard deviation for jitter calculation
|
||||||
|
if (firstSample) {
|
||||||
|
stdev.reset();
|
||||||
|
firstSample = false;
|
||||||
|
} else {
|
||||||
|
double tDiff = (usecTimestampNow() - usecTimestamp(&lastReceive)) / 1000;
|
||||||
|
stdev.addValue(tDiff);
|
||||||
|
|
||||||
|
if (stdev.getSamples() > 500) {
|
||||||
|
printf("Avg: %4.2f, Stdev: %4.2f\n", stdev.getAverage(), stdev.getStDev());
|
||||||
|
stdev.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gettimeofday(&lastReceive, NULL);
|
||||||
|
|
||||||
// add or update the existing interface agent
|
// add or update the existing interface agent
|
||||||
agentList.addOrUpdateAgent(agentAddress, agentAddress, packetData[0]);
|
if (!LOOPBACK_SANITY_CHECK) {
|
||||||
agentList.updateAgentWithData(agentAddress, (void *)packetData, receivedBytes);
|
agentList.addOrUpdateAgent(agentAddress, agentAddress, packetData[0]);
|
||||||
|
agentList.updateAgentWithData(agentAddress, (void *)packetData, receivedBytes);
|
||||||
|
} else {
|
||||||
|
memcpy(loopbackAudioPacket, packetData + 1 + (sizeof(float) * 4), 1024);
|
||||||
|
agentList.getAgentSocket().send(agentAddress, loopbackAudioPacket, 1024);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
48
shared/src/StdDev.cpp
Normal file
48
shared/src/StdDev.cpp
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
//
|
||||||
|
// StdDev.cpp
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Philip Rosedale on 3/12/13.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "StdDev.h"
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
const int MAX_STDEV_SAMPLES = 1000; // Don't add more than this number of samples.
|
||||||
|
|
||||||
|
StDev::StDev() {
|
||||||
|
data = new float[MAX_STDEV_SAMPLES];
|
||||||
|
sampleCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StDev::reset() {
|
||||||
|
sampleCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StDev::addValue(float v) {
|
||||||
|
data[sampleCount++] = v;
|
||||||
|
if (sampleCount == MAX_STDEV_SAMPLES) sampleCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float StDev::getAverage() {
|
||||||
|
float average = 0;
|
||||||
|
for (int i = 0; i < sampleCount; i++) {
|
||||||
|
average += data[i];
|
||||||
|
}
|
||||||
|
if (sampleCount > 0)
|
||||||
|
return average/(float)sampleCount;
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float StDev::getStDev() {
|
||||||
|
float average = getAverage();
|
||||||
|
float stdev = 0;
|
||||||
|
for (int i = 0; i < sampleCount; i++) {
|
||||||
|
stdev += powf(data[i] - average, 2);
|
||||||
|
}
|
||||||
|
if (sampleCount > 1)
|
||||||
|
return sqrt(stdev/(float)(sampleCount - 1.0));
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
27
shared/src/StdDev.h
Normal file
27
shared/src/StdDev.h
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
//
|
||||||
|
// StdDev.h
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Philip Rosedale on 3/12/13.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __hifi__StdDev__
|
||||||
|
#define __hifi__StdDev__
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
class StDev {
|
||||||
|
public:
|
||||||
|
StDev();
|
||||||
|
void reset();
|
||||||
|
void addValue(float v);
|
||||||
|
float getAverage();
|
||||||
|
float getStDev();
|
||||||
|
int getSamples() {return sampleCount;};
|
||||||
|
private:
|
||||||
|
float * data;
|
||||||
|
int sampleCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* defined(__hifi__StdDev__) */
|
Loading…
Reference in a new issue