Merge remote-tracking branch 'origin'

This commit is contained in:
Philip Rosedale 2013-02-26 17:34:26 -08:00
commit 27cc3a8ee5
16 changed files with 282 additions and 278 deletions

View file

@ -32,8 +32,6 @@
#include "SharedUtil.h"
const int DOMAIN_LISTEN_PORT = 40102;
const int MAX_PACKET_SIZE = 1500;
unsigned char packetData[MAX_PACKET_SIZE];
const int LOGOFF_CHECK_INTERVAL = 5000;
@ -70,10 +68,10 @@ int main(int argc, const char * argv[])
agentList.startSilentAgentRemovalThread();
std::map<char, Agent *> newestSoloAgents;
while (true) {
if (agentList.getAgentSocket().receive((sockaddr *)&agentPublicAddress, packetData, &receivedBytes)) {
std::map<char, Agent *> newestSoloAgents;
agentType = packetData[0];
unpackSocket(&packetData[1], (sockaddr *)&agentLocalAddress);

View file

@ -18,18 +18,12 @@
Oscilloscope * scope;
const short BUFFER_LENGTH_BYTES = 1024;
const short BUFFER_LENGTH_SAMPLES = BUFFER_LENGTH_BYTES / sizeof(int16_t);
const short PACKET_LENGTH_BYTES = 1024;
const short PACKET_LENGTH_SAMPLES = PACKET_LENGTH_BYTES / sizeof(int16_t);
const int PHASE_DELAY_AT_90 = 20;
const float AMPLITUDE_RATIO_AT_90 = 0.5;
const short RING_BUFFER_FRAMES = 10;
const short RING_BUFFER_SIZE_SAMPLES = RING_BUFFER_FRAMES * BUFFER_LENGTH_SAMPLES;
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);
@ -90,7 +84,23 @@ int audioCallback (const void *inputBuffer,
audioMixerSocket.sin_family = AF_INET;
audioMixerSocket.sin_addr.s_addr = data->mixerAddress;
audioMixerSocket.sin_port = data->mixerPort;
data->audioSocket->send((sockaddr *)&audioMixerSocket, (void *)inputLeft, BUFFER_LENGTH_BYTES);
int leadingBytes = 1 + (sizeof(float) * 3);
// we need the amount of bytes in the buffer + 1 for type + 12 for 3 floats for position
unsigned char dataPacket[BUFFER_LENGTH_BYTES + leadingBytes];
dataPacket[0] = 'I';
// memcpy the three float positions
for (int p = 0; p < 3; p++) {
memcpy(dataPacket + 1 + (p * sizeof(float)), &data->sourcePosition[p], sizeof(float));
}
// copy the audio data to the last 1024 bytes of the data packet
memcpy(dataPacket + leadingBytes, inputLeft, BUFFER_LENGTH_BYTES);
data->audioSocket->send((sockaddr *)&audioMixerSocket, dataPacket, BUFFER_LENGTH_BYTES + leadingBytes);
}
//
@ -134,27 +144,27 @@ int audioCallback (const void *inputBuffer,
// if we've been reset, and there isn't any new packets yet
// just play some silence
if (ringBuffer->endOfLastWrite != NULL) {
if (ringBuffer->getEndOfLastWrite() != NULL) {
if (!ringBuffer->started && ringBuffer->diffLastWriteNextOutput() <= PACKET_LENGTH_SAMPLES + JITTER_BUFFER_SAMPLES) {
if (!ringBuffer->isStarted() && ringBuffer->diffLastWriteNextOutput() <= PACKET_LENGTH_SAMPLES + JITTER_BUFFER_SAMPLES) {
printf("Held back\n");
} else if (ringBuffer->diffLastWriteNextOutput() < PACKET_LENGTH_SAMPLES) {
ringBuffer->started = false;
ringBuffer->setStarted(false);
starve_counter++;
printf("Starved #%d\n", starve_counter);
data->wasStarved = 10; // Frames to render the indication that the system was starved.
} else {
ringBuffer->started = true;
ringBuffer->setStarted(true);
// play whatever we have in the audio buffer
// no sample overlap, either a direct copy of the audio data, or a copy with some appended silence
memcpy(queueBuffer, ringBuffer->nextOutput, BUFFER_LENGTH_BYTES);
memcpy(queueBuffer, ringBuffer->getNextOutput(), BUFFER_LENGTH_BYTES);
ringBuffer->nextOutput += BUFFER_LENGTH_SAMPLES;
ringBuffer->setNextOutput(ringBuffer->getNextOutput() + BUFFER_LENGTH_SAMPLES);
if (ringBuffer->nextOutput == ringBuffer->buffer + RING_BUFFER_SIZE_SAMPLES) {
ringBuffer->nextOutput = ringBuffer->buffer;
if (ringBuffer->getNextOutput() == ringBuffer->getBuffer() + RING_BUFFER_SAMPLES) {
ringBuffer->setNextOutput(ringBuffer->getBuffer());
}
}
}
@ -204,7 +214,6 @@ void *receiveAudioViaUDP(void *args) {
while (!stopAudioReceiveThread) {
if (sharedAudioData->audioSocket->receive((void *)receivedData, &receivedBytes)) {
bool firstSample = (currentReceiveTime.tv_sec == 0);
gettimeofday(&currentReceiveTime, NULL);
@ -232,30 +241,7 @@ void *receiveAudioViaUDP(void *args) {
}
AudioRingBuffer *ringBuffer = sharedAudioData->ringBuffer;
if (ringBuffer->endOfLastWrite == NULL) {
ringBuffer->endOfLastWrite = ringBuffer->buffer;
} else if (ringBuffer->diffLastWriteNextOutput() > RING_BUFFER_SIZE_SAMPLES - PACKET_LENGTH_SAMPLES) {
std::cout << "NAB: " << ringBuffer->nextOutput - ringBuffer->buffer << "\n";
std::cout << "LAW: " << ringBuffer->endOfLastWrite - ringBuffer->buffer << "\n";
std::cout << "D: " << ringBuffer->diffLastWriteNextOutput() << "\n";
std::cout << "Full\n";
// reset us to started state
ringBuffer->endOfLastWrite = ringBuffer->buffer;
ringBuffer->nextOutput = ringBuffer->buffer;
ringBuffer->started = false;
}
int16_t *copyToPointer = ringBuffer->endOfLastWrite;
// just copy the recieved data to the right spot and then add packet length to previous pointer
memcpy(copyToPointer, receivedData, PACKET_LENGTH_BYTES);
ringBuffer->endOfLastWrite += PACKET_LENGTH_SAMPLES;
if (ringBuffer->endOfLastWrite == ringBuffer->buffer + RING_BUFFER_SIZE_SAMPLES) {
ringBuffer->endOfLastWrite = ringBuffer->buffer;
}
ringBuffer->parseData(receivedData, PACKET_LENGTH_BYTES);
if (LOG_SAMPLE_DELAY) {
gettimeofday(&previousReceiveTime, NULL);
@ -266,6 +252,10 @@ void *receiveAudioViaUDP(void *args) {
pthread_exit(0);
}
void Audio::setSourcePosition(glm::vec3 newPosition) {
audioData->sourcePosition = newPosition;
}
/**
* Initialize portaudio and start an audio stream.
* Should be called at the beginning of program exection.
@ -284,7 +274,7 @@ Audio::Audio(Oscilloscope * s)
// setup a UDPSocket
audioData->audioSocket = new UDPSocket(AUDIO_UDP_LISTEN_PORT);
audioData->ringBuffer = new AudioRingBuffer(RING_BUFFER_SIZE_SAMPLES);
audioData->ringBuffer = new AudioRingBuffer();
AudioRecThreadStruct threadArgs;
threadArgs.sharedAudioData = audioData;
@ -359,7 +349,7 @@ void Audio::render(int screenWidth, int screenHeight)
float timeLeftInCurrentBuffer = 0;
if (audioData->lastCallback.tv_usec > 0) timeLeftInCurrentBuffer = diffclock(&audioData->lastCallback, &currentTime)/(1000.0*(float)BUFFER_LENGTH_SAMPLES/(float)SAMPLE_RATE) * frameWidth;
if (audioData->ringBuffer->endOfLastWrite != NULL)
if (audioData->ringBuffer->getEndOfLastWrite() != NULL)
remainingBuffer = audioData->ringBuffer->diffLastWriteNextOutput() / BUFFER_LENGTH_SAMPLES * frameWidth;
if (audioData->wasStarved == 0) glColor3f(0, 1, 0);

View file

@ -25,11 +25,12 @@ public:
void getInputLoudness(float * lastLoudness, float * averageLoudness);
void updateMixerParams(in_addr_t mixerAddress, in_port_t mixerPort);
void setSourcePosition(glm::vec3 position);
// terminates audio I/O
bool terminate();
private:
bool initialized;
AudioData *audioData;
// protects constructor so that public init method is used

View file

@ -11,17 +11,22 @@
#include <iostream>
#include <stdint.h>
#include <glm/glm.hpp>
#include "AudioRingBuffer.h"
#include "UDPSocket.h"
class AudioData {
public:
public:
AudioData(int bufferLength);
~AudioData();
AudioRingBuffer *ringBuffer;
UDPSocket *audioSocket;
int16_t *samplesToQueue;
glm::vec3 sourcePosition;
// store current mixer address and port
in_addr_t mixerAddress;
in_port_t mixerPort;
@ -34,9 +39,6 @@ class AudioData {
float lastInputLoudness;
float averagedInputLoudness;
AudioData(int bufferLength);
~AudioData();
};
#endif /* defined(__interface__AudioData__) */

View file

@ -64,6 +64,10 @@ Head::~Head() {
// all data is primitive, do nothing
}
Head* Head::clone() const {
return new Head(*this);
}
void Head::reset()
{
Pitch = Yaw = Roll = 0;

View file

@ -24,6 +24,8 @@ class Head : public AgentData {
public:
Head();
~Head();
Head* clone() const;
void reset();
void UpdatePos(float frametime, SerialInterface * serialInterface, int head_mirror, glm::vec3 * gravity);
void setNoise (float mag) { noise = mag; }

View file

@ -53,7 +53,6 @@ int simulate_on = 1;
// Network Socket and network constants
//
const int MAX_PACKET_SIZE = 1500;
char DOMAIN_HOSTNAME[] = "highfidelity.below92.com";
char DOMAIN_IP[100] = ""; // IP Address will be used first if not empty string
const int DOMAINSERVER_PORT = 40102;
@ -513,6 +512,7 @@ void simulateHead(float frametime)
myHead.setRenderYaw(myHead.getRenderYaw() + render_yaw_rate);
myHead.setRenderPitch(render_pitch);
myHead.setPos(glm::vec3(location[0], location[1], location[2]));
audio.setSourcePosition(glm::vec3(location[0], location[1], location[2]));
// Get audio loudness data from audio input device
float loudness, averageLoudness;

View file

@ -13,229 +13,125 @@
#include <fstream>
#include <limits>
#include "AudioRingBuffer.h"
#include "UDPSocket.h"
const int MAX_AGENTS = 1000;
const int LOGOFF_CHECK_INTERVAL = 1000;
#include <AgentList.h>
#include <SharedUtil.h>
const unsigned short MIXER_LISTEN_PORT = 55443;
const int BUFFER_LENGTH_BYTES = 1024;
const int BUFFER_LENGTH_SAMPLES = BUFFER_LENGTH_BYTES / sizeof(int16_t);
const float SAMPLE_RATE = 22050.0;
const float BUFFER_SEND_INTERVAL_USECS = (BUFFER_LENGTH_SAMPLES/SAMPLE_RATE) * 1000000;
const short JITTER_BUFFER_MSECS = 20;
const short JITTER_BUFFER_SAMPLES = JITTER_BUFFER_MSECS * (SAMPLE_RATE / 1000.0);
const short RING_BUFFER_FRAMES = 10;
const short RING_BUFFER_SAMPLES = RING_BUFFER_FRAMES * BUFFER_LENGTH_SAMPLES;
const long MAX_SAMPLE_VALUE = std::numeric_limits<int16_t>::max();
const long MIN_SAMPLE_VALUE = std::numeric_limits<int16_t>::min();
const float DISTANCE_RATIO = 3.0/4.2;
char DOMAIN_HOSTNAME[] = "highfidelity.below92.com";
char DOMAIN_IP[100] = ""; // IP Address will be re-set by lookup on startup
const int DOMAINSERVER_PORT = 40102;
const int DOMAINSERVER_PORT = 40102;
const int MAX_SOURCE_BUFFERS = 20;
sockaddr_in agentAddress;
UDPSocket audioSocket = UDPSocket(MIXER_LISTEN_PORT);
struct AgentList {
char *address;
unsigned short port;
bool active;
timeval time;
bool bufferTransmitted;
} agents[MAX_AGENTS];
int numAgents = 0;
AudioRingBuffer *sourceBuffers[MAX_SOURCE_BUFFERS];
double diffclock(timeval *clock1, timeval *clock2)
{
double diffms = (clock2->tv_sec - clock1->tv_sec) * 1000.0;
diffms += (clock2->tv_usec - clock1->tv_usec) / 1000.0; // us to ms
return diffms;
}
double usecTimestamp(timeval *time, double addedUsecs = 0) {
return (time->tv_sec * 1000000.0) + time->tv_usec + addedUsecs;
}
AgentList agentList(MIXER_LISTEN_PORT);
void *sendBuffer(void *args)
{
int sentBytes;
int currentFrame = 1;
timeval startTime, sendTime, now;
int16_t *clientMix = new int16_t[BUFFER_LENGTH_SAMPLES];
long *masterMix = new long[BUFFER_LENGTH_SAMPLES];
int nextFrame = 0;
timeval startTime;
gettimeofday(&startTime, NULL);
while (true) {
sentBytes = 0;
for (int wb = 0; wb < BUFFER_LENGTH_SAMPLES; wb++) {
masterMix[wb] = 0;
}
gettimeofday(&sendTime, NULL);
for (int b = 0; b < MAX_SOURCE_BUFFERS; b++) {
if (sourceBuffers[b]->endOfLastWrite != NULL) {
if (!sourceBuffers[b]->started
&& sourceBuffers[b]->diffLastWriteNextOutput() <= BUFFER_LENGTH_SAMPLES + JITTER_BUFFER_SAMPLES) {
std::cout << "Held back buffer " << b << ".\n";
} else if (sourceBuffers[b]->diffLastWriteNextOutput() < BUFFER_LENGTH_SAMPLES) {
std::cout << "Buffer " << b << " starved.\n";
sourceBuffers[b]->started = false;
} else {
sourceBuffers[b]->started = true;
agents[b].bufferTransmitted = true;
for (int s = 0; s < BUFFER_LENGTH_SAMPLES; s++) {
masterMix[s] += sourceBuffers[b]->nextOutput[s];
}
sourceBuffers[b]->nextOutput += BUFFER_LENGTH_SAMPLES;
if (sourceBuffers[b]->nextOutput >= sourceBuffers[b]->buffer + RING_BUFFER_SAMPLES) {
sourceBuffers[b]->nextOutput = sourceBuffers[b]->buffer;
}
}
}
}
for (int a = 0; a < numAgents; a++) {
if (diffclock(&agents[a].time, &sendTime) <= LOGOFF_CHECK_INTERVAL) {
int16_t *previousOutput = NULL;
if (agents[a].bufferTransmitted) {
previousOutput = (sourceBuffers[a]->nextOutput == sourceBuffers[a]->buffer)
? sourceBuffers[a]->buffer + RING_BUFFER_SAMPLES - BUFFER_LENGTH_SAMPLES
: sourceBuffers[a]->nextOutput - BUFFER_LENGTH_SAMPLES;
agents[a].bufferTransmitted = false;
}
for(int as = 0; as < BUFFER_LENGTH_SAMPLES; as++) {
long longSample = previousOutput != NULL
? masterMix[as] - previousOutput[as]
: masterMix[as];
int16_t shortSample;
if (longSample < 0) {
shortSample = std::max(longSample, MIN_SAMPLE_VALUE);
} else {
shortSample = std::min(longSample, MAX_SAMPLE_VALUE);
}
clientMix[as] = shortSample;
// std::cout << as << " - CM: " << clientMix[as] << " MM: " << masterMix[as] << "\n";
// std::cout << previousOutput - sourceBuffers[a]->buffer << "\n";
if (previousOutput != NULL) {
// std::cout << "PO: " << previousOutput[as] << "\n";
}
}
sentBytes = audioSocket.send(agents[a].address, agents[a].port, clientMix, BUFFER_LENGTH_BYTES);
for (int i = 0; i < agentList.getAgents().size(); i++) {
AudioRingBuffer *agentBuffer = (AudioRingBuffer *) agentList.getAgents()[i].getLinkedData();
if (sentBytes < BUFFER_LENGTH_BYTES) {
std::cout << "Error sending mix packet! " << sentBytes << strerror(errno) << "\n";
if (agentBuffer != NULL && agentBuffer->getEndOfLastWrite() != NULL) {
if (!agentBuffer->isStarted() && agentBuffer->diffLastWriteNextOutput() <= BUFFER_LENGTH_SAMPLES + JITTER_BUFFER_SAMPLES) {
printf("Held back buffer %d.\n", i);
} else if (agentBuffer->diffLastWriteNextOutput() < BUFFER_LENGTH_SAMPLES) {
printf("Buffer %d starved.\n", i);
agentBuffer->setStarted(false);
} else {
// good buffer, add this to the mix
agentBuffer->setStarted(true);
agentBuffer->setAddedToMix(true);
}
}
}
for (int i = 0; i < agentList.getAgents().size(); i++) {
Agent *agent = &agentList.getAgents()[i];
int16_t clientMix[BUFFER_LENGTH_SAMPLES] = {};
for (int j = 0; j < agentList.getAgents().size(); j++) {
if (i != j) {
AudioRingBuffer *otherAgentBuffer = (AudioRingBuffer *)agentList.getAgents()[j].getLinkedData();
float *agentPosition = ((AudioRingBuffer *)agent->getLinkedData())->getPosition();
float *otherAgentPosition = otherAgentBuffer->getPosition();
float distanceToAgent = sqrtf(powf(agentPosition[0] - otherAgentPosition[0], 2) +
powf(agentPosition[1] - otherAgentPosition[1], 2) +
powf(agentPosition[2] - otherAgentPosition[2], 2));
float distanceCoeff = powf((logf(DISTANCE_RATIO * distanceToAgent) / logf(3)), 2);
for (int s = 0; s < BUFFER_LENGTH_SAMPLES; s++) {
int16_t sample = (otherAgentBuffer->getNextOutput()[s] / distanceCoeff);
clientMix[s] += sample;
}
}
}
}
gettimeofday(&now, NULL);
agentList.getAgentSocket().send(agent->getPublicSocket(), clientMix, BUFFER_LENGTH_BYTES);
}
for (int i = 0; i < agentList.getAgents().size(); i++) {
AudioRingBuffer *agentBuffer = (AudioRingBuffer *)agentList.getAgents()[i].getLinkedData();
if (agentBuffer->wasAddedToMix()) {
agentBuffer->setNextOutput(agentBuffer->getNextOutput() + BUFFER_LENGTH_SAMPLES);
if (agentBuffer->getNextOutput() >= agentBuffer->getBuffer() + RING_BUFFER_SAMPLES) {
agentBuffer->setNextOutput(agentBuffer->getBuffer());
}
agentBuffer->setAddedToMix(false);
}
}
double usecToSleep = usecTimestamp(&startTime) + (++nextFrame * BUFFER_SEND_INTERVAL_USECS) - usecTimestampNow();
double usecToSleep = usecTimestamp(&startTime, (currentFrame * BUFFER_SEND_INTERVAL_USECS)) - usecTimestamp(&now);
if (usecToSleep > 0) {
usleep(usecToSleep);
} else {
std::cout << "NOT SLEEPING!";
std::cout << "Took too much time, not sleeping!\n";
}
currentFrame++;
}
pthread_exit(0);
}
int addAgent(sockaddr_in *newAddress, void *audioData) {
// Search for agent in list and add if needed
int is_new = 0;
int i = 0;
for (i = 0; i < numAgents; i++) {
if (strcmp(inet_ntoa(newAddress->sin_addr), agents[i].address) == 0
&& ntohs(newAddress->sin_port) == agents[i].port) {
break;
}
}
if ((i == numAgents) || (agents[i].active == false)) {
is_new = 1;
agents[i].address = new char();
strcpy(agents[i].address, inet_ntoa(newAddress->sin_addr));
agents[i].bufferTransmitted = false;
}
agents[i].port = ntohs(newAddress->sin_port);
agents[i].active = true;
gettimeofday(&agents[i].time, NULL);
if (sourceBuffers[i]->endOfLastWrite == NULL) {
sourceBuffers[i]->endOfLastWrite = sourceBuffers[i]->buffer;
} else if (sourceBuffers[i]->diffLastWriteNextOutput() > RING_BUFFER_SAMPLES - BUFFER_LENGTH_SAMPLES) {
// reset us to started state
sourceBuffers[i]->endOfLastWrite = sourceBuffers[i]->buffer;
sourceBuffers[i]->nextOutput = sourceBuffers[i]->buffer;
sourceBuffers[i]->started = false;
}
memcpy(sourceBuffers[i]->endOfLastWrite, audioData, BUFFER_LENGTH_BYTES);
sourceBuffers[i]->endOfLastWrite += BUFFER_LENGTH_SAMPLES;
if (sourceBuffers[i]->endOfLastWrite >= sourceBuffers[i]->buffer + RING_BUFFER_SAMPLES) {
sourceBuffers[i]->endOfLastWrite = sourceBuffers[i]->buffer;
}
if (i == numAgents) {
numAgents++;
}
return is_new;
}
void *reportAliveToDS(void *args) {
timeval lastSend, now;
timeval lastSend;
unsigned char output[7];
while (true) {
gettimeofday(&lastSend, NULL);
*output = 'M';
packSocket(output + 1, 895283510, htons(MIXER_LISTEN_PORT));
audioSocket.send(DOMAIN_IP, DOMAINSERVER_PORT, output, 7);
// packSocket(output + 1, 895283510, htons(MIXER_LISTEN_PORT));
packSocket(output + 1, 788637888, htons(MIXER_LISTEN_PORT));
agentList.getAgentSocket().send(DOMAIN_IP, DOMAINSERVER_PORT, output, 7);
gettimeofday(&now, NULL);
double usecToSleep = 1000000 - (usecTimestamp(&now) - usecTimestamp(&lastSend));
double usecToSleep = 1000000 - (usecTimestampNow() - usecTimestamp(&lastSend));
if (usecToSleep > 0) {
usleep(usecToSleep);
@ -245,11 +141,20 @@ void *reportAliveToDS(void *args) {
}
}
void attachNewBufferToAgent(Agent *newAgent) {
if (newAgent->getLinkedData() == NULL) {
newAgent->setLinkedData(new AudioRingBuffer());
}
}
int main(int argc, const char * argv[])
{
timeval lastAgentUpdate;
{
ssize_t receivedBytes = 0;
agentList.linkedDataCreateCallback = attachNewBufferToAgent;
agentList.startSilentAgentRemovalThread();
// setup the agentSocket to report to domain server
pthread_t reportAliveThread;
pthread_create(&reportAliveThread, NULL, reportAliveToDS, NULL);
@ -270,29 +175,24 @@ int main(int argc, const char * argv[])
printf("Using static domainserver IP: %s\n", DOMAIN_IP);
}
gettimeofday(&lastAgentUpdate, NULL);
int16_t packetData[BUFFER_LENGTH_SAMPLES];
for (int b = 0; b < MAX_SOURCE_BUFFERS; b++) {
sourceBuffers[b] = new AudioRingBuffer(10 * BUFFER_LENGTH_SAMPLES);
}
unsigned char *packetData = new unsigned char[MAX_PACKET_SIZE];
pthread_t sendBufferThread;
pthread_create(&sendBufferThread, NULL, sendBuffer, NULL);
sockaddr *agentAddress = new sockaddr;
while (true) {
if(audioSocket.receive((sockaddr *)&agentAddress, packetData, &receivedBytes)) {
if (receivedBytes == BUFFER_LENGTH_BYTES) {
if (addAgent(&agentAddress, packetData)) {
std::cout << "Added agent: " <<
inet_ntoa(agentAddress.sin_addr) << " on " <<
ntohs(agentAddress.sin_port) << "\n";
}
if(agentList.getAgentSocket().receive(agentAddress, packetData, &receivedBytes)) {
if (receivedBytes >= BUFFER_LENGTH_BYTES) {
// add or update the existing interface agent
agentList.addOrUpdateAgent(agentAddress, agentAddress, packetData[0]);
agentList.updateAgentWithData(agentAddress, (void *)packetData, receivedBytes);
}
}
}
agentList.stopSilentAgentRemovalThread();
pthread_join(reportAliveThread, NULL);
pthread_join(sendBufferThread, NULL);

View file

@ -49,8 +49,11 @@ Agent::Agent(const Agent &otherAgent) {
lastRecvTimeUsecs = otherAgent.lastRecvTimeUsecs;
type = otherAgent.type;
// linked data is transient, gets re-assigned on next packet receive
linkedData = NULL;
if (otherAgent.linkedData != NULL) {
linkedData = otherAgent.linkedData->clone();
} else {
linkedData = NULL;
}
}
Agent& Agent::operator=(Agent otherAgent) {
@ -116,8 +119,6 @@ void Agent::activatePublicSocket() {
activeSocket = publicSocket;
}
AgentData* Agent::getLinkedData() {
return linkedData;
}

View file

@ -13,6 +13,7 @@ class AgentData {
public:
virtual ~AgentData() = 0;
virtual void parseData(void * data, int size) = 0;
virtual AgentData* clone() const = 0;
};
#endif

View file

@ -14,6 +14,7 @@
#include "Agent.h"
#include "UDPSocket.h"
const int MAX_PACKET_SIZE = 1500;
const unsigned short AGENT_SOCKET_LISTEN_PORT = 40103;
const int AGENT_SILENCE_THRESHOLD_USECS = 2 * 1000000;
extern const char *SOLO_AGENT_TYPES_STRING;
@ -33,6 +34,7 @@ class AgentList {
int updateList(unsigned char *packetData, size_t dataBytes);
bool addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, char agentType);
void processAgentData(sockaddr *senderAddress, void *packetData, size_t dataBytes);
void updateAgentWithData(sockaddr *senderAddress, void *packetData, size_t dataBytes);
void broadcastToAgents(char *broadcastData, size_t dataBytes);
void sendToAgent(Agent *destAgent, void *packetData, size_t dataBytes);
void pingAgents();
@ -44,7 +46,6 @@ class AgentList {
pthread_t removeSilentAgentsThread;
int indexOfMatchingAgent(sockaddr *senderAddress);
void updateAgentWithData(sockaddr *senderAddress, void *packetData, size_t dataBytes);
void handlePingReply(sockaddr *agentAddress);
};

View file

@ -6,22 +6,115 @@
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
//
#include <cstring>
#include "AudioRingBuffer.h"
AudioRingBuffer::AudioRingBuffer(short ringBufferSamples) {
ringBufferLengthSamples = ringBufferSamples;
AudioRingBuffer::AudioRingBuffer() {
started = false;
addedToMix = false;
endOfLastWrite = NULL;
buffer = new int16_t[ringBufferLengthSamples];
buffer = new int16_t[RING_BUFFER_SAMPLES];
nextOutput = buffer;
};
AudioRingBuffer::AudioRingBuffer(const AudioRingBuffer &otherRingBuffer) {
started = otherRingBuffer.started;
addedToMix = otherRingBuffer.addedToMix;
buffer = new int16_t[RING_BUFFER_SAMPLES];
memcpy(buffer, otherRingBuffer.buffer, sizeof(int16_t) * RING_BUFFER_SAMPLES);
nextOutput = buffer + (otherRingBuffer.nextOutput - otherRingBuffer.buffer);
endOfLastWrite = buffer + (otherRingBuffer.endOfLastWrite - otherRingBuffer.buffer);
}
AudioRingBuffer::~AudioRingBuffer() {
delete[] buffer;
};
AudioRingBuffer* AudioRingBuffer::clone() const {
return new AudioRingBuffer(*this);
}
int16_t* AudioRingBuffer::getNextOutput() {
return nextOutput;
}
void AudioRingBuffer::setNextOutput(int16_t *newPointer) {
nextOutput = newPointer;
}
int16_t* AudioRingBuffer::getEndOfLastWrite() {
return endOfLastWrite;
}
void AudioRingBuffer::setEndOfLastWrite(int16_t *newPointer) {
endOfLastWrite = newPointer;
}
int16_t* AudioRingBuffer::getBuffer() {
return buffer;
}
bool AudioRingBuffer::isStarted() {
return started;
}
void AudioRingBuffer::setStarted(bool status) {
started = status;
}
bool AudioRingBuffer::wasAddedToMix() {
return addedToMix;
}
void AudioRingBuffer::setAddedToMix(bool added) {
addedToMix = added;
}
float* AudioRingBuffer::getPosition() {
return position;
}
void AudioRingBuffer::setPosition(float *newPosition) {
position[0] = newPosition[0];
position[1] = newPosition[1];
position[2] = newPosition[2];
}
void AudioRingBuffer::parseData(void *data, int size) {
unsigned char *audioDataStart = (unsigned char *) data;
if (size > BUFFER_LENGTH_BYTES) {
for (int p = 0; p < 3; p ++) {
memcpy(&position[p], audioDataStart + 1 + (sizeof(float) * p), sizeof(float));
}
audioDataStart += (1 + (sizeof(float) * 3));
}
if (endOfLastWrite == NULL) {
endOfLastWrite = buffer;
} else if (diffLastWriteNextOutput() > RING_BUFFER_SAMPLES - BUFFER_LENGTH_SAMPLES) {
endOfLastWrite = buffer;
nextOutput = buffer;
started = false;
}
memcpy(endOfLastWrite, audioDataStart, BUFFER_LENGTH_BYTES);
endOfLastWrite += BUFFER_LENGTH_SAMPLES;
addedToMix = false;
if (endOfLastWrite >= buffer + RING_BUFFER_SAMPLES) {
endOfLastWrite = buffer;
}
}
short AudioRingBuffer::diffLastWriteNextOutput()
{
if (endOfLastWrite == NULL) {
@ -30,20 +123,9 @@ short AudioRingBuffer::diffLastWriteNextOutput()
short sampleDifference = endOfLastWrite - nextOutput;
if (sampleDifference < 0) {
sampleDifference += ringBufferLengthSamples;
sampleDifference += RING_BUFFER_SAMPLES;
}
return sampleDifference;
}
}
short AudioRingBuffer::bufferOverlap(int16_t *pointer, short addedDistance)
{
short samplesLeft = (buffer + ringBufferLengthSamples) - pointer;
if (samplesLeft < addedDistance) {
return addedDistance - samplesLeft;
} else {
return 0;
}
}

View file

@ -11,20 +11,43 @@
#include <iostream>
#include <stdint.h>
#include "AgentData.h"
class AudioRingBuffer {
const int BUFFER_LENGTH_BYTES = 1024;
const int BUFFER_LENGTH_SAMPLES = BUFFER_LENGTH_BYTES / sizeof(int16_t);
const short RING_BUFFER_FRAMES = 10;
const short RING_BUFFER_SAMPLES = RING_BUFFER_FRAMES * BUFFER_LENGTH_SAMPLES;
class AudioRingBuffer : public AgentData {
public:
AudioRingBuffer();
~AudioRingBuffer();
AudioRingBuffer(const AudioRingBuffer &otherRingBuffer);
void parseData(void *data, int size);
AudioRingBuffer* clone() const;
int16_t* getNextOutput();
void setNextOutput(int16_t *newPointer);
int16_t* getEndOfLastWrite();
void setEndOfLastWrite(int16_t *newPointer);
int16_t* getBuffer();
bool isStarted();
void setStarted(bool status);
bool wasAddedToMix();
void setAddedToMix(bool added);
float* getPosition();
void setPosition(float newPosition[]);
short diffLastWriteNextOutput();
private:
float position[3];
int16_t *nextOutput;
int16_t *endOfLastWrite;
int16_t *buffer;
short ringBufferLengthSamples;
bool started;
short diffLastWriteNextOutput();
short bufferOverlap(int16_t *pointer, short addedDistance);
AudioRingBuffer(short ringBufferSamples);
~AudioRingBuffer();
bool addedToMix;
};
#endif /* defined(__interface__AudioRingBuffer__) */

View file

@ -9,11 +9,11 @@
#include "SharedUtil.h"
double usecTimestamp(timeval *time) {
return (time->tv_sec * 1000000.0);
return (time->tv_sec * 1000000.0 + time->tv_usec);
}
double usecTimestampNow() {
timeval now;
gettimeofday(&now, NULL);
return (now.tv_sec * 1000000.0);
return (now.tv_sec * 1000000.0 + now.tv_usec);
}

View file

@ -113,7 +113,6 @@ bool UDPSocket::receive(sockaddr *recvAddress, void *receivedData, ssize_t *rece
int UDPSocket::send(sockaddr *destAddress, const void *data, size_t byteLength) {
// send data via UDP
int sent_bytes = sendto(handle, (const char*)data, byteLength,
0, (sockaddr *) destAddress, sizeof(sockaddr_in));

View file

@ -13,7 +13,7 @@
#include <netinet/in.h>
#include <netdb.h>
#define MAX_BUFFER_LENGTH_BYTES 1024
#define MAX_BUFFER_LENGTH_BYTES 1500
class UDPSocket {
public: