mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-25 16:55:07 +02:00
transmitter full movement, and audio jitter buffer tweaks/debugging data
This commit is contained in:
parent
79f39483d0
commit
674bd8d798
6 changed files with 88 additions and 31 deletions
|
@ -14,10 +14,13 @@
|
|||
#include <cstring>
|
||||
#include "Audio.h"
|
||||
#include "Util.h"
|
||||
#include <SharedUtil.h>
|
||||
#include "UDPSocket.h"
|
||||
|
||||
Oscilloscope * scope;
|
||||
|
||||
const int NUM_AUDIO_CHANNELS = 2;
|
||||
|
||||
const int PACKET_LENGTH_BYTES = 1024;
|
||||
const int PACKET_LENGTH_BYTES_PER_CHANNEL = PACKET_LENGTH_BYTES / 2;
|
||||
const int PACKET_LENGTH_SAMPLES = PACKET_LENGTH_BYTES / sizeof(int16_t);
|
||||
|
@ -33,8 +36,11 @@ const int PHASE_DELAY_AT_90 = 20;
|
|||
const float AMPLITUDE_RATIO_AT_90 = 0.5;
|
||||
|
||||
const int SAMPLE_RATE = 22050;
|
||||
const float JITTER_BUFFER_LENGTH_MSECS = 30.0;
|
||||
const short JITTER_BUFFER_SAMPLES = JITTER_BUFFER_LENGTH_MSECS * (SAMPLE_RATE / 1000.0);
|
||||
const float JITTER_BUFFER_LENGTH_MSECS = 4;
|
||||
const short JITTER_BUFFER_SAMPLES = JITTER_BUFFER_LENGTH_MSECS *
|
||||
NUM_AUDIO_CHANNELS * (SAMPLE_RATE / 1000.0);
|
||||
|
||||
const float AUDIO_CALLBACK_MSECS = (float)BUFFER_LENGTH_SAMPLES / (float)SAMPLE_RATE * 1000.0;
|
||||
|
||||
const int FLANGE_EFFECT_THRESHOLD = 200;
|
||||
const float FLANGE_RATE = 4;
|
||||
|
@ -49,7 +55,10 @@ StDev stdev;
|
|||
bool stopAudioReceiveThread = false;
|
||||
int samplesLeftForFlange = 0;
|
||||
|
||||
#define LOG_SAMPLE_DELAY 1
|
||||
timeval firstPlaybackTimer;
|
||||
int packetsReceivedThisPlayback = 0;
|
||||
|
||||
#define LOG_SAMPLE_DELAY 0
|
||||
|
||||
std::ofstream logFile;
|
||||
|
||||
|
@ -85,6 +94,8 @@ int audioCallback (const void *inputBuffer,
|
|||
int16_t *inputLeft = ((int16_t **) inputBuffer)[0];
|
||||
// int16_t *inputRight = ((int16_t **) inputBuffer)[1];
|
||||
|
||||
//printf("Audio callback at %6.0f\n", usecTimestampNow()/1000);
|
||||
|
||||
if (inputLeft != NULL) {
|
||||
|
||||
if (data->mixerAddress != 0) {
|
||||
|
@ -163,16 +174,23 @@ int audioCallback (const void *inputBuffer,
|
|||
|
||||
if (ringBuffer->getEndOfLastWrite() != NULL) {
|
||||
|
||||
if (!ringBuffer->isStarted() && ringBuffer->diffLastWriteNextOutput() <= PACKET_LENGTH_SAMPLES + JITTER_BUFFER_SAMPLES) {
|
||||
printf("Held back\n");
|
||||
if (!ringBuffer->isStarted() && ringBuffer->diffLastWriteNextOutput() < PACKET_LENGTH_SAMPLES + JITTER_BUFFER_SAMPLES) {
|
||||
printf("Held back, buffer has %d of %d samples required.\n", ringBuffer->diffLastWriteNextOutput(), PACKET_LENGTH_SAMPLES + JITTER_BUFFER_SAMPLES);
|
||||
} else if (ringBuffer->diffLastWriteNextOutput() < PACKET_LENGTH_SAMPLES) {
|
||||
ringBuffer->setStarted(false);
|
||||
|
||||
starve_counter++;
|
||||
packetsReceivedThisPlayback = 0;
|
||||
|
||||
printf("Starved #%d\n", starve_counter);
|
||||
data->wasStarved = 10; // Frames to render the indication that the system was starved.
|
||||
} else {
|
||||
ringBuffer->setStarted(true);
|
||||
if (!ringBuffer->isStarted()) {
|
||||
ringBuffer->setStarted(true);
|
||||
printf("starting playback %3.1f msecs delayed, \n", (usecTimestampNow() - usecTimestamp(&firstPlaybackTimer))/1000.0);
|
||||
} else {
|
||||
//printf("pushing buffer\n");
|
||||
}
|
||||
// play whatever we have in the audio buffer
|
||||
|
||||
// if we haven't fired off the flange effect, check if we should
|
||||
|
@ -265,7 +283,7 @@ void *receiveAudioViaUDP(void *args) {
|
|||
delete[] directory;
|
||||
delete[] filename;
|
||||
}
|
||||
|
||||
|
||||
while (!stopAudioReceiveThread) {
|
||||
if (sharedAudioData->audioSocket->receive((void *)receivedData, &receivedBytes)) {
|
||||
bool firstSample = (currentReceiveTime.tv_sec == 0);
|
||||
|
@ -295,6 +313,17 @@ void *receiveAudioViaUDP(void *args) {
|
|||
}
|
||||
|
||||
AudioRingBuffer *ringBuffer = sharedAudioData->ringBuffer;
|
||||
|
||||
|
||||
if (!ringBuffer->isStarted()) {
|
||||
printf("Audio packet %d received at %6.0f\n", ++packetsReceivedThisPlayback, usecTimestampNow()/1000);
|
||||
}
|
||||
else {
|
||||
//printf("Audio packet received at %6.0f\n", usecTimestampNow()/1000);
|
||||
}
|
||||
|
||||
if (packetsReceivedThisPlayback == 1) gettimeofday(&firstPlaybackTimer, NULL);
|
||||
|
||||
ringBuffer->parseData(receivedData, PACKET_LENGTH_BYTES);
|
||||
|
||||
if (LOG_SAMPLE_DELAY) {
|
||||
|
@ -407,10 +436,14 @@ void Audio::render(int screenWidth, int screenHeight)
|
|||
timeval currentTime;
|
||||
gettimeofday(¤tTime, NULL);
|
||||
float timeLeftInCurrentBuffer = 0;
|
||||
if (audioData->lastCallback.tv_usec > 0) timeLeftInCurrentBuffer = diffclock(&audioData->lastCallback, ¤tTime)/(1000.0*(float)PACKET_LENGTH_SAMPLES/(float)SAMPLE_RATE) * frameWidth;
|
||||
if (audioData->lastCallback.tv_usec > 0) {
|
||||
timeLeftInCurrentBuffer = AUDIO_CALLBACK_MSECS - diffclock(&audioData->lastCallback, ¤tTime);
|
||||
}
|
||||
|
||||
// /(1000.0*(float)BUFFER_LENGTH_SAMPLES/(float)SAMPLE_RATE) * frameWidth
|
||||
|
||||
if (audioData->ringBuffer->getEndOfLastWrite() != NULL)
|
||||
remainingBuffer = audioData->ringBuffer->diffLastWriteNextOutput() / PACKET_LENGTH_SAMPLES * frameWidth;
|
||||
remainingBuffer = audioData->ringBuffer->diffLastWriteNextOutput() / PACKET_LENGTH_SAMPLES * AUDIO_CALLBACK_MSECS;
|
||||
|
||||
if (audioData->wasStarved == 0) glColor3f(0, 1, 0);
|
||||
else {
|
||||
|
@ -420,8 +453,8 @@ void Audio::render(int screenWidth, int screenHeight)
|
|||
|
||||
glBegin(GL_QUADS);
|
||||
glVertex2f(startX, topY + 5);
|
||||
glVertex2f(startX + remainingBuffer + timeLeftInCurrentBuffer, topY + 5);
|
||||
glVertex2f(startX + remainingBuffer + timeLeftInCurrentBuffer, bottomY - 5);
|
||||
glVertex2f(startX + (remainingBuffer + timeLeftInCurrentBuffer)/AUDIO_CALLBACK_MSECS*frameWidth, topY + 5);
|
||||
glVertex2f(startX + (remainingBuffer + timeLeftInCurrentBuffer)/AUDIO_CALLBACK_MSECS*frameWidth, bottomY - 5);
|
||||
glVertex2f(startX, bottomY - 5);
|
||||
glEnd();
|
||||
|
||||
|
@ -431,15 +464,16 @@ void Audio::render(int screenWidth, int screenHeight)
|
|||
// Show a yellow bar with the averaged msecs latency you are hearing (from time of packet receipt)
|
||||
glColor3f(1,1,0);
|
||||
glBegin(GL_QUADS);
|
||||
glVertex2f(startX + audioData->averagedLatency - 2, topY - 2);
|
||||
glVertex2f(startX + audioData->averagedLatency + 2, topY - 2);
|
||||
glVertex2f(startX + audioData->averagedLatency + 2, bottomY + 2);
|
||||
glVertex2f(startX + audioData->averagedLatency - 2, bottomY + 2);
|
||||
glVertex2f(startX + audioData->averagedLatency/AUDIO_CALLBACK_MSECS*frameWidth - 2, topY - 2);
|
||||
glVertex2f(startX + audioData->averagedLatency/AUDIO_CALLBACK_MSECS*frameWidth + 2, topY - 2);
|
||||
glVertex2f(startX + audioData->averagedLatency/AUDIO_CALLBACK_MSECS*frameWidth + 2, bottomY + 2);
|
||||
glVertex2f(startX + audioData->averagedLatency/AUDIO_CALLBACK_MSECS*frameWidth - 2, bottomY + 2);
|
||||
glEnd();
|
||||
|
||||
char out[20];
|
||||
sprintf(out, "%3.0f\n", audioData->averagedLatency/(float)frameWidth*(1000.0*(float)PACKET_LENGTH_SAMPLES/(float)SAMPLE_RATE));
|
||||
drawtext(startX + audioData->averagedLatency - 10, topY-10, 0.08, 0, 1, 0, out, 1,1,0);
|
||||
char out[40];
|
||||
sprintf(out, "%3.0f\n", audioData->averagedLatency);
|
||||
drawtext(startX + audioData->averagedLatency/AUDIO_CALLBACK_MSECS*frameWidth - 10, topY-10, 0.08, 0, 1, 0, out, 1,1,0);
|
||||
//drawtext(startX + 0, topY-10, 0.08, 0, 1, 0, out, 1,1,0);
|
||||
|
||||
// Show a Cyan bar with the most recently measured jitter stdev
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ void Hand::reset()
|
|||
transmitterHz = DEFAULT_TRANSMITTER_HZ;
|
||||
}
|
||||
|
||||
void Hand::render()
|
||||
void Hand::render(int isMine)
|
||||
{
|
||||
const float POINTER_LENGTH = 20.0;
|
||||
glPushMatrix();
|
||||
|
@ -122,13 +122,13 @@ void Hand::processTransmitterData(char *packetData, int numBytes) {
|
|||
const float ANG_VEL_THRESHOLD = 0.0;
|
||||
float angVelScale = ANG_VEL_SENSITIVITY*(1.0/getTransmitterHz());
|
||||
//addAngularVelocity(gyrX*angVelScale,gyrZ*angVelScale,-gyrY*angVelScale);
|
||||
addAngularVelocity(0,
|
||||
addAngularVelocity(fabs(gyrX*angVelScale)>ANG_VEL_THRESHOLD?gyrX*angVelScale:0,
|
||||
fabs(gyrZ*angVelScale)>ANG_VEL_THRESHOLD?gyrZ*angVelScale:0,
|
||||
0);
|
||||
fabs(-gyrY*angVelScale)>ANG_VEL_THRESHOLD?-gyrY*angVelScale:0);
|
||||
|
||||
// Add linear forces to the hand
|
||||
//const float LINEAR_VEL_SENSITIVITY = 50.0;
|
||||
const float LINEAR_VEL_SENSITIVITY = 0.0;
|
||||
const float LINEAR_VEL_SENSITIVITY = 5.0;
|
||||
float linVelScale = LINEAR_VEL_SENSITIVITY*(1.0/getTransmitterHz());
|
||||
glm::vec3 linVel(linX*linVelScale, linZ*linVelScale, -linY*linVelScale);
|
||||
addVelocity(linVel);
|
||||
|
@ -184,14 +184,37 @@ void Hand::simulate(float deltaTime)
|
|||
-rollRate*ANGULAR_DAMPING_COEFFICIENT*deltaTime);
|
||||
}
|
||||
|
||||
// The absolute threshold method
|
||||
// The absolute limits method (no springs)
|
||||
if (1) {
|
||||
// Limit rotation
|
||||
const float YAW_LIMIT = 20;
|
||||
const float PITCH_LIMIT = 20;
|
||||
|
||||
if (yaw > YAW_LIMIT) { yaw = YAW_LIMIT; yawRate = 0.0; }
|
||||
if (yaw < -YAW_LIMIT) { yaw = -YAW_LIMIT; yawRate = 0.0; }
|
||||
if (pitch > PITCH_LIMIT) { pitch = PITCH_LIMIT; pitchRate = 0.0; }
|
||||
if (pitch < -PITCH_LIMIT) { pitch = -PITCH_LIMIT; pitchRate = 0.0; }
|
||||
|
||||
// Damp Rotation Rates
|
||||
yawRate *= 0.99;
|
||||
pitchRate *= 0.99;
|
||||
rollRate *= 0.99;
|
||||
|
||||
// Limit position
|
||||
const float X_LIMIT = 1.0;
|
||||
const float Y_LIMIT = 1.0;
|
||||
const float Z_LIMIT = 1.0;
|
||||
|
||||
if (position.x > DEFAULT_X + X_LIMIT) { position.x = DEFAULT_X + X_LIMIT; velocity.x = 0; }
|
||||
if (position.x < DEFAULT_X - X_LIMIT) { position.x = DEFAULT_X - X_LIMIT; velocity.x = 0; }
|
||||
if (position.y > DEFAULT_Y + Y_LIMIT) { position.y = DEFAULT_Y + Y_LIMIT; velocity.y = 0; }
|
||||
if (position.y < DEFAULT_Y - Y_LIMIT) { position.y = DEFAULT_Y - Y_LIMIT; velocity.y = 0; }
|
||||
if (position.z > DEFAULT_Z + Z_LIMIT) { position.z = DEFAULT_Z + Z_LIMIT; velocity.z = 0; }
|
||||
if (position.z < DEFAULT_Z - Z_LIMIT) { position.z = DEFAULT_Z - Z_LIMIT; velocity.z = 0; }
|
||||
|
||||
// Damp Velocity
|
||||
velocity *= 0.99;
|
||||
|
||||
// Damp Yaw Rate
|
||||
yawRate *= 0.99;
|
||||
}
|
||||
|
||||
}
|
|
@ -20,7 +20,7 @@ class Hand {
|
|||
public:
|
||||
Hand(glm::vec3 color);
|
||||
void simulate (float deltaTime);
|
||||
void render ();
|
||||
void render (int isMine);
|
||||
void reset ();
|
||||
void setNoise (float mag) { noise = mag; };
|
||||
void addVelocity (glm::vec3 v) { velocity += v; };
|
||||
|
|
|
@ -239,7 +239,7 @@ void Head::simulate(float deltaTime)
|
|||
|
||||
}
|
||||
|
||||
void Head::render(int faceToFace, float * myLocation)
|
||||
void Head::render(int faceToFace, int isMine, float * myLocation)
|
||||
{
|
||||
int side = 0;
|
||||
|
||||
|
@ -255,7 +255,7 @@ void Head::render(int faceToFace, float * myLocation)
|
|||
|
||||
glRotatef(Yaw, 0, 1, 0);
|
||||
|
||||
hand->render();
|
||||
hand->render(1);
|
||||
|
||||
// Don't render a head if it is really close to your location, because that is your own head!
|
||||
if ((distanceToCamera > 1.0) || faceToFace) {
|
||||
|
|
|
@ -47,7 +47,7 @@ class Head : public AgentData {
|
|||
float getRoll() {return Roll;}
|
||||
float getYaw() {return Yaw;}
|
||||
|
||||
void render(int faceToFace, float * myLocation);
|
||||
void render(int faceToFace, int isMine, float * myLocation);
|
||||
void simulate(float);
|
||||
|
||||
// Send and receive network data
|
||||
|
|
|
@ -588,7 +588,7 @@ void display(void)
|
|||
glPushMatrix();
|
||||
glm::vec3 pos = agentHead->getPos();
|
||||
glTranslatef(-pos.x, -pos.y, -pos.z);
|
||||
agentHead->render(0, &location[0]);
|
||||
agentHead->render(0, 0, &location[0]);
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
@ -602,7 +602,7 @@ void display(void)
|
|||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glTranslatef(0.f, 0.f, -7.f);
|
||||
myHead.render(display_head, &location[0]);
|
||||
myHead.render(display_head, 1, &location[0]);
|
||||
glPopMatrix();
|
||||
|
||||
//glm::vec3 test(0.5, 0.5, 0.5);
|
||||
|
|
Loading…
Reference in a new issue