diff --git a/domain/src/main.cpp b/domain/src/main.cpp index 7b6f75ad3f..81b2ccc7d9 100644 --- a/domain/src/main.cpp +++ b/domain/src/main.cpp @@ -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 newestSoloAgents; - while (true) { if (agentList.getAgentSocket().receive((sockaddr *)&agentPublicAddress, packetData, &receivedBytes)) { + std::map newestSoloAgents; + agentType = packetData[0]; unpackSocket(&packetData[1], (sockaddr *)&agentLocalAddress); diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index b433b2a199..74f6d51e7c 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -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(¤tReceiveTime, 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, ¤tTime)/(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); diff --git a/interface/src/Audio.h b/interface/src/Audio.h index 7f1fa9143f..0798486106 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -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 diff --git a/interface/src/AudioData.h b/interface/src/AudioData.h index e5094f8263..4efe39884a 100644 --- a/interface/src/AudioData.h +++ b/interface/src/AudioData.h @@ -11,17 +11,22 @@ #include #include +#include #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__) */ diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index d69a3fa35f..6930d7a77a 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -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; diff --git a/interface/src/Head.h b/interface/src/Head.h index 8fc73c7e8c..b554d4541e 100644 --- a/interface/src/Head.h +++ b/interface/src/Head.h @@ -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; } diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 5f372e5065..1906b4e696 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -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; diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index eb125e1831..85313b6a6e 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -13,229 +13,125 @@ #include #include #include "AudioRingBuffer.h" -#include "UDPSocket.h" - -const int MAX_AGENTS = 1000; -const int LOGOFF_CHECK_INTERVAL = 1000; +#include +#include 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::max(); const long MIN_SAMPLE_VALUE = std::numeric_limits::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); diff --git a/shared/src/Agent.cpp b/shared/src/Agent.cpp index a635314b64..cacb3a5f94 100644 --- a/shared/src/Agent.cpp +++ b/shared/src/Agent.cpp @@ -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; } diff --git a/shared/src/AgentData.h b/shared/src/AgentData.h index e39f5ade6b..9db7535521 100644 --- a/shared/src/AgentData.h +++ b/shared/src/AgentData.h @@ -13,6 +13,7 @@ class AgentData { public: virtual ~AgentData() = 0; virtual void parseData(void * data, int size) = 0; + virtual AgentData* clone() const = 0; }; #endif diff --git a/shared/src/AgentList.h b/shared/src/AgentList.h index 2755058503..4fb6a2d989 100644 --- a/shared/src/AgentList.h +++ b/shared/src/AgentList.h @@ -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); }; diff --git a/shared/src/AudioRingBuffer.cpp b/shared/src/AudioRingBuffer.cpp index f79df7945d..15743b7d19 100644 --- a/shared/src/AudioRingBuffer.cpp +++ b/shared/src/AudioRingBuffer.cpp @@ -6,22 +6,115 @@ // Copyright (c) 2013 HighFidelity, Inc. All rights reserved. // +#include #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; - } -} diff --git a/shared/src/AudioRingBuffer.h b/shared/src/AudioRingBuffer.h index eecdbd0c55..f9c3f5e136 100644 --- a/shared/src/AudioRingBuffer.h +++ b/shared/src/AudioRingBuffer.h @@ -11,20 +11,43 @@ #include #include +#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__) */ diff --git a/shared/src/SharedUtil.cpp b/shared/src/SharedUtil.cpp index 5880b8919a..d9de883024 100644 --- a/shared/src/SharedUtil.cpp +++ b/shared/src/SharedUtil.cpp @@ -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); } \ No newline at end of file diff --git a/shared/src/UDPSocket.cpp b/shared/src/UDPSocket.cpp index ec4c63803e..85ebcf2056 100644 --- a/shared/src/UDPSocket.cpp +++ b/shared/src/UDPSocket.cpp @@ -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)); diff --git a/shared/src/UDPSocket.h b/shared/src/UDPSocket.h index 27a3c48ad3..b2389ad73f 100644 --- a/shared/src/UDPSocket.h +++ b/shared/src/UDPSocket.h @@ -13,7 +13,7 @@ #include #include -#define MAX_BUFFER_LENGTH_BYTES 1024 +#define MAX_BUFFER_LENGTH_BYTES 1500 class UDPSocket { public: