From 4741eb869e0b12b043f9ca4be7c115ac03791552 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Hor=C3=A1=C4=8Dek?= Date: Fri, 22 Feb 2013 18:22:16 +0100 Subject: [PATCH 01/85] add Mac OS X "Scope" menu with empty action --- interface/CMakeLists.txt | 2 +- interface/src/InterfaceMacOSX.h | 6 ++++ interface/src/InterfaceMacOSX.mm | 55 ++++++++++++++++++++++++++++++++ interface/src/main.cpp | 12 ++++++- 4 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 interface/src/InterfaceMacOSX.h create mode 100644 interface/src/InterfaceMacOSX.mm diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 0685aca6cd..d3bb79281b 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -21,7 +21,7 @@ endif (APPLE) configure_file(InterfaceConfig.h.in ${PROJECT_BINARY_DIR}/includes/InterfaceConfig.h) # grab the implementation and header files from src dir -file(GLOB INTERFACE_SRCS src/*.cpp src/*.h) +file(GLOB INTERFACE_SRCS src/*.mm src/*.cpp src/*.h) if (APPLE) # set how the icon shows up in the Info.plist file diff --git a/interface/src/InterfaceMacOSX.h b/interface/src/InterfaceMacOSX.h new file mode 100644 index 0000000000..1416d637a4 --- /dev/null +++ b/interface/src/InterfaceMacOSX.h @@ -0,0 +1,6 @@ +#ifndef __interface__InterfaceMacOSX +#define __interface__InterfaceMacOSX + +void initMacOSXMenu(); + +#endif diff --git a/interface/src/InterfaceMacOSX.mm b/interface/src/InterfaceMacOSX.mm new file mode 100644 index 0000000000..c834067324 --- /dev/null +++ b/interface/src/InterfaceMacOSX.mm @@ -0,0 +1,55 @@ +#import +#import + +@interface InterfaceMainMenuTarget : NSObject + +@property (strong, nonatomic) NSMenuItem *scopeAudioMenuItem; +@property (strong, nonatomic) NSMenuItem *scopeNoneMenuItem; + +@end + +@implementation InterfaceMainMenuTarget + +- (void)scopeAudioAction { + NSLog(@"scopeAudioAction"); +} + +- (void)scopeNoneAction { + NSLog(@"scopeNoneAction"); +} + +@end + +static InterfaceMainMenuTarget *sharedInterfaceMainMenuTarget = nil; + +void initMacOSXMenu() { + @autoreleasepool { + if (NSApp) { + if (!sharedInterfaceMainMenuTarget) { + sharedInterfaceMainMenuTarget = [[InterfaceMainMenuTarget alloc] init]; + } + + NSMenu *mainMenu = [NSApp mainMenu]; + + NSMenuItem *scopeMenuItem = [mainMenu insertItemWithTitle:@"Scope" + action:nil + keyEquivalent:@"" + atIndex:3]; + + NSMenu *scopeMenu = [[[NSMenu alloc] init] initWithTitle:@"Scope"]; + [scopeMenuItem setSubmenu:scopeMenu]; + sharedInterfaceMainMenuTarget.scopeAudioMenuItem = [scopeMenu addItemWithTitle:@"Audio" + action:@selector(scopeAudioAction) + keyEquivalent:@""]; + [sharedInterfaceMainMenuTarget.scopeAudioMenuItem setTarget:sharedInterfaceMainMenuTarget]; + [sharedInterfaceMainMenuTarget.scopeAudioMenuItem setState:NSOnState]; + + sharedInterfaceMainMenuTarget.scopeNoneMenuItem = [scopeMenu addItemWithTitle:@"None" + action:@selector(scopeNoneAction) + keyEquivalent:@""]; + [sharedInterfaceMainMenuTarget.scopeNoneMenuItem setTarget:sharedInterfaceMainMenuTarget]; + + [NSApp setMainMenu:mainMenu]; + } + } +} diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 0f96ceb951..e20ef1a23d 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -44,6 +44,12 @@ #include "Oscilloscope.h" #include "UDPSocket.h" +#ifdef __APPLE__ + +#include "InterfaceMacOSX.h" + +#endif + using namespace std; int audio_on = 1; // Whether to turn on the audio support @@ -966,7 +972,11 @@ int main(int argc, char** argv) printf( "Init() complete.\n" ); glutTimerFunc(1000, Timer, 0); - + +#ifdef __APPLE__ + initMacOSXMenu(); +#endif + glutMainLoop(); pthread_join(networkReceiveThread, NULL); From 36a558d1236781d0bb72e66610f602d8d3ef2521 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Hor=C3=A1=C4=8Dek?= Date: Fri, 22 Feb 2013 18:38:25 +0100 Subject: [PATCH 02/85] add "Scope" menu functionality --- interface/src/InterfaceMacOSX.h | 4 +++- interface/src/InterfaceMacOSX.mm | 24 ++++++++++++++++++++---- interface/src/main.cpp | 2 +- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/interface/src/InterfaceMacOSX.h b/interface/src/InterfaceMacOSX.h index 1416d637a4..2b36ff811f 100644 --- a/interface/src/InterfaceMacOSX.h +++ b/interface/src/InterfaceMacOSX.h @@ -1,6 +1,8 @@ #ifndef __interface__InterfaceMacOSX #define __interface__InterfaceMacOSX -void initMacOSXMenu(); +class Oscilloscope; + +void initMacOSXMenu(Oscilloscope *audioScope); #endif diff --git a/interface/src/InterfaceMacOSX.mm b/interface/src/InterfaceMacOSX.mm index c834067324..500dd6efc8 100644 --- a/interface/src/InterfaceMacOSX.mm +++ b/interface/src/InterfaceMacOSX.mm @@ -1,6 +1,16 @@ +#include "Oscilloscope.h" + #import #import +#import "InterfaceMacOSX.h" + +@class InterfaceMainMenuTarget; + +static InterfaceMainMenuTarget *sharedInterfaceMainMenuTarget = nil; +static Oscilloscope *sharedAudioScope; + + @interface InterfaceMainMenuTarget : NSObject @property (strong, nonatomic) NSMenuItem *scopeAudioMenuItem; @@ -8,21 +18,27 @@ @end + @implementation InterfaceMainMenuTarget - (void)scopeAudioAction { - NSLog(@"scopeAudioAction"); + sharedAudioScope->setState(true); + [self.scopeAudioMenuItem setState:NSOnState]; + [self.scopeNoneMenuItem setState:NSOffState]; } - (void)scopeNoneAction { - NSLog(@"scopeNoneAction"); + sharedAudioScope->setState(false); + [self.scopeAudioMenuItem setState:NSOffState]; + [self.scopeNoneMenuItem setState:NSOnState]; } @end -static InterfaceMainMenuTarget *sharedInterfaceMainMenuTarget = nil; -void initMacOSXMenu() { +void initMacOSXMenu(Oscilloscope *audioScope) { + sharedAudioScope = audioScope; + @autoreleasepool { if (NSApp) { if (!sharedInterfaceMainMenuTarget) { diff --git a/interface/src/main.cpp b/interface/src/main.cpp index e20ef1a23d..5ab8451f04 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -974,7 +974,7 @@ int main(int argc, char** argv) glutTimerFunc(1000, Timer, 0); #ifdef __APPLE__ - initMacOSXMenu(); + initMacOSXMenu(&audioScope); #endif glutMainLoop(); From 7d73ca9b418aa67143f5605fd1c30d02ac456654 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Hor=C3=A1=C4=8Dek?= Date: Fri, 22 Feb 2013 18:46:41 +0100 Subject: [PATCH 03/85] code cleanup --- interface/src/InterfaceMacOSX.mm | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/interface/src/InterfaceMacOSX.mm b/interface/src/InterfaceMacOSX.mm index 500dd6efc8..466212207b 100644 --- a/interface/src/InterfaceMacOSX.mm +++ b/interface/src/InterfaceMacOSX.mm @@ -37,13 +37,12 @@ static Oscilloscope *sharedAudioScope; void initMacOSXMenu(Oscilloscope *audioScope) { - sharedAudioScope = audioScope; - @autoreleasepool { if (NSApp) { if (!sharedInterfaceMainMenuTarget) { sharedInterfaceMainMenuTarget = [[InterfaceMainMenuTarget alloc] init]; } + sharedAudioScope = audioScope; NSMenu *mainMenu = [NSApp mainMenu]; @@ -55,17 +54,15 @@ void initMacOSXMenu(Oscilloscope *audioScope) { NSMenu *scopeMenu = [[[NSMenu alloc] init] initWithTitle:@"Scope"]; [scopeMenuItem setSubmenu:scopeMenu]; sharedInterfaceMainMenuTarget.scopeAudioMenuItem = [scopeMenu addItemWithTitle:@"Audio" - action:@selector(scopeAudioAction) - keyEquivalent:@""]; + action:@selector(scopeAudioAction) + keyEquivalent:@""]; [sharedInterfaceMainMenuTarget.scopeAudioMenuItem setTarget:sharedInterfaceMainMenuTarget]; [sharedInterfaceMainMenuTarget.scopeAudioMenuItem setState:NSOnState]; sharedInterfaceMainMenuTarget.scopeNoneMenuItem = [scopeMenu addItemWithTitle:@"None" - action:@selector(scopeNoneAction) - keyEquivalent:@""]; + action:@selector(scopeNoneAction) + keyEquivalent:@""]; [sharedInterfaceMainMenuTarget.scopeNoneMenuItem setTarget:sharedInterfaceMainMenuTarget]; - - [NSApp setMainMenu:mainMenu]; } } } From 1317be2382c4aa0073f8047af76906a17145e6e5 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 25 Feb 2013 11:52:38 -0800 Subject: [PATCH 04/85] domain server only returns newest of types in SOLO_AGENT_TYPES_STRING --- domain/src/main.cpp | 36 +++++++++++++++++++++++++++++++----- shared/src/Agent.cpp | 3 +++ shared/src/Agent.h | 1 + shared/src/AgentList.cpp | 2 ++ shared/src/AgentList.h | 1 + 5 files changed, 38 insertions(+), 5 deletions(-) diff --git a/domain/src/main.cpp b/domain/src/main.cpp index 5f9b075c48..7dd89df557 100644 --- a/domain/src/main.cpp +++ b/domain/src/main.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include "AgentList.h" #include "SharedUtil.h" @@ -42,6 +43,15 @@ const int LOGOFF_CHECK_INTERVAL = 5000; int lastActiveCount = 0; AgentList agentList(DOMAIN_LISTEN_PORT); +unsigned char * addAgentToBroadcastPacket(unsigned char *currentPosition, Agent *agentToAdd) { + *currentPosition++ = agentToAdd->type; + + currentPosition += packSocket(currentPosition, agentToAdd->publicSocket); + currentPosition += packSocket(currentPosition, agentToAdd->localSocket); + + // return the new unsigned char * for broadcast packet + return currentPosition; +} int main(int argc, const char * argv[]) { @@ -60,6 +70,8 @@ int main(int argc, const char * argv[]) agentList.startSilentAgentRemovalThread(); + std::map newestSoloAgents; + while (true) { if (agentList.getAgentSocket()->receive((sockaddr *)&agentPublicAddress, packetData, &receivedBytes)) { agentType = packetData[0]; @@ -73,17 +85,31 @@ int main(int argc, const char * argv[]) for(std::vector::iterator agent = agentList.agents.begin(); agent != agentList.agents.end(); agent++) { if (DEBUG_TO_SELF || !agent->matches((sockaddr *)&agentPublicAddress, (sockaddr *)&agentLocalAddress, agentType)) { - *currentBufferPos++ = agent->type; - - currentBufferPos += packSocket(currentBufferPos, agent->publicSocket); - currentBufferPos += packSocket(currentBufferPos, agent->localSocket); + if (strchr(SOLO_AGENT_TYPES_STRING, (int) agent->type) == NULL) { + // this is an agent of which there can be multiple, just add them to the packet + currentBufferPos = addAgentToBroadcastPacket(currentBufferPos, &(*agent)); + } else { + std::cout << "We have a solo agent: " << &(*agent) << "\n"; + // solo agent, we need to only send newest + if (newestSoloAgents[agent->type] == NULL || + newestSoloAgents[agent->type]->firstRecvTimeUsecs < agent->firstRecvTimeUsecs) { + // we have to set the newer solo agent to add it to the broadcast later + newestSoloAgents[agent->type] = &(*agent); + } + } } else { // this is the agent, just update last receive to now agent->lastRecvTimeUsecs = usecTimestampNow(); } } - ; + for (std::map::iterator agentIterator = newestSoloAgents.begin(); + agentIterator != newestSoloAgents.end(); + agentIterator++) { + std::cout << "Newest agent: " << agentIterator->second << "\n"; + // this is the newest alive solo agent, add them to the packet + currentBufferPos = addAgentToBroadcastPacket(currentBufferPos, agentIterator->second); + } if ((packetBytesWithoutLeadingChar = (currentBufferPos - startPointer))) { agentList.getAgentSocket()->send((sockaddr *)&agentPublicAddress, broadcastPacket, packetBytesWithoutLeadingChar + 1); diff --git a/shared/src/Agent.cpp b/shared/src/Agent.cpp index 5b48033225..5790329c80 100644 --- a/shared/src/Agent.cpp +++ b/shared/src/Agent.cpp @@ -22,6 +22,8 @@ Agent::Agent(sockaddr *agentPublicSocket, sockaddr *agentLocalSocket, char agent memcpy(localSocket, agentLocalSocket, sizeof(sockaddr)); type = agentType; + + firstRecvTimeUsecs = usecTimestampNow(); lastRecvTimeUsecs = usecTimestampNow(); activeSocket = NULL; @@ -43,6 +45,7 @@ Agent::Agent(const Agent &otherAgent) { activeSocket = NULL; } + firstRecvTimeUsecs = otherAgent.firstRecvTimeUsecs; lastRecvTimeUsecs = otherAgent.lastRecvTimeUsecs; type = otherAgent.type; diff --git a/shared/src/Agent.h b/shared/src/Agent.h index efcebc3b05..90073a92b0 100644 --- a/shared/src/Agent.h +++ b/shared/src/Agent.h @@ -28,6 +28,7 @@ class Agent { char type; timeval pingStarted; int pingMsecs; + double firstRecvTimeUsecs; double lastRecvTimeUsecs; bool isSelf; AgentData *linkedData; diff --git a/shared/src/AgentList.cpp b/shared/src/AgentList.cpp index d068ab15fc..fdf4e430ff 100644 --- a/shared/src/AgentList.cpp +++ b/shared/src/AgentList.cpp @@ -11,6 +11,8 @@ #include #include "SharedUtil.h" +const char * SOLO_AGENT_TYPES_STRING = "M"; + bool stopAgentRemovalThread = false; pthread_mutex_t vectorChangeMutex = PTHREAD_MUTEX_INITIALIZER; diff --git a/shared/src/AgentList.h b/shared/src/AgentList.h index 399340b841..734d64da9e 100644 --- a/shared/src/AgentList.h +++ b/shared/src/AgentList.h @@ -16,6 +16,7 @@ const unsigned short AGENT_SOCKET_LISTEN_PORT = 40103; const int AGENT_SILENCE_THRESHOLD_USECS = 2 * 1000000; +extern const char *SOLO_AGENT_TYPES_STRINGg; class AgentList { public: From 4541a5fe7867ec5e1f58f776dddb9337b461b8f2 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 25 Feb 2013 12:24:42 -0800 Subject: [PATCH 05/85] AgentList returns agents vector and agentSocket by reference --- interface/src/main.cpp | 8 ++++---- shared/src/AgentList.cpp | 8 ++++++-- shared/src/AgentList.h | 15 +++++++++------ 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 44ed1b8ac9..9b3ad7a39f 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -223,7 +223,7 @@ void Timer(int extra) output[0] = 'I'; packSocket(output + 1, localAddress, htons(AGENT_SOCKET_LISTEN_PORT)); - agentList.getAgentSocket()->send(DOMAIN_IP, DOMAINSERVER_PORT, output, 7); + agentList.getAgentSocket().send(DOMAIN_IP, DOMAINSERVER_PORT, output, 7); // Ping the agents we can see agentList.pingAgents(); @@ -570,7 +570,7 @@ void display(void) if (display_field) field.render(); // Render heads of other agents - for(std::vector::iterator agent = agentList.agents.begin(); agent != agentList.agents.end(); agent++) { + for(std::vector::iterator agent = agentList.getAgents().begin(); agent != agentList.getAgents().end(); agent++) { if (agent->linkedData != NULL) { Head *agentHead = (Head *)agent->linkedData; glPushMatrix(); @@ -659,7 +659,7 @@ void display(void) // Draw number of nearby people always char agents[100]; - sprintf(agents, "Agents nearby: %ld\n", agentList.agents.size()); + sprintf(agents, "Agents nearby: %ld\n", agentList.getAgents().size()); drawtext(WIDTH-200,20, 0.10, 0, 1.0, 0, agents, 1, 1, 0); glPopMatrix(); @@ -744,7 +744,7 @@ void *networkReceive(void *args) char *incomingPacket = new char[MAX_PACKET_SIZE]; while (!stopNetworkReceiveThread) { - if (agentList.getAgentSocket()->receive(&senderAddress, incomingPacket, &bytesReceived)) { + if (agentList.getAgentSocket().receive(&senderAddress, incomingPacket, &bytesReceived)) { packetcount++; bytescount += bytesReceived; diff --git a/shared/src/AgentList.cpp b/shared/src/AgentList.cpp index fdf4e430ff..0a72c3065e 100644 --- a/shared/src/AgentList.cpp +++ b/shared/src/AgentList.cpp @@ -30,8 +30,12 @@ AgentList::~AgentList() { stopSilentAgentRemovalThread(); } -UDPSocket * AgentList::getAgentSocket() { - return &agentSocket; +std::vector& AgentList::getAgents() { + return agents; +} + +UDPSocket& AgentList::getAgentSocket() { + return agentSocket; } void AgentList::processAgentData(sockaddr *senderAddress, void *packetData, size_t dataBytes) { diff --git a/shared/src/AgentList.h b/shared/src/AgentList.h index 734d64da9e..2755058503 100644 --- a/shared/src/AgentList.h +++ b/shared/src/AgentList.h @@ -16,18 +16,19 @@ const unsigned short AGENT_SOCKET_LISTEN_PORT = 40103; const int AGENT_SILENCE_THRESHOLD_USECS = 2 * 1000000; -extern const char *SOLO_AGENT_TYPES_STRINGg; +extern const char *SOLO_AGENT_TYPES_STRING; class AgentList { public: AgentList(); AgentList(int socketListenPort); ~AgentList(); - std::vector agents; + void(*linkedDataCreateCallback)(Agent *); void(*audioMixerSocketUpdate)(in_addr_t, in_port_t); - - UDPSocket* getAgentSocket(); + + std::vector& getAgents(); + UDPSocket& getAgentSocket(); int updateList(unsigned char *packetData, size_t dataBytes); bool addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, char agentType); @@ -38,11 +39,13 @@ class AgentList { void startSilentAgentRemovalThread(); void stopSilentAgentRemovalThread(); private: + UDPSocket agentSocket; + std::vector agents; + pthread_t removeSilentAgentsThread; + int indexOfMatchingAgent(sockaddr *senderAddress); void updateAgentWithData(sockaddr *senderAddress, void *packetData, size_t dataBytes); void handlePingReply(sockaddr *agentAddress); - UDPSocket agentSocket; - pthread_t removeSilentAgentsThread; }; #endif /* defined(__hifi__AgentList__) */ From d211eb6c84f5def959cab898524312441399aecb Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 25 Feb 2013 12:51:52 -0800 Subject: [PATCH 06/85] use getters and setters for all member variables in AgentList and Agent --- domain/src/main.cpp | 22 ++++++------ interface/src/main.cpp | 10 +++--- shared/src/Agent.cpp | 75 ++++++++++++++++++++++++++++++++++++---- shared/src/Agent.h | 33 ++++++++++++------ shared/src/AgentList.cpp | 51 ++++++++++++--------------- 5 files changed, 129 insertions(+), 62 deletions(-) diff --git a/domain/src/main.cpp b/domain/src/main.cpp index 7dd89df557..424416ca6c 100644 --- a/domain/src/main.cpp +++ b/domain/src/main.cpp @@ -44,10 +44,10 @@ int lastActiveCount = 0; AgentList agentList(DOMAIN_LISTEN_PORT); unsigned char * addAgentToBroadcastPacket(unsigned char *currentPosition, Agent *agentToAdd) { - *currentPosition++ = agentToAdd->type; + *currentPosition++ = agentToAdd->getType(); - currentPosition += packSocket(currentPosition, agentToAdd->publicSocket); - currentPosition += packSocket(currentPosition, agentToAdd->localSocket); + currentPosition += packSocket(currentPosition, agentToAdd->getPublicSocket()); + currentPosition += packSocket(currentPosition, agentToAdd->getLocalSocket()); // return the new unsigned char * for broadcast packet return currentPosition; @@ -73,7 +73,7 @@ int main(int argc, const char * argv[]) std::map newestSoloAgents; while (true) { - if (agentList.getAgentSocket()->receive((sockaddr *)&agentPublicAddress, packetData, &receivedBytes)) { + if (agentList.getAgentSocket().receive((sockaddr *)&agentPublicAddress, packetData, &receivedBytes)) { agentType = packetData[0]; unpackSocket(&packetData[1], (sockaddr *)&agentLocalAddress); @@ -82,24 +82,24 @@ int main(int argc, const char * argv[]) currentBufferPos = broadcastPacket + 1; startPointer = currentBufferPos; - for(std::vector::iterator agent = agentList.agents.begin(); agent != agentList.agents.end(); agent++) { + for(std::vector::iterator agent = agentList.getAgents().begin(); agent != agentList.getAgents().end(); agent++) { if (DEBUG_TO_SELF || !agent->matches((sockaddr *)&agentPublicAddress, (sockaddr *)&agentLocalAddress, agentType)) { - if (strchr(SOLO_AGENT_TYPES_STRING, (int) agent->type) == NULL) { + if (strchr(SOLO_AGENT_TYPES_STRING, (int) agent->getType()) == NULL) { // this is an agent of which there can be multiple, just add them to the packet currentBufferPos = addAgentToBroadcastPacket(currentBufferPos, &(*agent)); } else { std::cout << "We have a solo agent: " << &(*agent) << "\n"; // solo agent, we need to only send newest - if (newestSoloAgents[agent->type] == NULL || - newestSoloAgents[agent->type]->firstRecvTimeUsecs < agent->firstRecvTimeUsecs) { + if (newestSoloAgents[agent->getType()] == NULL || + newestSoloAgents[agent->getType()]->getFirstRecvTimeUsecs() < agent->getFirstRecvTimeUsecs()) { // we have to set the newer solo agent to add it to the broadcast later - newestSoloAgents[agent->type] = &(*agent); + newestSoloAgents[agent->getType()] = &(*agent); } } } else { // this is the agent, just update last receive to now - agent->lastRecvTimeUsecs = usecTimestampNow(); + agent->setLastRecvTimeUsecs(usecTimestampNow()); } } @@ -112,7 +112,7 @@ int main(int argc, const char * argv[]) } if ((packetBytesWithoutLeadingChar = (currentBufferPos - startPointer))) { - agentList.getAgentSocket()->send((sockaddr *)&agentPublicAddress, broadcastPacket, packetBytesWithoutLeadingChar + 1); + agentList.getAgentSocket().send((sockaddr *)&agentPublicAddress, broadcastPacket, packetBytesWithoutLeadingChar + 1); } } } diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 9b3ad7a39f..6d19004bfe 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -571,8 +571,8 @@ void display(void) // Render heads of other agents for(std::vector::iterator agent = agentList.getAgents().begin(); agent != agentList.getAgents().end(); agent++) { - if (agent->linkedData != NULL) { - Head *agentHead = (Head *)agent->linkedData; + if (agent->getLinkedData() != NULL) { + Head *agentHead = (Head *)agent->getLinkedData(); glPushMatrix(); glm::vec3 pos = agentHead->getPos(); glTranslatef(-pos.x, -pos.y, -pos.z); @@ -583,7 +583,7 @@ void display(void) if (!display_head) balls.render(); - // Render the world box + // Render the world box if (!display_head && stats_on) render_world_box(); // Render my own head @@ -851,8 +851,8 @@ void mouseoverFunc( int x, int y) } void attachNewHeadToAgent(Agent *newAgent) { - if (newAgent->linkedData == NULL) { - newAgent->linkedData = new Head(); + if (newAgent->getLinkedData() == NULL) { + newAgent->setLinkedData(new Head()); } } diff --git a/shared/src/Agent.cpp b/shared/src/Agent.cpp index 5790329c80..a635314b64 100644 --- a/shared/src/Agent.cpp +++ b/shared/src/Agent.cpp @@ -58,6 +58,75 @@ Agent& Agent::operator=(Agent otherAgent) { return *this; } +Agent::~Agent() { + delete publicSocket; + delete localSocket; + delete linkedData; +} + +char Agent::getType() { + return type; +} + +void Agent::setType(char newType) { + type = newType; +} + +double Agent::getFirstRecvTimeUsecs() { + return firstRecvTimeUsecs; +} + +void Agent::setFirstRecvTimeUsecs(double newTimeUsecs) { + firstRecvTimeUsecs = newTimeUsecs; +} + +double Agent::getLastRecvTimeUsecs() { + return lastRecvTimeUsecs; +} + +void Agent::setLastRecvTimeUsecs(double newTimeUsecs) { + lastRecvTimeUsecs = newTimeUsecs; +} + +sockaddr* Agent::getPublicSocket() { + return publicSocket; +} + +void Agent::setPublicSocket(sockaddr *newSocket) { + publicSocket = newSocket; +} + +sockaddr* Agent::getLocalSocket() { + return localSocket; +} + +void Agent::setLocalSocket(sockaddr *newSocket) { + publicSocket = newSocket; +} + +sockaddr* Agent::getActiveSocket() { + return activeSocket; +} + +void Agent::activateLocalSocket() { + activeSocket = localSocket; +} + +void Agent::activatePublicSocket() { + activeSocket = publicSocket; +} + + + +AgentData* Agent::getLinkedData() { + return linkedData; +} + +void Agent::setLinkedData(AgentData *newData) { + linkedData = newData; +} + + bool Agent::operator==(const Agent& otherAgent) { return matches(otherAgent.publicSocket, otherAgent.localSocket, otherAgent.type); } @@ -71,12 +140,6 @@ void Agent::swap(Agent &first, Agent &second) { swap(first.linkedData, second.linkedData); } -Agent::~Agent() { - delete publicSocket; - delete localSocket; - delete linkedData; -} - bool Agent::matches(sockaddr *otherPublicSocket, sockaddr *otherLocalSocket, char otherAgentType) { // checks if two agent objects are the same agent (same type + local + public address) return type == otherAgentType diff --git a/shared/src/Agent.h b/shared/src/Agent.h index 90073a92b0..dafbeb768f 100644 --- a/shared/src/Agent.h +++ b/shared/src/Agent.h @@ -18,24 +18,35 @@ class Agent { Agent(); Agent(sockaddr *agentPublicSocket, sockaddr *agentLocalSocket, char agentType); Agent(const Agent &otherAgent); + ~Agent(); Agent& operator=(Agent otherAgent); bool operator==(const Agent& otherAgent); - ~Agent(); - + bool matches(sockaddr *otherPublicSocket, sockaddr *otherLocalSocket, char otherAgentType); - - sockaddr *publicSocket, *localSocket, *activeSocket; - char type; - timeval pingStarted; - int pingMsecs; - double firstRecvTimeUsecs; - double lastRecvTimeUsecs; - bool isSelf; - AgentData *linkedData; + char getType(); + void setType(char newType); + double getFirstRecvTimeUsecs(); + void setFirstRecvTimeUsecs(double newTimeUsecs); + double getLastRecvTimeUsecs(); + void setLastRecvTimeUsecs(double newTimeUsecs); + sockaddr* getPublicSocket(); + void setPublicSocket(sockaddr *newSocket); + sockaddr* getLocalSocket(); + void setLocalSocket(sockaddr *newSocket); + sockaddr* getActiveSocket(); + void activatePublicSocket(); + void activateLocalSocket(); + AgentData* getLinkedData(); + void setLinkedData(AgentData *newData); friend std::ostream& operator<<(std::ostream& os, const Agent* agent); private: void swap(Agent &first, Agent &second); + sockaddr *publicSocket, *localSocket, *activeSocket; + char type; + double firstRecvTimeUsecs; + double lastRecvTimeUsecs; + AgentData *linkedData; }; std::ostream& operator<<(std::ostream& os, const Agent* agent); diff --git a/shared/src/AgentList.cpp b/shared/src/AgentList.cpp index 0a72c3065e..d1c4db24ce 100644 --- a/shared/src/AgentList.cpp +++ b/shared/src/AgentList.cpp @@ -75,22 +75,22 @@ void AgentList::updateAgentWithData(sockaddr *senderAddress, void *packetData, s if (agentIndex != -1) { Agent *matchingAgent = &agents[agentIndex]; - matchingAgent->lastRecvTimeUsecs = usecTimestampNow(); + matchingAgent->setLastRecvTimeUsecs(usecTimestampNow()); - if (matchingAgent->linkedData == NULL) { + if (matchingAgent->getLinkedData() == NULL) { if (linkedDataCreateCallback != NULL) { linkedDataCreateCallback(matchingAgent); } } - matchingAgent->linkedData->parseData(packetData, dataBytes); + matchingAgent->getLinkedData()->parseData(packetData, dataBytes); } } int AgentList::indexOfMatchingAgent(sockaddr *senderAddress) { for(std::vector::iterator agent = agents.begin(); agent != agents.end(); agent++) { - if (agent->activeSocket != NULL && socketMatch(agent->activeSocket, senderAddress)) { + if (agent->getActiveSocket() != NULL && socketMatch(agent->getActiveSocket(), senderAddress)) { return agent - agents.begin(); } } @@ -140,10 +140,10 @@ bool AgentList::addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, if (socketMatch(publicSocket, localSocket)) { // likely debugging scenario with DS + agent on local network // set the agent active right away - newAgent.activeSocket = newAgent.localSocket; + newAgent.activatePublicSocket(); } - if (newAgent.type == 'M' && audioMixerSocketUpdate != NULL) { + if (newAgent.getType() == 'M' && audioMixerSocketUpdate != NULL) { // this is an audio mixer // for now that means we need to tell the audio class // to use the local socket information the domain server gave us @@ -160,10 +160,10 @@ bool AgentList::addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, return true; } else { - if (agent->type == 'M') { + if (agent->getType() == 'M') { // until the Audio class also uses our agentList, we need to update // the lastRecvTimeUsecs for the audio mixer so it doesn't get killed and re-added continously - agent->lastRecvTimeUsecs = usecTimestampNow(); + agent->setLastRecvTimeUsecs(usecTimestampNow()); } // we had this agent already, do nothing for now @@ -175,9 +175,9 @@ void AgentList::broadcastToAgents(char *broadcastData, size_t dataBytes) { for(std::vector::iterator agent = agents.begin(); agent != agents.end(); agent++) { // for now assume we only want to send to other interface clients // until the Audio class uses the AgentList - if (agent->activeSocket != NULL && agent->type == 'I') { + if (agent->getActiveSocket() != NULL && agent->getType() == 'I') { // we know which socket is good for this agent, send there - agentSocket.send(agent->activeSocket, broadcastData, dataBytes); + agentSocket.send(agent->getActiveSocket(), broadcastData, dataBytes); } } } @@ -186,15 +186,15 @@ void AgentList::pingAgents() { char payload[] = "P"; for(std::vector::iterator agent = agents.begin(); agent != agents.end(); agent++) { - if (agent->type == 'I') { - if (agent->activeSocket != NULL) { + if (agent->getType() == 'I') { + if (agent->getActiveSocket() != NULL) { // we know which socket is good for this agent, send there - agentSocket.send(agent->activeSocket, payload, 1); + agentSocket.send(agent->getActiveSocket(), payload, 1); } else { // ping both of the sockets for the agent so we can figure out // which socket we can use - agentSocket.send(agent->publicSocket, payload, 1); - agentSocket.send(agent->localSocket, payload, 1); + agentSocket.send(agent->getPublicSocket(), payload, 1); + agentSocket.send(agent->getLocalSocket(), payload, 1); } } } @@ -203,19 +203,12 @@ void AgentList::pingAgents() { void AgentList::handlePingReply(sockaddr *agentAddress) { for(std::vector::iterator agent = agents.begin(); agent != agents.end(); agent++) { // check both the public and local addresses for each agent to see if we find a match - // prioritize the private address so that we prune erroneous local matches - sockaddr *matchedSocket = NULL; - - if (socketMatch(agent->publicSocket, agentAddress)) { - matchedSocket = agent->publicSocket; - } else if (socketMatch(agent->localSocket, agentAddress)) { - matchedSocket = agent->localSocket; - } - - if (matchedSocket != NULL) { - // matched agent, stop checking - // update the agent's ping - agent->activeSocket = matchedSocket; + // prioritize the private address so that we prune erroneous local matches + if (socketMatch(agent->getPublicSocket(), agentAddress)) { + agent->activatePublicSocket(); + break; + } else if (socketMatch(agent->getLocalSocket(), agentAddress)) { + agent->activateLocalSocket(); break; } } @@ -229,7 +222,7 @@ void *removeSilentAgents(void *args) { checkTimeUSecs = usecTimestampNow(); for(std::vector::iterator agent = agents->begin(); agent != agents->end();) { - if ((checkTimeUSecs - agent->lastRecvTimeUsecs) > AGENT_SILENCE_THRESHOLD_USECS) { + if ((checkTimeUSecs - agent->getLastRecvTimeUsecs()) > AGENT_SILENCE_THRESHOLD_USECS) { std::cout << "Killing agent " << &(*agent) << "\n"; pthread_mutex_lock(&vectorChangeMutex); agent = agents->erase(agent); From b6d255477b115f77c4b885313e35714dd3a43c06 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 25 Feb 2013 13:06:36 -0800 Subject: [PATCH 07/85] remove extraneous logging for Domain server solo agents --- domain/src/main.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/domain/src/main.cpp b/domain/src/main.cpp index 424416ca6c..7b6f75ad3f 100644 --- a/domain/src/main.cpp +++ b/domain/src/main.cpp @@ -89,7 +89,6 @@ int main(int argc, const char * argv[]) // this is an agent of which there can be multiple, just add them to the packet currentBufferPos = addAgentToBroadcastPacket(currentBufferPos, &(*agent)); } else { - std::cout << "We have a solo agent: " << &(*agent) << "\n"; // solo agent, we need to only send newest if (newestSoloAgents[agent->getType()] == NULL || newestSoloAgents[agent->getType()]->getFirstRecvTimeUsecs() < agent->getFirstRecvTimeUsecs()) { @@ -106,7 +105,6 @@ int main(int argc, const char * argv[]) for (std::map::iterator agentIterator = newestSoloAgents.begin(); agentIterator != newestSoloAgents.end(); agentIterator++) { - std::cout << "Newest agent: " << agentIterator->second << "\n"; // this is the newest alive solo agent, add them to the packet currentBufferPos = addAgentToBroadcastPacket(currentBufferPos, agentIterator->second); } From a22cd3680a8b1b9146215f5eb069fd573f8c1d1f Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Mon, 25 Feb 2013 14:31:56 -0800 Subject: [PATCH 08/85] Added angular velocity and angular movement to hand, changed hand to block. --- interface/src/Hand.cpp | 57 ++++++++++++++++++++++++++++++++++++------ interface/src/Hand.h | 4 ++- 2 files changed, 52 insertions(+), 9 deletions(-) diff --git a/interface/src/Hand.cpp b/interface/src/Hand.cpp index 89209d309a..16698a74d1 100644 --- a/interface/src/Hand.cpp +++ b/interface/src/Hand.cpp @@ -24,14 +24,24 @@ Hand::Hand(glm::vec3 initcolor) scale.z = scale.y * 1.0; } +void Hand::addAngularVelocity (float pRate, float yRate, float rRate) { + pitchRate += pRate; + yawRate += yRate; + rollRate += rRate; +} + void Hand::render() { -// glPushMatrix(); -// glTranslatef(position.x, position.y, position.z); -// glColor3f(color.x, color.y, color.z); -// glScalef(scale.x, scale.y, scale.z); -// glutSolidSphere(1.5, 20, 20); -// glPopMatrix(); + glPushMatrix(); + glTranslatef(position.x, position.y, position.z); + glRotatef(yaw, 0, 1, 0); + glRotatef(pitch, 1, 0, 0); + glRotatef(roll, 0, 0, 1); + glColor3f(color.x, color.y, color.z); + glScalef(scale.x, scale.y, scale.z); + //glutSolidSphere(1.5, 20, 20); + glutSolidCube(1.0); + glPopMatrix(); } void Hand::reset() @@ -39,17 +49,48 @@ void Hand::reset() position.x = DEFAULT_X; position.y = DEFAULT_Y; position.z = DEFAULT_Z; + pitch = yaw = roll = 0; + pitchRate = yawRate = rollRate = 0; setTarget(position); velocity.x = velocity.y = velocity.z = 0; } void Hand::simulate(float deltaTime) { - // If noise, add wandering movement + const float VNOISE = 0.1; + const float RSPRING = 0.01; + const float RNOISE = 0.1; + + // If noise, add a bit of random velocity if (noise) { - position += noise * 0.1f * glm::vec3(randFloat() - 0.5, randFloat() - 0.5, randFloat() - 0.5); + glm::vec3 nVel(randFloat() - 0.5f, randFloat() - 0.5f, randFloat() - 0.5f); + nVel *= VNOISE; + addVelocity(nVel); + + addAngularVelocity(RNOISE*(randFloat() - 0.5f), + RNOISE*(randFloat() - 0.5f), + RNOISE*(randFloat() - 0.5f)); } + position += velocity*deltaTime; + + pitch += pitchRate; + yaw += yawRate; + roll += rollRate; + // Decay position of hand toward target position -= deltaTime*(position - target); + // Decay velocity + velocity *= 1.0 - deltaTime; + + // Decay Angular Velocity + pitchRate *= 1.0 - deltaTime; + yawRate *= 1.0 - deltaTime; + rollRate *= 1.0 - deltaTime; + + // Add spring effect to return hand rotation to zero + pitchRate -= pitch * RSPRING; + yawRate -= yaw * RSPRING; + rollRate -= roll * RSPRING; + } \ No newline at end of file diff --git a/interface/src/Hand.h b/interface/src/Hand.h index 9f64343673..01478839ee 100644 --- a/interface/src/Hand.h +++ b/interface/src/Hand.h @@ -23,12 +23,14 @@ public: void render (); void reset (); void setNoise (float mag) { noise = mag; }; - void addVel (glm::vec3 v) { velocity += v; }; + void addVelocity (glm::vec3 v) { velocity += v; }; + void addAngularVelocity (float pRate, float yRate, float rRate); glm::vec3 getPos() { return position; }; void setPos(glm::vec3 p) { position = p; }; void setTarget(glm::vec3 t) { target = t; }; private: glm::vec3 position, target, velocity, color, scale; + float pitch, yaw, roll, pitchRate, yawRate, rollRate; float noise; }; From f7b20a7c9c03b42147e16e50ebecc62316dc14b4 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Mon, 25 Feb 2013 15:06:28 -0800 Subject: [PATCH 09/85] Added ability to drag hand by clicking and dragging on the screen. --- interface/src/Hand.cpp | 12 +++++++++--- interface/src/Head.h | 4 +++- interface/src/main.cpp | 13 +++++++++++-- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/interface/src/Hand.cpp b/interface/src/Hand.cpp index 16698a74d1..dc6f73e456 100644 --- a/interface/src/Hand.cpp +++ b/interface/src/Hand.cpp @@ -57,9 +57,11 @@ void Hand::reset() void Hand::simulate(float deltaTime) { - const float VNOISE = 0.1; + const float VNOISE = 0.01; const float RSPRING = 0.01; + const float PSPRING = 0.4; const float RNOISE = 0.1; + const float VDECAY = 5.0; // If noise, add a bit of random velocity if (noise) { @@ -77,11 +79,15 @@ void Hand::simulate(float deltaTime) yaw += yawRate; roll += rollRate; + // Spring effect to return hand to target; + glm::vec3 sVel = target - position; + sVel *= PSPRING; + addVelocity(sVel); // Decay position of hand toward target - position -= deltaTime*(position - target); + //position -= deltaTime*(position - target); // Decay velocity - velocity *= 1.0 - deltaTime; + velocity *= 1.0 - deltaTime*VDECAY; // Decay Angular Velocity pitchRate *= 1.0 - deltaTime; diff --git a/interface/src/Head.h b/interface/src/Head.h index 038f37bfc5..8fc73c7e8c 100644 --- a/interface/src/Head.h +++ b/interface/src/Head.h @@ -60,6 +60,9 @@ class Head : public AgentData { void SetNewHeadTarget(float, float); glm::vec3 getPos() { return position; }; void setPos(glm::vec3 newpos) { position = newpos; }; + + Hand * hand; + private: float noise; float Pitch; @@ -99,7 +102,6 @@ class Head : public AgentData { void readSensors(); float renderYaw, renderPitch; // Pitch from view frustum when this is own head. - Hand * hand; }; #endif \ No newline at end of file diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 6d19004bfe..3ae6e4e411 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -144,14 +144,15 @@ int display_head_mouse = 1; // Display sample mouse pointer controlled int head_mouse_x, head_mouse_y; int head_lean_x, head_lean_y; -int mouse_x, mouse_y; // Where is the mouse +int mouse_x, mouse_y; // Where is the mouse +int mouse_start_x, mouse_start_y; // Mouse location at start of last down click int mouse_pressed = 0; // true if mouse has been pressed (clear when finished) int nearbyAgents = 0; // How many other people near you is the domain server reporting? int speed; -// +// // Serial USB Variables // @@ -813,6 +814,8 @@ void mouseFunc( int button, int state, int x, int y ) mouse_y = y; mouse_pressed = 1; lattice.mouseClick((float)x/(float)WIDTH,(float)y/(float)HEIGHT); + mouse_start_x = x; + mouse_start_y = y; } if( button == GLUT_LEFT_BUTTON && state == GLUT_UP ) { @@ -833,6 +836,12 @@ void motionFunc( int x, int y) char mouse_string[20]; sprintf(mouse_string, "M %d %d\n", mouse_x, mouse_y); //network_send(UDP_socket, mouse_string, strlen(mouse_string)); + + // Send dragged mouse vector to the hand; + float dx = mouse_x - mouse_start_x; + float dy = mouse_y - mouse_start_y; + glm::vec3 vel(dx*0.003, -dy*0.003, 0); + myHead.hand->addVelocity(vel); } lattice.mouseClick((float)x/(float)WIDTH,(float)y/(float)HEIGHT); From e2c3c253a8ed4ad9918ae92e47e85298d5942f13 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 25 Feb 2013 15:19:53 -0800 Subject: [PATCH 10/85] fix birarda's stupid bug in timestamp creation --- shared/src/SharedUtil.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 From abfd3a01685722fb41e63e578e1916b8d1e88613 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 25 Feb 2013 17:07:32 -0800 Subject: [PATCH 11/85] refactor mixer to use AgentList, AudioRingBuffer as AgentData --- interface/src/Audio.cpp | 53 +++---- interface/src/Head.cpp | 4 + interface/src/Head.h | 2 + mixer/src/main.cpp | 266 +++++++++++---------------------- shared/src/Agent.cpp | 9 +- shared/src/AgentData.h | 1 + shared/src/AgentList.h | 2 +- shared/src/AudioRingBuffer.cpp | 89 +++++++++-- shared/src/AudioRingBuffer.h | 36 ++++- shared/src/UDPSocket.cpp | 1 - 10 files changed, 222 insertions(+), 241 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index b433b2a199..27c2a33a0b 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,7 @@ 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); + data->audioSocket->send((sockaddr *)&audioMixerSocket, (void *)inputLeft, BUFFER_LENGTH_BYTES); } // @@ -134,27 +128,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 +198,6 @@ void *receiveAudioViaUDP(void *args) { while (!stopAudioReceiveThread) { if (sharedAudioData->audioSocket->receive((void *)receivedData, &receivedBytes)) { - bool firstSample = (currentReceiveTime.tv_sec == 0); gettimeofday(¤tReceiveTime, NULL); @@ -233,28 +226,24 @@ 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"; + if (ringBuffer->getEndOfLastWrite() == NULL) { + ringBuffer->setEndOfLastWrite(ringBuffer->getBuffer()); + } else if (ringBuffer->diffLastWriteNextOutput() > RING_BUFFER_SAMPLES - PACKET_LENGTH_SAMPLES) { // reset us to started state - ringBuffer->endOfLastWrite = ringBuffer->buffer; - ringBuffer->nextOutput = ringBuffer->buffer; - ringBuffer->started = false; + ringBuffer->setEndOfLastWrite(ringBuffer->getBuffer()); + ringBuffer->setNextOutput(ringBuffer->getBuffer()); + ringBuffer->setStarted(false); } - int16_t *copyToPointer = ringBuffer->endOfLastWrite; + int16_t *copyToPointer = ringBuffer->getEndOfLastWrite(); // 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; + ringBuffer->setEndOfLastWrite(ringBuffer->getEndOfLastWrite() + PACKET_LENGTH_SAMPLES); - if (ringBuffer->endOfLastWrite == ringBuffer->buffer + RING_BUFFER_SIZE_SAMPLES) { - ringBuffer->endOfLastWrite = ringBuffer->buffer; + if (ringBuffer->getEndOfLastWrite() == ringBuffer->getBuffer() + RING_BUFFER_SAMPLES) { + ringBuffer->setEndOfLastWrite(ringBuffer->getBuffer()); } if (LOG_SAMPLE_DELAY) { @@ -284,7 +273,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 +348,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/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 038f37bfc5..94714d97b0 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/mixer/src/main.cpp b/mixer/src/main.cpp index eb125e1831..379298b828 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -13,24 +13,21 @@ #include #include #include "AudioRingBuffer.h" -#include "UDPSocket.h" +#include +#include const int MAX_AGENTS = 1000; const int LOGOFF_CHECK_INTERVAL = 1000; 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(); @@ -40,190 +37,100 @@ 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; + int nextFrame = 0; + timeval startTime; int16_t *clientMix = new int16_t[BUFFER_LENGTH_SAMPLES]; long *masterMix = new long[BUFFER_LENGTH_SAMPLES]; - + gettimeofday(&startTime, NULL); while (true) { sentBytes = 0; - - for (int wb = 0; wb < BUFFER_LENGTH_SAMPLES; wb++) { - masterMix[wb] = 0; + + for (int ms = 0; ms < BUFFER_LENGTH_SAMPLES; ms++) { + masterMix[ms] = 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 ab = 0; ab < agentList.getAgents().size(); ab++) { + AudioRingBuffer *agentBuffer = (AudioRingBuffer *)agentList.getAgents()[ab].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", ab); + } else if (agentBuffer->diffLastWriteNextOutput() < BUFFER_LENGTH_SAMPLES) { + printf("Buffer %d starved.\n", ab); + agentBuffer->setStarted(false); + } else { + // good buffer, add this to the mix + agentBuffer->setStarted(true); + agentBuffer->setAddedToMix(true); + + for (int s = 0; s < BUFFER_LENGTH_SAMPLES; s++) { + masterMix[s] += agentBuffer->getNextOutput()[s]; + } + + agentBuffer->setNextOutput(agentBuffer->getNextOutput() + BUFFER_LENGTH_SAMPLES); + + if (agentBuffer->getNextOutput() >= agentBuffer->getBuffer() + RING_BUFFER_SAMPLES) { + agentBuffer->setNextOutput(agentBuffer->getBuffer()); + } } } - } - - gettimeofday(&now, NULL); + } - double usecToSleep = usecTimestamp(&startTime, (currentFrame * BUFFER_SEND_INTERVAL_USECS)) - usecTimestamp(&now); + for (int ab = 0; ab < agentList.getAgents().size(); ab++) { + Agent *agent = &agentList.getAgents()[ab]; + AudioRingBuffer *agentBuffer = (AudioRingBuffer *)agent->getLinkedData(); + int16_t *previousOutput = NULL; + + if (agentBuffer != NULL && agentBuffer->wasAddedToMix()) { + previousOutput = (agentBuffer->getNextOutput() == agentBuffer->getBuffer()) + ? agentBuffer->getBuffer() + RING_BUFFER_SAMPLES - BUFFER_LENGTH_SAMPLES + : agentBuffer->getNextOutput() - BUFFER_LENGTH_SAMPLES; + agentBuffer->setAddedToMix(false); + } + + for (int s = 0; s < BUFFER_LENGTH_SAMPLES; s++) { + long longSample = (previousOutput != NULL) + ? masterMix[s] - previousOutput[s] + : masterMix[s]; + + int16_t shortSample; + + if (longSample < 0) { + shortSample = std::max(longSample, MIN_SAMPLE_VALUE); + } else { + shortSample = std::min(longSample, MAX_SAMPLE_VALUE); + } + + clientMix[s] = shortSample; + } + + agentList.getAgentSocket().send(agent->getPublicSocket(), clientMix, BUFFER_LENGTH_BYTES); + } + + double usecToSleep = usecTimestamp(&startTime) + (++nextFrame * BUFFER_SEND_INTERVAL_USECS) - usecTimestampNow(); + 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) { @@ -231,11 +138,9 @@ void *reportAliveToDS(void *args) { *output = 'M'; packSocket(output + 1, 895283510, htons(MIXER_LISTEN_PORT)); - audioSocket.send(DOMAIN_IP, DOMAINSERVER_PORT, output, 7); + 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 +150,18 @@ 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; + // setup the agentSocket to report to domain server pthread_t reportAliveThread; pthread_create(&reportAliveThread, NULL, reportAliveToDS, NULL); @@ -270,25 +182,19 @@ 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); - } + int16_t *packetData = new int16_t[BUFFER_LENGTH_SAMPLES]; pthread_t sendBufferThread; pthread_create(&sendBufferThread, NULL, sendBuffer, NULL); + + sockaddr *agentAddress = new sockaddr; while (true) { - if(audioSocket.receive((sockaddr *)&agentAddress, packetData, &receivedBytes)) { + if(agentList.getAgentSocket().receive(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"; - } + // add or update the existing interface agent + agentList.addOrUpdateAgent(agentAddress, agentAddress, 'I'); + agentList.updateAgentWithData(agentAddress, (void *)packetData, receivedBytes); } } } 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..0741e63d7b 100644 --- a/shared/src/AgentList.h +++ b/shared/src/AgentList.h @@ -33,6 +33,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 +45,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..48b916588b 100644 --- a/shared/src/AudioRingBuffer.cpp +++ b/shared/src/AudioRingBuffer.cpp @@ -8,20 +8,90 @@ #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; +} + +void AudioRingBuffer::parseData(void *data, int size) { + int16_t *audioData = (int16_t *)data; + + if (endOfLastWrite == NULL) { + endOfLastWrite = buffer; + } else if (diffLastWriteNextOutput() > RING_BUFFER_SAMPLES - BUFFER_LENGTH_SAMPLES) { + endOfLastWrite = buffer; + nextOutput = buffer; + started = false; + } + + memcpy(endOfLastWrite, audioData, BUFFER_LENGTH_BYTES); + endOfLastWrite += BUFFER_LENGTH_SAMPLES; + + if (endOfLastWrite >= buffer + RING_BUFFER_SAMPLES) { + endOfLastWrite = buffer; + } +} + short AudioRingBuffer::diffLastWriteNextOutput() { if (endOfLastWrite == NULL) { @@ -30,20 +100,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..c8a656728d 100644 --- a/shared/src/AudioRingBuffer.h +++ b/shared/src/AudioRingBuffer.h @@ -11,20 +11,40 @@ #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); + + short diffLastWriteNextOutput(); + private: 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/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)); From bf94f1f861e2b3764efaa7d3d3d3d72a310e2a43 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 25 Feb 2013 17:13:44 -0800 Subject: [PATCH 12/85] refactor Audio.cpp in interface to use parseData in ARB --- interface/src/Audio.cpp | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 27c2a33a0b..6e9136b4b5 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -225,26 +225,7 @@ void *receiveAudioViaUDP(void *args) { } AudioRingBuffer *ringBuffer = sharedAudioData->ringBuffer; - - if (ringBuffer->getEndOfLastWrite() == NULL) { - ringBuffer->setEndOfLastWrite(ringBuffer->getBuffer()); - } else if (ringBuffer->diffLastWriteNextOutput() > RING_BUFFER_SAMPLES - PACKET_LENGTH_SAMPLES) { - - // reset us to started state - ringBuffer->setEndOfLastWrite(ringBuffer->getBuffer()); - ringBuffer->setNextOutput(ringBuffer->getBuffer()); - ringBuffer->setStarted(false); - } - - int16_t *copyToPointer = ringBuffer->getEndOfLastWrite(); - - // just copy the recieved data to the right spot and then add packet length to previous pointer - memcpy(copyToPointer, receivedData, PACKET_LENGTH_BYTES); - ringBuffer->setEndOfLastWrite(ringBuffer->getEndOfLastWrite() + PACKET_LENGTH_SAMPLES); - - if (ringBuffer->getEndOfLastWrite() == ringBuffer->getBuffer() + RING_BUFFER_SAMPLES) { - ringBuffer->setEndOfLastWrite(ringBuffer->getBuffer()); - } + ringBuffer->parseData(receivedData, PACKET_LENGTH_BYTES); if (LOG_SAMPLE_DELAY) { gettimeofday(&previousReceiveTime, NULL); From 26a87b3b436b2a560cb155669bc60ee2300a02da Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 26 Feb 2013 09:41:16 -0800 Subject: [PATCH 13/85] Added critically damped spring behavior to hand, and added simulateHand() routine to main.cpp that uses mouse to correctly move hand controller. --- interface/src/Hand.cpp | 19 ++++++++++--------- interface/src/main.cpp | 33 +++++++++++++++++---------------- 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/interface/src/Hand.cpp b/interface/src/Hand.cpp index dc6f73e456..9ba98c8e12 100644 --- a/interface/src/Hand.cpp +++ b/interface/src/Hand.cpp @@ -59,7 +59,8 @@ void Hand::simulate(float deltaTime) { const float VNOISE = 0.01; const float RSPRING = 0.01; - const float PSPRING = 0.4; + const float LINEAR_SPRING_CONSTANT = 500; + const float LINEAR_DAMPING_COEFFICIENT = 2.0*powf(LINEAR_SPRING_CONSTANT,0.5); const float RNOISE = 0.1; const float VDECAY = 5.0; @@ -79,15 +80,15 @@ void Hand::simulate(float deltaTime) yaw += yawRate; roll += rollRate; - // Spring effect to return hand to target; - glm::vec3 sVel = target - position; - sVel *= PSPRING; - addVelocity(sVel); - // Decay position of hand toward target - //position -= deltaTime*(position - target); + // Use a spring to attempt to return the hand to the target position + glm::vec3 springForce = target - position; + springForce *= LINEAR_SPRING_CONSTANT; + addVelocity(springForce * deltaTime); - // Decay velocity - velocity *= 1.0 - deltaTime*VDECAY; + // Critically damp the spring + glm::vec3 dampingForce(velocity); + dampingForce *= LINEAR_DAMPING_COEFFICIENT; + addVelocity(-dampingForce * deltaTime); // Decay Angular Velocity pitchRate *= 1.0 - deltaTime; diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 3ae6e4e411..e6901a2829 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -391,7 +391,20 @@ void reset_sensors() } } -void update_pos(float frametime) +void simulateHand(float deltaTime) { + // If mouse is being dragged, send current force to the hand controller + if (mouse_pressed == 1) + { + // Add a velocity to the hand corresponding to the detected size of the drag vector + const float MOUSE_HAND_FORCE = 3.0; + float dx = mouse_x - mouse_start_x; + float dy = mouse_y - mouse_start_y; + glm::vec3 vel(dx*MOUSE_HAND_FORCE, -dy*MOUSE_HAND_FORCE*(WIDTH/HEIGHT), 0); + myHead.hand->addVelocity(vel*deltaTime); + } +} + +void simulateHead(float frametime) // Using serial data, update avatar/render position and angles { // float measured_pitch_rate = serialPort.getRelativeValue(PITCH_RATE); @@ -766,7 +779,9 @@ void idle(void) { steps_per_frame++; // Simulation - update_pos(1.f/FPS); + simulateHead(1.f/FPS); + simulateHand(1.f/FPS); + if (simulate_on) { field.simulate(1.f/FPS); myHead.simulate(1.f/FPS); @@ -830,22 +845,8 @@ void motionFunc( int x, int y) { mouse_x = x; mouse_y = y; - if (mouse_pressed == 1) - { - // Send network packet containing mouse location - char mouse_string[20]; - sprintf(mouse_string, "M %d %d\n", mouse_x, mouse_y); - //network_send(UDP_socket, mouse_string, strlen(mouse_string)); - - // Send dragged mouse vector to the hand; - float dx = mouse_x - mouse_start_x; - float dy = mouse_y - mouse_start_y; - glm::vec3 vel(dx*0.003, -dy*0.003, 0); - myHead.hand->addVelocity(vel); - } lattice.mouseClick((float)x/(float)WIDTH,(float)y/(float)HEIGHT); - } void mouseoverFunc( int x, int y) From df1186660bd55d8a86ea750a868078ce488d4e9b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 26 Feb 2013 10:28:47 -0800 Subject: [PATCH 14/85] add missing cstring include for memcpy --- shared/src/AudioRingBuffer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/shared/src/AudioRingBuffer.cpp b/shared/src/AudioRingBuffer.cpp index 48b916588b..d234a405e3 100644 --- a/shared/src/AudioRingBuffer.cpp +++ b/shared/src/AudioRingBuffer.cpp @@ -6,6 +6,7 @@ // Copyright (c) 2013 HighFidelity, Inc. All rights reserved. // +#include #include "AudioRingBuffer.h" AudioRingBuffer::AudioRingBuffer() { From 1783ee5f85f193b75d73f48cf7bc03c920f880a6 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 26 Feb 2013 13:13:40 -0800 Subject: [PATCH 15/85] send interface client position to audio mixer --- domain/src/main.cpp | 2 -- interface/src/Audio.cpp | 24 +++++++++++++++++++++++- interface/src/Audio.h | 3 ++- interface/src/AudioData.h | 10 ++++++---- interface/src/main.cpp | 2 +- mixer/src/main.cpp | 11 +++-------- shared/src/AgentList.cpp | 2 +- shared/src/AgentList.h | 1 + shared/src/AudioRingBuffer.cpp | 16 ++++++++++++++-- shared/src/UDPSocket.h | 2 +- 10 files changed, 52 insertions(+), 21 deletions(-) diff --git a/domain/src/main.cpp b/domain/src/main.cpp index 7b6f75ad3f..9a8b6bc64f 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; diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 6e9136b4b5..4990e4f5de 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -84,7 +84,25 @@ 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 = new unsigned char[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); + + delete dataPacket; } // @@ -236,6 +254,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. 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/main.cpp b/interface/src/main.cpp index e6901a2829..c86d3c179d 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 379298b828..37093396ce 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -16,12 +16,8 @@ #include #include -const int MAX_AGENTS = 1000; -const int LOGOFF_CHECK_INTERVAL = 1000; - const unsigned short MIXER_LISTEN_PORT = 55443; - const float SAMPLE_RATE = 22050.0; const float BUFFER_SEND_INTERVAL_USECS = (BUFFER_LENGTH_SAMPLES/SAMPLE_RATE) * 1000000; @@ -35,7 +31,6 @@ 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 MAX_SOURCE_BUFFERS = 20; AgentList agentList(MIXER_LISTEN_PORT); @@ -182,7 +177,7 @@ int main(int argc, const char * argv[]) printf("Using static domainserver IP: %s\n", DOMAIN_IP); } - int16_t *packetData = new int16_t[BUFFER_LENGTH_SAMPLES]; + unsigned char *packetData = new unsigned char[MAX_PACKET_SIZE]; pthread_t sendBufferThread; pthread_create(&sendBufferThread, NULL, sendBuffer, NULL); @@ -191,9 +186,9 @@ int main(int argc, const char * argv[]) while (true) { if(agentList.getAgentSocket().receive(agentAddress, packetData, &receivedBytes)) { - if (receivedBytes == BUFFER_LENGTH_BYTES) { + if (receivedBytes > BUFFER_LENGTH_BYTES) { // add or update the existing interface agent - agentList.addOrUpdateAgent(agentAddress, agentAddress, 'I'); + agentList.addOrUpdateAgent(agentAddress, agentAddress, packetData[0]); agentList.updateAgentWithData(agentAddress, (void *)packetData, receivedBytes); } } diff --git a/shared/src/AgentList.cpp b/shared/src/AgentList.cpp index d1c4db24ce..fe280894ac 100644 --- a/shared/src/AgentList.cpp +++ b/shared/src/AgentList.cpp @@ -147,7 +147,7 @@ bool AgentList::addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, // this is an audio mixer // for now that means we need to tell the audio class // to use the local socket information the domain server gave us - sockaddr_in *localSocketIn = (sockaddr_in *)localSocket; + sockaddr_in *localSocketIn = (sockaddr_in *)publicSocket; audioMixerSocketUpdate(localSocketIn->sin_addr.s_addr, localSocketIn->sin_port); } diff --git a/shared/src/AgentList.h b/shared/src/AgentList.h index 0741e63d7b..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; diff --git a/shared/src/AudioRingBuffer.cpp b/shared/src/AudioRingBuffer.cpp index d234a405e3..e20860a7bf 100644 --- a/shared/src/AudioRingBuffer.cpp +++ b/shared/src/AudioRingBuffer.cpp @@ -75,8 +75,20 @@ void AudioRingBuffer::setAddedToMix(bool added) { } void AudioRingBuffer::parseData(void *data, int size) { - int16_t *audioData = (int16_t *)data; + int16_t *audioDataStart = (int16_t *) data; + if (size > BUFFER_LENGTH_BYTES) { + float position[3]; + unsigned char *charData = (unsigned char *) data; + + for (int p = 0; p < 3; p ++) { + memcpy(&position[p], charData + 1 + (sizeof(float) * p), sizeof(float)); + } + + audioDataStart = (int16_t *) charData + 1 + (sizeof(float) * 3); + } + + if (endOfLastWrite == NULL) { endOfLastWrite = buffer; } else if (diffLastWriteNextOutput() > RING_BUFFER_SAMPLES - BUFFER_LENGTH_SAMPLES) { @@ -85,7 +97,7 @@ void AudioRingBuffer::parseData(void *data, int size) { started = false; } - memcpy(endOfLastWrite, audioData, BUFFER_LENGTH_BYTES); + memcpy(endOfLastWrite, audioDataStart, BUFFER_LENGTH_BYTES); endOfLastWrite += BUFFER_LENGTH_SAMPLES; if (endOfLastWrite >= buffer + RING_BUFFER_SAMPLES) { 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: From c6458308094d16ad3d5f0e6c9f2a4f9d815d58b6 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 26 Feb 2013 13:43:50 -0800 Subject: [PATCH 16/85] temporary test against birarda's domain server --- interface/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index c86d3c179d..a408bb5db1 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -54,7 +54,7 @@ int simulate_on = 1; // char DOMAIN_HOSTNAME[] = "highfidelity.below92.com"; -char DOMAIN_IP[100] = ""; // IP Address will be used first if not empty string +char DOMAIN_IP[100] = "192.168.1.47"; // IP Address will be used first if not empty string const int DOMAINSERVER_PORT = 40102; AgentList agentList; From c123990d7ae48c2d5b79d0bfc0f6ced480429ef4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 26 Feb 2013 13:59:33 -0800 Subject: [PATCH 17/85] switch back to EC2 DS for sanity check --- interface/src/main.cpp | 2 +- shared/src/AgentList.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index a408bb5db1..c86d3c179d 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -54,7 +54,7 @@ int simulate_on = 1; // char DOMAIN_HOSTNAME[] = "highfidelity.below92.com"; -char DOMAIN_IP[100] = "192.168.1.47"; // IP Address will be used first if not empty string +char DOMAIN_IP[100] = ""; // IP Address will be used first if not empty string const int DOMAINSERVER_PORT = 40102; AgentList agentList; diff --git a/shared/src/AgentList.cpp b/shared/src/AgentList.cpp index fe280894ac..d1c4db24ce 100644 --- a/shared/src/AgentList.cpp +++ b/shared/src/AgentList.cpp @@ -147,7 +147,7 @@ bool AgentList::addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, // this is an audio mixer // for now that means we need to tell the audio class // to use the local socket information the domain server gave us - sockaddr_in *localSocketIn = (sockaddr_in *)publicSocket; + sockaddr_in *localSocketIn = (sockaddr_in *)localSocket; audioMixerSocketUpdate(localSocketIn->sin_addr.s_addr, localSocketIn->sin_port); } From 971f5b6ad60d51f3be35f09b7280ed6372944624 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 26 Feb 2013 16:55:39 -0800 Subject: [PATCH 18/85] recreate the newestSoloAgents map for each broadcastPacket --- domain/src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/domain/src/main.cpp b/domain/src/main.cpp index 9a8b6bc64f..81b2ccc7d9 100644 --- a/domain/src/main.cpp +++ b/domain/src/main.cpp @@ -68,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); From 31a164fd19bc7a468d2102eb70151e8db804d281 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 26 Feb 2013 16:57:33 -0800 Subject: [PATCH 19/85] initial changing of volumne of source based on distance --- interface/src/Audio.cpp | 4 +- mixer/src/main.cpp | 94 ++++++++++++++++------------------ shared/src/AudioRingBuffer.cpp | 22 +++++--- shared/src/AudioRingBuffer.h | 3 ++ 4 files changed, 64 insertions(+), 59 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 4990e4f5de..74f6d51e7c 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -88,7 +88,7 @@ int audioCallback (const void *inputBuffer, 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 = new unsigned char[BUFFER_LENGTH_BYTES + leadingBytes]; + unsigned char dataPacket[BUFFER_LENGTH_BYTES + leadingBytes]; dataPacket[0] = 'I'; @@ -101,8 +101,6 @@ int audioCallback (const void *inputBuffer, memcpy(dataPacket + leadingBytes, inputLeft, BUFFER_LENGTH_BYTES); data->audioSocket->send((sockaddr *)&audioMixerSocket, dataPacket, BUFFER_LENGTH_BYTES + leadingBytes); - - delete dataPacket; } // diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index 37093396ce..1e9f665df7 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -27,10 +27,11 @@ const short JITTER_BUFFER_SAMPLES = JITTER_BUFFER_MSECS * (SAMPLE_RATE / 1000.0) 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; AgentList agentList(MIXER_LISTEN_PORT); @@ -39,78 +40,70 @@ void *sendBuffer(void *args) int sentBytes; int nextFrame = 0; timeval startTime; - - int16_t *clientMix = new int16_t[BUFFER_LENGTH_SAMPLES]; - long *masterMix = new long[BUFFER_LENGTH_SAMPLES]; gettimeofday(&startTime, NULL); while (true) { sentBytes = 0; - for (int ms = 0; ms < BUFFER_LENGTH_SAMPLES; ms++) { - masterMix[ms] = 0; - } - - for (int ab = 0; ab < agentList.getAgents().size(); ab++) { - AudioRingBuffer *agentBuffer = (AudioRingBuffer *)agentList.getAgents()[ab].getLinkedData(); + for (int i = 0; i < agentList.getAgents().size(); i++) { + AudioRingBuffer *agentBuffer = (AudioRingBuffer *) agentList.getAgents()[i].getLinkedData(); if (agentBuffer != NULL && agentBuffer->getEndOfLastWrite() != NULL) { + if (!agentBuffer->isStarted() && agentBuffer->diffLastWriteNextOutput() <= BUFFER_LENGTH_SAMPLES + JITTER_BUFFER_SAMPLES) { - printf("Held back buffer %d.\n", ab); + printf("Held back buffer %d.\n", i); } else if (agentBuffer->diffLastWriteNextOutput() < BUFFER_LENGTH_SAMPLES) { - printf("Buffer %d starved.\n", ab); + 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 s = 0; s < BUFFER_LENGTH_SAMPLES; s++) { - masterMix[s] += agentBuffer->getNextOutput()[s]; - } - - agentBuffer->setNextOutput(agentBuffer->getNextOutput() + BUFFER_LENGTH_SAMPLES); - - if (agentBuffer->getNextOutput() >= agentBuffer->getBuffer() + RING_BUFFER_SAMPLES) { - agentBuffer->setNextOutput(agentBuffer->getBuffer()); - } } + } } - - for (int ab = 0; ab < agentList.getAgents().size(); ab++) { - Agent *agent = &agentList.getAgents()[ab]; - AudioRingBuffer *agentBuffer = (AudioRingBuffer *)agent->getLinkedData(); - int16_t *previousOutput = NULL; - - if (agentBuffer != NULL && agentBuffer->wasAddedToMix()) { - previousOutput = (agentBuffer->getNextOutput() == agentBuffer->getBuffer()) - ? agentBuffer->getBuffer() + RING_BUFFER_SAMPLES - BUFFER_LENGTH_SAMPLES - : agentBuffer->getNextOutput() - BUFFER_LENGTH_SAMPLES; - agentBuffer->setAddedToMix(false); - } - - for (int s = 0; s < BUFFER_LENGTH_SAMPLES; s++) { - long longSample = (previousOutput != NULL) - ? masterMix[s] - previousOutput[s] - : masterMix[s]; + for (int i = 0; i < agentList.getAgents().size(); i++) { + Agent *agent = &agentList.getAgents()[i]; - int16_t shortSample; - - if (longSample < 0) { - shortSample = std::max(longSample, MIN_SAMPLE_VALUE); - } else { - shortSample = std::min(longSample, MAX_SAMPLE_VALUE); + 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 = 1 / (log(DISTANCE_RATIO * distanceToAgent) / log(3)); + + for (int s = 0; s < BUFFER_LENGTH_SAMPLES; s++) { + int16_t sample = (otherAgentBuffer->getNextOutput()[s] * distanceCoeff); + clientMix[s] += sample; + } } - - clientMix[s] = shortSample; } 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(); if (usecToSleep > 0) { @@ -132,7 +125,8 @@ void *reportAliveToDS(void *args) { gettimeofday(&lastSend, NULL); *output = 'M'; - packSocket(output + 1, 895283510, htons(MIXER_LISTEN_PORT)); +// 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); double usecToSleep = 1000000 - (usecTimestampNow() - usecTimestamp(&lastSend)); @@ -186,7 +180,7 @@ int main(int argc, const char * argv[]) while (true) { if(agentList.getAgentSocket().receive(agentAddress, packetData, &receivedBytes)) { - if (receivedBytes > BUFFER_LENGTH_BYTES) { + if (receivedBytes >= BUFFER_LENGTH_BYTES) { // add or update the existing interface agent agentList.addOrUpdateAgent(agentAddress, agentAddress, packetData[0]); agentList.updateAgentWithData(agentAddress, (void *)packetData, receivedBytes); diff --git a/shared/src/AudioRingBuffer.cpp b/shared/src/AudioRingBuffer.cpp index e20860a7bf..15743b7d19 100644 --- a/shared/src/AudioRingBuffer.cpp +++ b/shared/src/AudioRingBuffer.cpp @@ -74,20 +74,27 @@ 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) { - int16_t *audioDataStart = (int16_t *) data; + unsigned char *audioDataStart = (unsigned char *) data; if (size > BUFFER_LENGTH_BYTES) { - float position[3]; - unsigned char *charData = (unsigned char *) data; for (int p = 0; p < 3; p ++) { - memcpy(&position[p], charData + 1 + (sizeof(float) * p), sizeof(float)); + memcpy(&position[p], audioDataStart + 1 + (sizeof(float) * p), sizeof(float)); } - audioDataStart = (int16_t *) charData + 1 + (sizeof(float) * 3); + audioDataStart += (1 + (sizeof(float) * 3)); } - if (endOfLastWrite == NULL) { endOfLastWrite = buffer; @@ -98,8 +105,11 @@ void AudioRingBuffer::parseData(void *data, int size) { } memcpy(endOfLastWrite, audioDataStart, BUFFER_LENGTH_BYTES); + endOfLastWrite += BUFFER_LENGTH_SAMPLES; + addedToMix = false; + if (endOfLastWrite >= buffer + RING_BUFFER_SAMPLES) { endOfLastWrite = buffer; } diff --git a/shared/src/AudioRingBuffer.h b/shared/src/AudioRingBuffer.h index c8a656728d..f9c3f5e136 100644 --- a/shared/src/AudioRingBuffer.h +++ b/shared/src/AudioRingBuffer.h @@ -37,9 +37,12 @@ class AudioRingBuffer : public AgentData { 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; From c1d66e4026a436aff20575a1e94a2b9d1b61d24c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 26 Feb 2013 17:04:57 -0800 Subject: [PATCH 20/85] have mixer kill off silent agents --- mixer/src/main.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index 1e9f665df7..e008a4709f 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -151,6 +151,8 @@ int main(int argc, const char * argv[]) agentList.linkedDataCreateCallback = attachNewBufferToAgent; + agentList.startSilentAgentRemovalThread(); + // setup the agentSocket to report to domain server pthread_t reportAliveThread; pthread_create(&reportAliveThread, NULL, reportAliveToDS, NULL); @@ -188,6 +190,7 @@ int main(int argc, const char * argv[]) } } + agentList.stopSilentAgentRemovalThread(); pthread_join(reportAliveThread, NULL); pthread_join(sendBufferThread, NULL); From ba2b79b0785deba77fb48aa88061caee38574f7c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 26 Feb 2013 17:12:41 -0800 Subject: [PATCH 21/85] accentuate the distance dampening by squaring the coefficient --- mixer/src/main.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index e008a4709f..85313b6a6e 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -76,13 +76,15 @@ void *sendBuffer(void *args) 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 = 1 / (log(DISTANCE_RATIO * distanceToAgent) / log(3)); + + 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); + int16_t sample = (otherAgentBuffer->getNextOutput()[s] / distanceCoeff); clientMix[s] += sample; } } From fe2f2d501952b3de7c08790725584fd1ef028370 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 26 Feb 2013 17:33:40 -0800 Subject: [PATCH 22/85] Reduce mouse force on hand. --- interface/src/Hand.cpp | 1 - interface/src/main.cpp | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/Hand.cpp b/interface/src/Hand.cpp index 9ba98c8e12..157f0ee38e 100644 --- a/interface/src/Hand.cpp +++ b/interface/src/Hand.cpp @@ -62,7 +62,6 @@ void Hand::simulate(float deltaTime) const float LINEAR_SPRING_CONSTANT = 500; const float LINEAR_DAMPING_COEFFICIENT = 2.0*powf(LINEAR_SPRING_CONSTANT,0.5); const float RNOISE = 0.1; - const float VDECAY = 5.0; // If noise, add a bit of random velocity if (noise) { diff --git a/interface/src/main.cpp b/interface/src/main.cpp index e6901a2829..5f372e5065 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -396,7 +396,7 @@ void simulateHand(float deltaTime) { if (mouse_pressed == 1) { // Add a velocity to the hand corresponding to the detected size of the drag vector - const float MOUSE_HAND_FORCE = 3.0; + const float MOUSE_HAND_FORCE = 1.5; float dx = mouse_x - mouse_start_x; float dy = mouse_y - mouse_start_y; glm::vec3 vel(dx*MOUSE_HAND_FORCE, -dy*MOUSE_HAND_FORCE*(WIDTH/HEIGHT), 0); From 75aaa59f7648b0e078604d4974ea8ae16b82f8cd Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 26 Feb 2013 17:35:26 -0800 Subject: [PATCH 23/85] send the correct mixer IP again --- mixer/src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index 85313b6a6e..af39a0a4a2 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -127,8 +127,8 @@ void *reportAliveToDS(void *args) { gettimeofday(&lastSend, NULL); *output = 'M'; -// packSocket(output + 1, 895283510, htons(MIXER_LISTEN_PORT)); - packSocket(output + 1, 788637888, htons(MIXER_LISTEN_PORT)); + 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); double usecToSleep = 1000000 - (usecTimestampNow() - usecTimestamp(&lastSend)); From 1dd3a9970dee2f6c5b11ee7d35c13c9d736225ff Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 26 Feb 2013 18:44:42 -0800 Subject: [PATCH 24/85] Eyebrows driven by audio, mouth doesn't turn red. --- interface/src/Head.cpp | 27 +++++++++++++++++++++------ interface/src/Head.h | 6 ++++-- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index 6930d7a77a..1e5b3c4203 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -36,9 +36,9 @@ Head::Head() interBrowDistance = 0.75; NominalPupilSize = 0.10; Yaw = 0.0; - EyebrowPitch[0] = EyebrowPitch[1] = BrowPitchAngle[0]; - EyebrowRoll[0] = 30; - EyebrowRoll[1] = -30; + EyebrowPitch[0] = EyebrowPitch[1] = -30; + EyebrowRoll[0] = 20; + EyebrowRoll[1] = -20; MouthPitch = 0; MouthYaw = 0; MouthWidth = 1.0; @@ -56,6 +56,12 @@ Head::Head() scale = 1.0; renderYaw = 0.0; renderPitch = 0.0; + audioAttack = 0.0; + loudness = 0.0; + averageLoudness = 0.0; + lastLoudness = 0.0; + browAudioLift = 0.0; + setNoise(0); hand = new Hand(glm::vec3(skinColor[0], skinColor[1], skinColor[2])); } @@ -284,13 +290,22 @@ void Head::render(int faceToFace, float * myLocation) // Eyebrows + audioAttack = 0.9*audioAttack + 0.1*fabs(loudness - lastLoudness); + lastLoudness = loudness; + + const float BROW_LIFT_THRESHOLD = 100; + if (audioAttack > BROW_LIFT_THRESHOLD) + browAudioLift += sqrt(audioAttack)/1000.0; + + browAudioLift *= .90; + glPushMatrix(); glTranslatef(-interBrowDistance/2.0,0.4,0.45); for(side = 0; side < 2; side++) { glColor3fv(browColor); glPushMatrix(); - glTranslatef(0, 0.4, 0); + glTranslatef(0, 0.35 + browAudioLift, 0); glRotatef(EyebrowPitch[side]/2.0, 1, 0, 0); glRotatef(EyebrowRoll[side]/2.0, 0, 0, 1); glScalef(browWidth, browThickness, 1); @@ -305,10 +320,10 @@ void Head::render(int faceToFace, float * myLocation) glPushMatrix(); glTranslatef(0,-0.35,0.75); - glColor3f(loudness/1000.0,0,0); + glColor3f(0,0,0); glRotatef(MouthPitch, 1, 0, 0); glRotatef(MouthYaw, 0, 0, 1); - glScalef(MouthWidth*(.7 + sqrt(averageLoudness)/60.0), MouthHeight*(1.0 + sqrt(averageLoudness)/60.0), 1); + glScalef(MouthWidth*(.7 + sqrt(averageLoudness)/60.0), MouthHeight*(1.0 + sqrt(averageLoudness)/30.0), 1); glutSolidCube(0.5); glPopMatrix(); diff --git a/interface/src/Head.h b/interface/src/Head.h index b554d4541e..a6aaec725c 100644 --- a/interface/src/Head.h +++ b/interface/src/Head.h @@ -95,9 +95,11 @@ class Head : public AgentData { float scale; // Sound loudness information - float loudness; + float loudness, lastLoudness; float averageLoudness; - + float audioAttack; + float browAudioLift; + glm::vec3 position; int eyeContact; eyeContactTargets eyeContactTarget; From a9050e6dc5c04efe2b2731ac5370dcf3554b839c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 27 Feb 2013 14:45:14 -0800 Subject: [PATCH 25/85] read from magnetometer on SDA, SLC --- hardware/head_hand/head_hand.pde | 50 ++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/hardware/head_hand/head_hand.pde b/hardware/head_hand/head_hand.pde index 844f352e56..920f1428ef 100644 --- a/hardware/head_hand/head_hand.pde +++ b/hardware/head_hand/head_hand.pde @@ -5,6 +5,8 @@ // // PIN WIRING: Connect input sensors to the channels in following manner // +// SDA: Magnetomer SDA +// SDL: Magnetomer SDL // AIN 10: Yaw Gyro (shaking your head 'no') // AIN 16: Pitch Gyro (nodding your head 'yes') // AIN 17: Roll Gyro (looking quizzical, tilting your head) @@ -12,11 +14,16 @@ // AIN 19: Up/Down acceleration (sitting up/ducking in front of your monitor) // AIN 20: Forward/Back acceleration (Toward or away from your monitor) +// include HardWire for I2C communication to Magnetomer +#include + #define NUM_CHANNELS 6 #define MSECS_PER_SAMPLE 10 #define LED_PIN 12 +const int COMPASS_ADDRESS = 0x42 >> 1; + int inputPins[NUM_CHANNELS] = {10,16,17,18,19,20}; int LED = 0; @@ -26,8 +33,12 @@ unsigned int time; int measured[NUM_CHANNELS]; float accumulate[NUM_CHANNELS]; +bool readFromMag = false; + int sampleCount = 0; +HardWire Wire(1, I2C_FAST_MODE); + void setup() { int i; @@ -36,6 +47,7 @@ void setup() measured[i] = analogRead(inputPins[i]); accumulate[i] = measured[i]; } + Wire.begin(); pinMode(BOARD_LED_PIN, OUTPUT); pinMode(LED_PIN,OUTPUT); time = millis(); @@ -44,11 +56,22 @@ void setup() void loop() { int i; + int compassReading; + bool magTransmit = false; sampleCount++; for (i = 0; i < NUM_CHANNELS; i++) { accumulate[i] += analogRead(inputPins[i]); } + + if (readFromMag && magTransmit == false) { + // get current absolute magnetometer value + Wire.beginTransmission(COMPASS_ADDRESS); + Wire.send('A'); + Wire.endTransmission(); + magTransmit = true; + } + if ((millis() - time) >= MSECS_PER_SAMPLE) { samplesSent++; time = millis(); @@ -58,7 +81,7 @@ void loop() SerialUSB.print(" "); accumulate[i] = 0; } - + if ((samplesSent % 100 == 0) && (samplesSent % 150 == 0)) { LED = !LED; digitalWrite(LED_PIN, LED); @@ -72,10 +95,25 @@ void loop() else SerialUSB.print("0"); - SerialUSB.println(""); + SerialUSB.print(" "); sampleCount = 0; + + if (readFromMag) { + // send the absolute value from the magnetomer + Wire.requestFrom(COMPASS_ADDRESS, 2); + + if (2 <= Wire.available()) { + compassReading = Wire.receive(); + compassReading = compassReading << 8; + compassReading += Wire.receive(); + compassReading /= 10; + SerialUSB.print(compassReading); + } + } + + SerialUSB.println(""); + + // reset the magnetomerTransmit to false to prep it in next loop + magTransmit = false; } -} - - - +} \ No newline at end of file From 5978b50912425b2ef8a2d660059aa4538fa52431 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 27 Feb 2013 14:45:52 -0800 Subject: [PATCH 26/85] Revert "read from magnetometer on SDA, SLC" This reverts commit a9050e6dc5c04efe2b2731ac5370dcf3554b839c. --- hardware/head_hand/head_hand.pde | 50 ++++---------------------------- 1 file changed, 6 insertions(+), 44 deletions(-) diff --git a/hardware/head_hand/head_hand.pde b/hardware/head_hand/head_hand.pde index 920f1428ef..844f352e56 100644 --- a/hardware/head_hand/head_hand.pde +++ b/hardware/head_hand/head_hand.pde @@ -5,8 +5,6 @@ // // PIN WIRING: Connect input sensors to the channels in following manner // -// SDA: Magnetomer SDA -// SDL: Magnetomer SDL // AIN 10: Yaw Gyro (shaking your head 'no') // AIN 16: Pitch Gyro (nodding your head 'yes') // AIN 17: Roll Gyro (looking quizzical, tilting your head) @@ -14,16 +12,11 @@ // AIN 19: Up/Down acceleration (sitting up/ducking in front of your monitor) // AIN 20: Forward/Back acceleration (Toward or away from your monitor) -// include HardWire for I2C communication to Magnetomer -#include - #define NUM_CHANNELS 6 #define MSECS_PER_SAMPLE 10 #define LED_PIN 12 -const int COMPASS_ADDRESS = 0x42 >> 1; - int inputPins[NUM_CHANNELS] = {10,16,17,18,19,20}; int LED = 0; @@ -33,12 +26,8 @@ unsigned int time; int measured[NUM_CHANNELS]; float accumulate[NUM_CHANNELS]; -bool readFromMag = false; - int sampleCount = 0; -HardWire Wire(1, I2C_FAST_MODE); - void setup() { int i; @@ -47,7 +36,6 @@ void setup() measured[i] = analogRead(inputPins[i]); accumulate[i] = measured[i]; } - Wire.begin(); pinMode(BOARD_LED_PIN, OUTPUT); pinMode(LED_PIN,OUTPUT); time = millis(); @@ -56,22 +44,11 @@ void setup() void loop() { int i; - int compassReading; - bool magTransmit = false; sampleCount++; for (i = 0; i < NUM_CHANNELS; i++) { accumulate[i] += analogRead(inputPins[i]); } - - if (readFromMag && magTransmit == false) { - // get current absolute magnetometer value - Wire.beginTransmission(COMPASS_ADDRESS); - Wire.send('A'); - Wire.endTransmission(); - magTransmit = true; - } - if ((millis() - time) >= MSECS_PER_SAMPLE) { samplesSent++; time = millis(); @@ -81,7 +58,7 @@ void loop() SerialUSB.print(" "); accumulate[i] = 0; } - + if ((samplesSent % 100 == 0) && (samplesSent % 150 == 0)) { LED = !LED; digitalWrite(LED_PIN, LED); @@ -95,25 +72,10 @@ void loop() else SerialUSB.print("0"); - SerialUSB.print(" "); - sampleCount = 0; - - if (readFromMag) { - // send the absolute value from the magnetomer - Wire.requestFrom(COMPASS_ADDRESS, 2); - - if (2 <= Wire.available()) { - compassReading = Wire.receive(); - compassReading = compassReading << 8; - compassReading += Wire.receive(); - compassReading /= 10; - SerialUSB.print(compassReading); - } - } - SerialUSB.println(""); - - // reset the magnetomerTransmit to false to prep it in next loop - magTransmit = false; + sampleCount = 0; } -} \ No newline at end of file +} + + + From 29df6e6a3eaee61d9534dad9162516c1ca60cd8b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 28 Feb 2013 12:21:38 -0800 Subject: [PATCH 27/85] send 256 samples per callback so mixer can reply with two channels --- interface/src/Audio.cpp | 58 +++++++++++++++------------------- interface/src/AudioData.cpp | 4 +-- interface/src/AudioData.h | 2 +- interface/src/main.cpp | 2 +- mixer/src/main.cpp | 48 +++++++++++++++++----------- shared/src/AudioRingBuffer.cpp | 25 +++++++++------ shared/src/AudioRingBuffer.h | 10 ++---- 7 files changed, 76 insertions(+), 73 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 74f6d51e7c..45d57873df 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -18,8 +18,16 @@ Oscilloscope * scope; -const short PACKET_LENGTH_BYTES = 1024; -const short PACKET_LENGTH_SAMPLES = PACKET_LENGTH_BYTES / sizeof(int16_t); +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); +const int PACKET_LENGTH_SAMPLES_PER_CHANNEL = PACKET_LENGTH_SAMPLES / 2; + +const int BUFFER_LENGTH_BYTES = 512; +const int BUFFER_LENGTH_SAMPLES = BUFFER_LENGTH_BYTES / sizeof(int16_t); + +const int RING_BUFFER_FRAMES = 10; +const int RING_BUFFER_SAMPLES = RING_BUFFER_FRAMES * BUFFER_LENGTH_SAMPLES; const int PHASE_DELAY_AT_90 = 20; const float AMPLITUDE_RATIO_AT_90 = 0.5; @@ -97,7 +105,7 @@ int audioCallback (const void *inputBuffer, memcpy(dataPacket + 1 + (p * sizeof(float)), &data->sourcePosition[p], sizeof(float)); } - // copy the audio data to the last 1024 bytes of the data packet + // copy the audio data to the last BUFFER_LENGTH_BYTES bytes of the data packet memcpy(dataPacket + leadingBytes, inputLeft, BUFFER_LENGTH_BYTES); data->audioSocket->send((sockaddr *)&audioMixerSocket, dataPacket, BUFFER_LENGTH_BYTES + leadingBytes); @@ -126,21 +134,11 @@ int audioCallback (const void *inputBuffer, int16_t *outputLeft = ((int16_t **) outputBuffer)[0]; int16_t *outputRight = ((int16_t **) outputBuffer)[1]; - memset(outputLeft, 0, BUFFER_LENGTH_BYTES); - memset(outputRight, 0, BUFFER_LENGTH_BYTES); - - // Copy output data to oscilloscope - if (scope->getState()) { - for (int i = 0; i < BUFFER_LENGTH_SAMPLES; i++) { - scope->addData((float)outputRight[i]/32767.0, 2, i); - } - } + memset(outputLeft, 0, PACKET_LENGTH_BYTES_PER_CHANNEL); + memset(outputRight, 0, PACKET_LENGTH_BYTES_PER_CHANNEL); AudioRingBuffer *ringBuffer = data->ringBuffer; - int16_t *queueBuffer = data->samplesToQueue; - memset(queueBuffer, 0, BUFFER_LENGTH_BYTES); - // if we've been reset, and there isn't any new packets yet // just play some silence @@ -158,10 +156,10 @@ int audioCallback (const void *inputBuffer, 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->getNextOutput(), BUFFER_LENGTH_BYTES); + memcpy(outputLeft, ringBuffer->getNextOutput(), PACKET_LENGTH_BYTES_PER_CHANNEL); + memcpy(outputRight, ringBuffer->getNextOutput() + PACKET_LENGTH_SAMPLES_PER_CHANNEL, PACKET_LENGTH_BYTES_PER_CHANNEL); - ringBuffer->setNextOutput(ringBuffer->getNextOutput() + BUFFER_LENGTH_SAMPLES); + ringBuffer->setNextOutput(ringBuffer->getNextOutput() + PACKET_LENGTH_SAMPLES); if (ringBuffer->getNextOutput() == ringBuffer->getBuffer() + RING_BUFFER_SAMPLES) { ringBuffer->setNextOutput(ringBuffer->getBuffer()); @@ -169,10 +167,6 @@ int audioCallback (const void *inputBuffer, } } - // copy whatever is in the queueBuffer to the outputLeft and outputRight buffers - memcpy(outputLeft, queueBuffer, BUFFER_LENGTH_BYTES); - memcpy(outputRight, queueBuffer, BUFFER_LENGTH_BYTES); - gettimeofday(&data->lastCallback, NULL); return paContinue; } @@ -190,7 +184,7 @@ void *receiveAudioViaUDP(void *args) { AudioRecThreadStruct *threadArgs = (AudioRecThreadStruct *) args; AudioData *sharedAudioData = threadArgs->sharedAudioData; - int16_t *receivedData = new int16_t[BUFFER_LENGTH_SAMPLES]; + int16_t *receivedData = new int16_t[PACKET_LENGTH_SAMPLES]; ssize_t receivedBytes; timeval previousReceiveTime, currentReceiveTime = {}; @@ -270,11 +264,11 @@ Audio::Audio(Oscilloscope * s) scope = s; - audioData = new AudioData(BUFFER_LENGTH_BYTES); + audioData = new AudioData(); // setup a UDPSocket audioData->audioSocket = new UDPSocket(AUDIO_UDP_LISTEN_PORT); - audioData->ringBuffer = new AudioRingBuffer(); + audioData->ringBuffer = new AudioRingBuffer(RING_BUFFER_SAMPLES, PACKET_LENGTH_SAMPLES); AudioRecThreadStruct threadArgs; threadArgs.sharedAudioData = audioData; @@ -285,8 +279,8 @@ Audio::Audio(Oscilloscope * s) 2, // input channels 2, // output channels (paInt16 | paNonInterleaved), // sample format - 22050, // sample rate (hz) - 512, // frames per buffer + SAMPLE_RATE, // sample rate (hz) + BUFFER_LENGTH_SAMPLES, // frames per buffer audioCallback, // callback function (void *) audioData); // user data to be passed to callback if (paError != paNoError) goto error; @@ -297,7 +291,7 @@ Audio::Audio(Oscilloscope * s) Pa_StartStream(stream); if (paError != paNoError) goto error; - + return; error: @@ -347,10 +341,10 @@ 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)BUFFER_LENGTH_SAMPLES/(float)SAMPLE_RATE) * frameWidth; + if (audioData->lastCallback.tv_usec > 0) timeLeftInCurrentBuffer = diffclock(&audioData->lastCallback, ¤tTime)/(1000.0*(float)PACKET_LENGTH_SAMPLES/(float)SAMPLE_RATE) * frameWidth; if (audioData->ringBuffer->getEndOfLastWrite() != NULL) - remainingBuffer = audioData->ringBuffer->diffLastWriteNextOutput() / BUFFER_LENGTH_SAMPLES * frameWidth; + remainingBuffer = audioData->ringBuffer->diffLastWriteNextOutput() / PACKET_LENGTH_SAMPLES * frameWidth; if (audioData->wasStarved == 0) glColor3f(0, 1, 0); else { @@ -378,12 +372,12 @@ void Audio::render(int screenWidth, int screenHeight) glEnd(); char out[20]; - sprintf(out, "%3.0f\n", audioData->averagedLatency/(float)frameWidth*(1000.0*(float)BUFFER_LENGTH_SAMPLES/(float)SAMPLE_RATE)); + 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); // Show a Cyan bar with the most recently measured jitter stdev - int jitterPels = (float) audioData->measuredJitter/ ((1000.0*(float)BUFFER_LENGTH_SAMPLES/(float)SAMPLE_RATE)) * (float)frameWidth; + int jitterPels = (float) audioData->measuredJitter/ ((1000.0*(float)PACKET_LENGTH_SAMPLES/(float)SAMPLE_RATE)) * (float)frameWidth; glColor3f(0,1,1); glBegin(GL_QUADS); diff --git a/interface/src/AudioData.cpp b/interface/src/AudioData.cpp index afba708db4..ae1b9d6517 100644 --- a/interface/src/AudioData.cpp +++ b/interface/src/AudioData.cpp @@ -8,11 +8,10 @@ #include "AudioData.h" -AudioData::AudioData(int bufferLength) { +AudioData::AudioData() { mixerAddress = 0; mixerPort = 0; - samplesToQueue = new int16_t[bufferLength / sizeof(int16_t)]; averagedLatency = 0.0; lastCallback.tv_usec = 0; wasStarved = 0; @@ -22,6 +21,5 @@ AudioData::AudioData(int bufferLength) { AudioData::~AudioData() { - delete[] samplesToQueue; delete audioSocket; } \ No newline at end of file diff --git a/interface/src/AudioData.h b/interface/src/AudioData.h index 4efe39884a..d06d92811d 100644 --- a/interface/src/AudioData.h +++ b/interface/src/AudioData.h @@ -17,7 +17,7 @@ class AudioData { public: - AudioData(int bufferLength); + AudioData(); ~AudioData(); AudioRingBuffer *ringBuffer; diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 1906b4e696..25cc888b06 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -80,7 +80,7 @@ int fullscreen = 0; in_addr_t localAddress; -Oscilloscope audioScope(512,200,true); +Oscilloscope audioScope(256,200,true); #define HAND_RADIUS 0.25 // Radius of in-world 'hand' of you Head myHead; // The rendered head of oneself diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index af39a0a4a2..d976231d6b 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -19,11 +19,18 @@ const unsigned short MIXER_LISTEN_PORT = 55443; 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 int BUFFER_LENGTH_BYTES = 1024; +const int BUFFER_LENGTH_SAMPLES_PER_CHANNEL = (BUFFER_LENGTH_BYTES / 2) / sizeof(int16_t); + +const short RING_BUFFER_FRAMES = 10; +const short RING_BUFFER_SAMPLES = RING_BUFFER_FRAMES * BUFFER_LENGTH_SAMPLES_PER_CHANNEL; + +const float BUFFER_SEND_INTERVAL_USECS = (BUFFER_LENGTH_SAMPLES_PER_CHANNEL / SAMPLE_RATE) * 1000000; + const long MAX_SAMPLE_VALUE = std::numeric_limits::max(); const long MIN_SAMPLE_VALUE = std::numeric_limits::min(); @@ -51,9 +58,10 @@ void *sendBuffer(void *args) if (agentBuffer != NULL && agentBuffer->getEndOfLastWrite() != NULL) { - if (!agentBuffer->isStarted() && agentBuffer->diffLastWriteNextOutput() <= BUFFER_LENGTH_SAMPLES + JITTER_BUFFER_SAMPLES) { + if (!agentBuffer->isStarted() + && agentBuffer->diffLastWriteNextOutput() <= BUFFER_LENGTH_SAMPLES_PER_CHANNEL + JITTER_BUFFER_SAMPLES) { printf("Held back buffer %d.\n", i); - } else if (agentBuffer->diffLastWriteNextOutput() < BUFFER_LENGTH_SAMPLES) { + } else if (agentBuffer->diffLastWriteNextOutput() < BUFFER_LENGTH_SAMPLES_PER_CHANNEL) { printf("Buffer %d starved.\n", i); agentBuffer->setStarted(false); } else { @@ -68,24 +76,26 @@ void *sendBuffer(void *args) for (int i = 0; i < agentList.getAgents().size(); i++) { Agent *agent = &agentList.getAgents()[i]; - int16_t clientMix[BUFFER_LENGTH_SAMPLES] = {}; + int16_t clientMix[BUFFER_LENGTH_SAMPLES_PER_CHANNEL * 2] = {}; for (int j = 0; j < agentList.getAgents().size(); j++) { - if (i != j) { + if (i == j) { AudioRingBuffer *otherAgentBuffer = (AudioRingBuffer *)agentList.getAgents()[j].getLinkedData(); - float *agentPosition = ((AudioRingBuffer *)agent->getLinkedData())->getPosition(); - float *otherAgentPosition = otherAgentBuffer->getPosition(); +// 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); + float distanceCoeff = 1; - 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++) { + for (int s = 0; s < BUFFER_LENGTH_SAMPLES_PER_CHANNEL; s++) { int16_t sample = (otherAgentBuffer->getNextOutput()[s] / distanceCoeff); clientMix[s] += sample; + clientMix[s + BUFFER_LENGTH_SAMPLES_PER_CHANNEL] += sample; } } } @@ -96,7 +106,7 @@ void *sendBuffer(void *args) 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); + agentBuffer->setNextOutput(agentBuffer->getNextOutput() + BUFFER_LENGTH_SAMPLES_PER_CHANNEL); if (agentBuffer->getNextOutput() >= agentBuffer->getBuffer() + RING_BUFFER_SAMPLES) { agentBuffer->setNextOutput(agentBuffer->getBuffer()); @@ -127,8 +137,8 @@ void *reportAliveToDS(void *args) { gettimeofday(&lastSend, NULL); *output = 'M'; - packSocket(output + 1, 895283510, htons(MIXER_LISTEN_PORT)); -// packSocket(output + 1, 788637888, htons(MIXER_LISTEN_PORT)); +// 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); double usecToSleep = 1000000 - (usecTimestampNow() - usecTimestamp(&lastSend)); @@ -143,7 +153,7 @@ void *reportAliveToDS(void *args) { void attachNewBufferToAgent(Agent *newAgent) { if (newAgent->getLinkedData() == NULL) { - newAgent->setLinkedData(new AudioRingBuffer()); + newAgent->setLinkedData(new AudioRingBuffer(RING_BUFFER_SAMPLES, BUFFER_LENGTH_SAMPLES_PER_CHANNEL)); } } @@ -184,7 +194,7 @@ int main(int argc, const char * argv[]) while (true) { if(agentList.getAgentSocket().receive(agentAddress, packetData, &receivedBytes)) { - if (receivedBytes >= BUFFER_LENGTH_BYTES) { + if (packetData[0] == 'I') { // add or update the existing interface agent agentList.addOrUpdateAgent(agentAddress, agentAddress, packetData[0]); agentList.updateAgentWithData(agentAddress, (void *)packetData, receivedBytes); diff --git a/shared/src/AudioRingBuffer.cpp b/shared/src/AudioRingBuffer.cpp index 15743b7d19..1abf6f234a 100644 --- a/shared/src/AudioRingBuffer.cpp +++ b/shared/src/AudioRingBuffer.cpp @@ -9,22 +9,27 @@ #include #include "AudioRingBuffer.h" -AudioRingBuffer::AudioRingBuffer() { +AudioRingBuffer::AudioRingBuffer(int ringSamples, int bufferSamples) { + ringBufferLengthSamples = ringSamples; + bufferLengthSamples = bufferSamples; + started = false; addedToMix = false; endOfLastWrite = NULL; - buffer = new int16_t[RING_BUFFER_SAMPLES]; + buffer = new int16_t[ringBufferLengthSamples]; nextOutput = buffer; }; AudioRingBuffer::AudioRingBuffer(const AudioRingBuffer &otherRingBuffer) { + ringBufferLengthSamples = otherRingBuffer.ringBufferLengthSamples; + bufferLengthSamples = otherRingBuffer.bufferLengthSamples; started = otherRingBuffer.started; addedToMix = otherRingBuffer.addedToMix; - buffer = new int16_t[RING_BUFFER_SAMPLES]; - memcpy(buffer, otherRingBuffer.buffer, sizeof(int16_t) * RING_BUFFER_SAMPLES); + buffer = new int16_t[ringBufferLengthSamples]; + memcpy(buffer, otherRingBuffer.buffer, sizeof(int16_t) * ringBufferLengthSamples); nextOutput = buffer + (otherRingBuffer.nextOutput - otherRingBuffer.buffer); endOfLastWrite = buffer + (otherRingBuffer.endOfLastWrite - otherRingBuffer.buffer); @@ -87,7 +92,7 @@ void AudioRingBuffer::setPosition(float *newPosition) { void AudioRingBuffer::parseData(void *data, int size) { unsigned char *audioDataStart = (unsigned char *) data; - if (size > BUFFER_LENGTH_BYTES) { + if (size > (bufferLengthSamples * sizeof(int16_t))) { for (int p = 0; p < 3; p ++) { memcpy(&position[p], audioDataStart + 1 + (sizeof(float) * p), sizeof(float)); @@ -98,19 +103,19 @@ void AudioRingBuffer::parseData(void *data, int size) { if (endOfLastWrite == NULL) { endOfLastWrite = buffer; - } else if (diffLastWriteNextOutput() > RING_BUFFER_SAMPLES - BUFFER_LENGTH_SAMPLES) { + } else if (diffLastWriteNextOutput() > ringBufferLengthSamples - bufferLengthSamples) { endOfLastWrite = buffer; nextOutput = buffer; started = false; } - memcpy(endOfLastWrite, audioDataStart, BUFFER_LENGTH_BYTES); + memcpy(endOfLastWrite, audioDataStart, bufferLengthSamples * sizeof(int16_t)); - endOfLastWrite += BUFFER_LENGTH_SAMPLES; + endOfLastWrite += bufferLengthSamples; addedToMix = false; - if (endOfLastWrite >= buffer + RING_BUFFER_SAMPLES) { + if (endOfLastWrite >= buffer + ringBufferLengthSamples) { endOfLastWrite = buffer; } } @@ -123,7 +128,7 @@ short AudioRingBuffer::diffLastWriteNextOutput() short sampleDifference = endOfLastWrite - nextOutput; if (sampleDifference < 0) { - sampleDifference += RING_BUFFER_SAMPLES; + sampleDifference += ringBufferLengthSamples; } return sampleDifference; diff --git a/shared/src/AudioRingBuffer.h b/shared/src/AudioRingBuffer.h index f9c3f5e136..19d587d4f6 100644 --- a/shared/src/AudioRingBuffer.h +++ b/shared/src/AudioRingBuffer.h @@ -13,15 +13,9 @@ #include #include "AgentData.h" -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(int ringSamples, int bufferSamples); ~AudioRingBuffer(); AudioRingBuffer(const AudioRingBuffer &otherRingBuffer); @@ -42,6 +36,8 @@ class AudioRingBuffer : public AgentData { short diffLastWriteNextOutput(); private: + int ringBufferLengthSamples; + int bufferLengthSamples; float position[3]; int16_t *nextOutput; int16_t *endOfLastWrite; From a42fc472316197fb6682622946268eb8e8296834 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 28 Feb 2013 15:58:57 -0800 Subject: [PATCH 28/85] relink head to AudioRingBuffer, send source bearing --- interface/src/Audio.cpp | 29 +++++++++++++++++++++-------- interface/src/Audio.h | 5 ++--- interface/src/AudioData.h | 5 ++--- interface/src/main.cpp | 3 +-- shared/src/AudioRingBuffer.cpp | 10 ++++++++-- shared/src/AudioRingBuffer.h | 3 +++ 6 files changed, 37 insertions(+), 18 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 45d57873df..4a5d4907ed 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -93,20 +93,34 @@ int audioCallback (const void *inputBuffer, audioMixerSocket.sin_addr.s_addr = data->mixerAddress; audioMixerSocket.sin_port = data->mixerPort; - int leadingBytes = 1 + (sizeof(float) * 3); + int leadingBytes = 1 + (sizeof(float) * 4); // 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'; + unsigned char *currentPacketPtr = dataPacket + 1; // memcpy the three float positions for (int p = 0; p < 3; p++) { - memcpy(dataPacket + 1 + (p * sizeof(float)), &data->sourcePosition[p], sizeof(float)); + memcpy(currentPacketPtr, &data->linkedHead->getPos()[p], sizeof(float)); + currentPacketPtr += sizeof(float); } + // memcpy the corrected render yaw + float correctedYaw = fmodf(data->linkedHead->getRenderYaw(), 360); + + if (correctedYaw > 180) { + correctedYaw -= 360; + } else if (correctedYaw < -180) { + correctedYaw += 360; + } + + memcpy(currentPacketPtr, &correctedYaw, sizeof(float)); + currentPacketPtr += sizeof(float); + // copy the audio data to the last BUFFER_LENGTH_BYTES bytes of the data packet - memcpy(dataPacket + leadingBytes, inputLeft, BUFFER_LENGTH_BYTES); + memcpy(currentPacketPtr, inputLeft, BUFFER_LENGTH_BYTES); data->audioSocket->send((sockaddr *)&audioMixerSocket, dataPacket, BUFFER_LENGTH_BYTES + leadingBytes); } @@ -118,6 +132,7 @@ int audioCallback (const void *inputBuffer, for (int i = 0; i < BUFFER_LENGTH_SAMPLES; i++) { loudness += abs(inputLeft[i]); } + loudness /= BUFFER_LENGTH_SAMPLES; data->lastInputLoudness = loudness; data->averagedInputLoudness = 0.66*data->averagedInputLoudness + 0.33*loudness; @@ -246,10 +261,6 @@ 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. @@ -257,7 +268,7 @@ void Audio::setSourcePosition(glm::vec3 newPosition) { * @return Returns true if successful or false if an error occurred. Use Audio::getError() to retrieve the error code. */ -Audio::Audio(Oscilloscope * s) +Audio::Audio(Oscilloscope *s, Head *linkedHead) { paError = Pa_Initialize(); if (paError != paNoError) goto error; @@ -266,6 +277,8 @@ Audio::Audio(Oscilloscope * s) audioData = new AudioData(); + audioData->linkedHead = linkedHead; + // setup a UDPSocket audioData->audioSocket = new UDPSocket(AUDIO_UDP_LISTEN_PORT); audioData->ringBuffer = new AudioRingBuffer(RING_BUFFER_SAMPLES, PACKET_LENGTH_SAMPLES); diff --git a/interface/src/Audio.h b/interface/src/Audio.h index 0798486106..4bc93b37b0 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -13,11 +13,12 @@ #include #include "AudioData.h" #include "Oscilloscope.h" +#include "Head.h" class Audio { public: // initializes audio I/O - Audio(Oscilloscope * s); + Audio(Oscilloscope *s, Head *linkedHead); void render(); void render(int screenWidth, int screenHeight); @@ -25,8 +26,6 @@ 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: diff --git a/interface/src/AudioData.h b/interface/src/AudioData.h index d06d92811d..2047ffc6e3 100644 --- a/interface/src/AudioData.h +++ b/interface/src/AudioData.h @@ -14,6 +14,7 @@ #include #include "AudioRingBuffer.h" #include "UDPSocket.h" +#include "Head.h" class AudioData { public: @@ -23,9 +24,7 @@ class AudioData { UDPSocket *audioSocket; - int16_t *samplesToQueue; - - glm::vec3 sourcePosition; + Head *linkedHead; // store current mixer address and port in_addr_t mixerAddress; diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 25cc888b06..52e602df6a 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -106,7 +106,7 @@ Lattice lattice(160,100); Finger myFinger(WIDTH, HEIGHT); Field field; -Audio audio(&audioScope); +Audio audio(&audioScope, &myHead); #define RENDER_FRAME_MSECS 8 int steps_per_frame = 0; @@ -512,7 +512,6 @@ 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/shared/src/AudioRingBuffer.cpp b/shared/src/AudioRingBuffer.cpp index 1abf6f234a..0fc11e8f10 100644 --- a/shared/src/AudioRingBuffer.cpp +++ b/shared/src/AudioRingBuffer.cpp @@ -94,11 +94,17 @@ void AudioRingBuffer::parseData(void *data, int size) { if (size > (bufferLengthSamples * sizeof(int16_t))) { + unsigned char *dataPtr = audioDataStart + 1; + for (int p = 0; p < 3; p ++) { - memcpy(&position[p], audioDataStart + 1 + (sizeof(float) * p), sizeof(float)); + memcpy(&position[p], dataPtr, sizeof(float)); + dataPtr += sizeof(float); } - audioDataStart += (1 + (sizeof(float) * 3)); + memcpy(&bearing, dataPtr, sizeof(float)); + dataPtr += sizeof(float); + + audioDataStart = dataPtr; } if (endOfLastWrite == NULL) { diff --git a/shared/src/AudioRingBuffer.h b/shared/src/AudioRingBuffer.h index 19d587d4f6..fcd16e1884 100644 --- a/shared/src/AudioRingBuffer.h +++ b/shared/src/AudioRingBuffer.h @@ -33,12 +33,15 @@ class AudioRingBuffer : public AgentData { void setAddedToMix(bool added); float* getPosition(); void setPosition(float newPosition[]); + float getBearing(); + float setBearing(float newBearing); short diffLastWriteNextOutput(); private: int ringBufferLengthSamples; int bufferLengthSamples; float position[3]; + float bearing; int16_t *nextOutput; int16_t *endOfLastWrite; int16_t *buffer; From 400cb238f2b81a32bdb2fae42e563871a059baa9 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 28 Feb 2013 17:50:17 -0800 Subject: [PATCH 29/85] calculate angle between agent and other sources to prep for phase delay --- mixer/src/main.cpp | 41 ++++++++++++++++++++++++++-------- shared/src/AudioRingBuffer.cpp | 8 +++++++ shared/src/AudioRingBuffer.h | 2 +- 3 files changed, 41 insertions(+), 10 deletions(-) diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index d976231d6b..71df058916 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -80,17 +80,40 @@ void *sendBuffer(void *args) for (int j = 0; j < agentList.getAgents().size(); j++) { if (i == j) { + AudioRingBuffer *agentRingBuffer = (AudioRingBuffer *) agent->getLinkedData(); 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); - float distanceCoeff = 1; + + float *agentPosition = agentRingBuffer->getPosition(); + float otherAgentPosition[3] = {0,0,0}; + + // calculate the distance to the other agent + float distanceToAgent = sqrtf(powf(agentPosition[0] - otherAgentPosition[0], 2) + + powf(agentPosition[1] - otherAgentPosition[1], 2) + + powf(agentPosition[2] - otherAgentPosition[2], 2)); + // use the distance to the other agent to calculate the change in volume for this frame + float distanceCoeff = powf((logf(DISTANCE_RATIO * distanceToAgent) / logf(3)), 2); + + // get the angle from the right-angle triangle + float triangleAngle = atan2f(fabsf(agentPosition[2] - otherAgentPosition[2]), fabsf(agentPosition[0] - otherAgentPosition[0])) * (180 / M_PI); + float angleToSource; + + float agentBearing = agentRingBuffer->getBearing(); + + // find the angle we need for calculation based on the orientation of the triangle + if (otherAgentPosition[0] > agentPosition[0]) { + if (otherAgentPosition[2] > agentPosition[2]) { + angleToSource = -90 + triangleAngle - agentBearing; + } else { + angleToSource = -90 - triangleAngle - agentBearing; + } + } else { + if (otherAgentPosition[2] > agentPosition[2]) { + angleToSource = 90 - triangleAngle - agentBearing; + } else { + angleToSource = 90 + triangleAngle - agentBearing; + } + } for (int s = 0; s < BUFFER_LENGTH_SAMPLES_PER_CHANNEL; s++) { int16_t sample = (otherAgentBuffer->getNextOutput()[s] / distanceCoeff); diff --git a/shared/src/AudioRingBuffer.cpp b/shared/src/AudioRingBuffer.cpp index 0fc11e8f10..f6443db066 100644 --- a/shared/src/AudioRingBuffer.cpp +++ b/shared/src/AudioRingBuffer.cpp @@ -89,6 +89,14 @@ void AudioRingBuffer::setPosition(float *newPosition) { position[2] = newPosition[2]; } +float AudioRingBuffer::getBearing() { + return bearing; +} + +void AudioRingBuffer::setBearing(float newBearing) { + bearing = newBearing; +} + void AudioRingBuffer::parseData(void *data, int size) { unsigned char *audioDataStart = (unsigned char *) data; diff --git a/shared/src/AudioRingBuffer.h b/shared/src/AudioRingBuffer.h index fcd16e1884..90d3550bb0 100644 --- a/shared/src/AudioRingBuffer.h +++ b/shared/src/AudioRingBuffer.h @@ -34,7 +34,7 @@ class AudioRingBuffer : public AgentData { float* getPosition(); void setPosition(float newPosition[]); float getBearing(); - float setBearing(float newBearing); + void setBearing(float newBearing); short diffLastWriteNextOutput(); private: From c23b5ff785eafe29c1bac63de2054a5169a1f112 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 1 Mar 2013 12:33:24 -0800 Subject: [PATCH 30/85] cap distance amplification at 1, create spatialized mix --- mixer/src/main.cpp | 42 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index 71df058916..fbc0fbd60f 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -35,6 +35,7 @@ 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; +const int PHASE_DELAY_AT_90 = 20; char DOMAIN_HOSTNAME[] = "highfidelity.below92.com"; char DOMAIN_IP[100] = ""; // IP Address will be re-set by lookup on startup @@ -69,7 +70,6 @@ void *sendBuffer(void *args) agentBuffer->setStarted(true); agentBuffer->setAddedToMix(true); } - } } @@ -79,13 +79,13 @@ void *sendBuffer(void *args) int16_t clientMix[BUFFER_LENGTH_SAMPLES_PER_CHANNEL * 2] = {}; for (int j = 0; j < agentList.getAgents().size(); j++) { - if (i == j) { + if (i != j) { AudioRingBuffer *agentRingBuffer = (AudioRingBuffer *) agent->getLinkedData(); AudioRingBuffer *otherAgentBuffer = (AudioRingBuffer *)agentList.getAgents()[j].getLinkedData(); float *agentPosition = agentRingBuffer->getPosition(); - float otherAgentPosition[3] = {0,0,0}; + float *otherAgentPosition = otherAgentBuffer->getPosition(); // calculate the distance to the other agent float distanceToAgent = sqrtf(powf(agentPosition[0] - otherAgentPosition[0], 2) + @@ -93,6 +93,7 @@ void *sendBuffer(void *args) powf(agentPosition[2] - otherAgentPosition[2], 2)); // use the distance to the other agent to calculate the change in volume for this frame float distanceCoeff = powf((logf(DISTANCE_RATIO * distanceToAgent) / logf(3)), 2); + distanceCoeff = std::max(1.0f, distanceCoeff); // get the angle from the right-angle triangle float triangleAngle = atan2f(fabsf(agentPosition[2] - otherAgentPosition[2]), fabsf(agentPosition[0] - otherAgentPosition[0])) * (180 / M_PI); @@ -115,10 +116,39 @@ void *sendBuffer(void *args) } } + if (angleToSource > 180) { + angleToSource -= 360; + } else if (angleToSource < -180) { + angleToSource += 360; + } + + angleToSource *= (M_PI / 180); + + float sinRatio = fabsf(sinf(angleToSource)); + int numSamplesDelay = PHASE_DELAY_AT_90 * sinRatio; + + int16_t *goodChannel = angleToSource > 0 ? clientMix + BUFFER_LENGTH_SAMPLES_PER_CHANNEL : clientMix; + int16_t *delayedChannel = angleToSource > 0 ? clientMix : clientMix + BUFFER_LENGTH_SAMPLES_PER_CHANNEL; + + int16_t *delaySamplePointer = otherAgentBuffer->getNextOutput() == otherAgentBuffer->getBuffer() + ? otherAgentBuffer->getBuffer() + RING_BUFFER_SAMPLES - numSamplesDelay + : otherAgentBuffer->getNextOutput() - numSamplesDelay; + for (int s = 0; s < BUFFER_LENGTH_SAMPLES_PER_CHANNEL; s++) { - int16_t sample = (otherAgentBuffer->getNextOutput()[s] / distanceCoeff); - clientMix[s] += sample; - clientMix[s + BUFFER_LENGTH_SAMPLES_PER_CHANNEL] += sample; + + if (s < numSamplesDelay) { + // pull the earlier sample for the delayed channel + + int earlierSample = delaySamplePointer[s] / distanceCoeff; + delayedChannel[s] = earlierSample; + } + + int16_t currentSample = (otherAgentBuffer->getNextOutput()[s] / distanceCoeff); + goodChannel[s] = currentSample; + + if (s + numSamplesDelay < BUFFER_LENGTH_SAMPLES_PER_CHANNEL) { + delayedChannel[s + numSamplesDelay] = currentSample; + } } } } From c2578b72bd3a8327b0af84a46279af56521d9ed7 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 1 Mar 2013 14:54:00 -0800 Subject: [PATCH 31/85] test of a low pass filter in non-FFT space --- mixer/src/main.cpp | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index fbc0fbd60f..6a8be02b38 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -37,12 +37,20 @@ const long MIN_SAMPLE_VALUE = std::numeric_limits::min(); const float DISTANCE_RATIO = 3.0/4.2; const int PHASE_DELAY_AT_90 = 20; +const float BEARING_LOW_PASS_FACTOR = 0.1; +const float ANGLE_TO_SOURCE_LOW_PASS_FACTOR = 0.4; + 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; AgentList agentList(MIXER_LISTEN_PORT); +int16_t lowPassSampleCenteredAtPointer(int16_t *samplePointer) { + return (0.0625 * *(samplePointer - 3)) + (0.125 * *(samplePointer - 2)) + (0.1875 * *(samplePointer - 1)) + (0.25 * *samplePointer) + + (0.1875 * *(samplePointer + 1)) + (0.125 * *(samplePointer + 2)) + (0.0625 * *(samplePointer + 3)); +} + void *sendBuffer(void *args) { int sentBytes; @@ -134,8 +142,13 @@ void *sendBuffer(void *args) ? otherAgentBuffer->getBuffer() + RING_BUFFER_SAMPLES - numSamplesDelay : otherAgentBuffer->getNextOutput() - numSamplesDelay; + int16_t *lowPassFrame = new int16_t[(BUFFER_LENGTH_SAMPLES_PER_CHANNEL * 2) / 4]; + // calculate the low-pass filter intensity + float lowPassIntensity = ((agentBearing - otherAgentBuffer->getBearing()) * BEARING_LOW_PASS_FACTOR) + + (fabsf(angleToSource) * ANGLE_TO_SOURCE_LOW_PASS_FACTOR); + for (int s = 0; s < BUFFER_LENGTH_SAMPLES_PER_CHANNEL; s++) { - + if (s < numSamplesDelay) { // pull the earlier sample for the delayed channel @@ -149,6 +162,15 @@ void *sendBuffer(void *args) if (s + numSamplesDelay < BUFFER_LENGTH_SAMPLES_PER_CHANNEL) { delayedChannel[s + numSamplesDelay] = currentSample; } + + if ((s + 1) % 4 == 0) { + int sampleIndex = ((s + 1) / 4) - 1; + // this will be a sample in the lowPassFrame + lowPassFrame[sampleIndex] = lowPassSampleCenteredAtPointer(clientMix + s); + lowPassFrame[sampleIndex + (BUFFER_LENGTH_SAMPLES_PER_CHANNEL / 4)] = lowPassSampleCenteredAtPointer(clientMix + s + BUFFER_LENGTH_SAMPLES_PER_CHANNEL); + } + + clientMix[s] = lowPassFrame[s / 4]; } } } From 2bbeca1e01446253f91b707bc599c4d73b7638c7 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 1 Mar 2013 14:54:28 -0800 Subject: [PATCH 32/85] Revert "test of a low pass filter in non-FFT space" This reverts commit c2578b72bd3a8327b0af84a46279af56521d9ed7. --- mixer/src/main.cpp | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index 6a8be02b38..fbc0fbd60f 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -37,20 +37,12 @@ const long MIN_SAMPLE_VALUE = std::numeric_limits::min(); const float DISTANCE_RATIO = 3.0/4.2; const int PHASE_DELAY_AT_90 = 20; -const float BEARING_LOW_PASS_FACTOR = 0.1; -const float ANGLE_TO_SOURCE_LOW_PASS_FACTOR = 0.4; - 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; AgentList agentList(MIXER_LISTEN_PORT); -int16_t lowPassSampleCenteredAtPointer(int16_t *samplePointer) { - return (0.0625 * *(samplePointer - 3)) + (0.125 * *(samplePointer - 2)) + (0.1875 * *(samplePointer - 1)) + (0.25 * *samplePointer) + - (0.1875 * *(samplePointer + 1)) + (0.125 * *(samplePointer + 2)) + (0.0625 * *(samplePointer + 3)); -} - void *sendBuffer(void *args) { int sentBytes; @@ -142,13 +134,8 @@ void *sendBuffer(void *args) ? otherAgentBuffer->getBuffer() + RING_BUFFER_SAMPLES - numSamplesDelay : otherAgentBuffer->getNextOutput() - numSamplesDelay; - int16_t *lowPassFrame = new int16_t[(BUFFER_LENGTH_SAMPLES_PER_CHANNEL * 2) / 4]; - // calculate the low-pass filter intensity - float lowPassIntensity = ((agentBearing - otherAgentBuffer->getBearing()) * BEARING_LOW_PASS_FACTOR) + - (fabsf(angleToSource) * ANGLE_TO_SOURCE_LOW_PASS_FACTOR); - for (int s = 0; s < BUFFER_LENGTH_SAMPLES_PER_CHANNEL; s++) { - + if (s < numSamplesDelay) { // pull the earlier sample for the delayed channel @@ -162,15 +149,6 @@ void *sendBuffer(void *args) if (s + numSamplesDelay < BUFFER_LENGTH_SAMPLES_PER_CHANNEL) { delayedChannel[s + numSamplesDelay] = currentSample; } - - if ((s + 1) % 4 == 0) { - int sampleIndex = ((s + 1) / 4) - 1; - // this will be a sample in the lowPassFrame - lowPassFrame[sampleIndex] = lowPassSampleCenteredAtPointer(clientMix + s); - lowPassFrame[sampleIndex + (BUFFER_LENGTH_SAMPLES_PER_CHANNEL / 4)] = lowPassSampleCenteredAtPointer(clientMix + s + BUFFER_LENGTH_SAMPLES_PER_CHANNEL); - } - - clientMix[s] = lowPassFrame[s / 4]; } } } From 23088bbdfd0af52d2f53fa26ea3fe56b21f91b3d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 1 Mar 2013 15:19:13 -0800 Subject: [PATCH 33/85] have mixer report the EC2 address --- mixer/src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index fbc0fbd60f..2fb94ab71c 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -190,8 +190,8 @@ void *reportAliveToDS(void *args) { gettimeofday(&lastSend, NULL); *output = 'M'; -// packSocket(output + 1, 895283510, htons(MIXER_LISTEN_PORT)); - packSocket(output + 1, 788637888, htons(MIXER_LISTEN_PORT)); + 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); double usecToSleep = 1000000 - (usecTimestampNow() - usecTimestamp(&lastSend)); From 1c6fa5235745f699cb6469f7e67e62ec9c3f3787 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 1 Mar 2013 15:34:49 -0800 Subject: [PATCH 34/85] Revert "Revert "test of a low pass filter in non-FFT space"" This reverts commit 2bbeca1e01446253f91b707bc599c4d73b7638c7. --- mixer/src/main.cpp | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index 2fb94ab71c..185eb0305b 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -37,12 +37,20 @@ const long MIN_SAMPLE_VALUE = std::numeric_limits::min(); const float DISTANCE_RATIO = 3.0/4.2; const int PHASE_DELAY_AT_90 = 20; +const float BEARING_LOW_PASS_FACTOR = 0.1; +const float ANGLE_TO_SOURCE_LOW_PASS_FACTOR = 0.4; + 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; AgentList agentList(MIXER_LISTEN_PORT); +int16_t lowPassSampleCenteredAtPointer(int16_t *samplePointer) { + return (0.0625 * *(samplePointer - 3)) + (0.125 * *(samplePointer - 2)) + (0.1875 * *(samplePointer - 1)) + (0.25 * *samplePointer) + + (0.1875 * *(samplePointer + 1)) + (0.125 * *(samplePointer + 2)) + (0.0625 * *(samplePointer + 3)); +} + void *sendBuffer(void *args) { int sentBytes; @@ -134,8 +142,13 @@ void *sendBuffer(void *args) ? otherAgentBuffer->getBuffer() + RING_BUFFER_SAMPLES - numSamplesDelay : otherAgentBuffer->getNextOutput() - numSamplesDelay; + int16_t *lowPassFrame = new int16_t[(BUFFER_LENGTH_SAMPLES_PER_CHANNEL * 2) / 4]; + // calculate the low-pass filter intensity + float lowPassIntensity = ((agentBearing - otherAgentBuffer->getBearing()) * BEARING_LOW_PASS_FACTOR) + + (fabsf(angleToSource) * ANGLE_TO_SOURCE_LOW_PASS_FACTOR); + for (int s = 0; s < BUFFER_LENGTH_SAMPLES_PER_CHANNEL; s++) { - + if (s < numSamplesDelay) { // pull the earlier sample for the delayed channel @@ -149,6 +162,15 @@ void *sendBuffer(void *args) if (s + numSamplesDelay < BUFFER_LENGTH_SAMPLES_PER_CHANNEL) { delayedChannel[s + numSamplesDelay] = currentSample; } + + if ((s + 1) % 4 == 0) { + int sampleIndex = ((s + 1) / 4) - 1; + // this will be a sample in the lowPassFrame + lowPassFrame[sampleIndex] = lowPassSampleCenteredAtPointer(clientMix + s); + lowPassFrame[sampleIndex + (BUFFER_LENGTH_SAMPLES_PER_CHANNEL / 4)] = lowPassSampleCenteredAtPointer(clientMix + s + BUFFER_LENGTH_SAMPLES_PER_CHANNEL); + } + + clientMix[s] = lowPassFrame[s / 4]; } } } From 0c057139551ca1ea9cd7c727c61458d5af039ed4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 1 Mar 2013 15:47:55 -0800 Subject: [PATCH 35/85] the proper test of fred's low pass algorithm --- mixer/src/main.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index 185eb0305b..7f393ece43 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -142,7 +142,7 @@ void *sendBuffer(void *args) ? otherAgentBuffer->getBuffer() + RING_BUFFER_SAMPLES - numSamplesDelay : otherAgentBuffer->getNextOutput() - numSamplesDelay; - int16_t *lowPassFrame = new int16_t[(BUFFER_LENGTH_SAMPLES_PER_CHANNEL * 2) / 4]; + // calculate the low-pass filter intensity float lowPassIntensity = ((agentBearing - otherAgentBuffer->getBearing()) * BEARING_LOW_PASS_FACTOR) + (fabsf(angleToSource) * ANGLE_TO_SOURCE_LOW_PASS_FACTOR); @@ -162,7 +162,11 @@ void *sendBuffer(void *args) if (s + numSamplesDelay < BUFFER_LENGTH_SAMPLES_PER_CHANNEL) { delayedChannel[s + numSamplesDelay] = currentSample; } - + } + + int16_t lowPassFrame[(BUFFER_LENGTH_SAMPLES_PER_CHANNEL * 2) / 4]; + + for (int s = 0; s < BUFFER_LENGTH_SAMPLES_PER_CHANNEL; s++) { if ((s + 1) % 4 == 0) { int sampleIndex = ((s + 1) / 4) - 1; // this will be a sample in the lowPassFrame @@ -171,6 +175,7 @@ void *sendBuffer(void *args) } clientMix[s] = lowPassFrame[s / 4]; + clientMix[s + BUFFER_LENGTH_SAMPLES_PER_CHANNEL] = lowPassFrame[(s + BUFFER_LENGTH_SAMPLES_PER_CHANNEL) / 4]; } } } From f0642f1d11b9fe3711932d60ba1845dbe97e15ef Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 1 Mar 2013 15:50:16 -0800 Subject: [PATCH 36/85] remove low pass filtering tests This reverts commit 0c057139551ca1ea9cd7c727c61458d5af039ed4. --- mixer/src/main.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index 7f393ece43..185eb0305b 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -142,7 +142,7 @@ void *sendBuffer(void *args) ? otherAgentBuffer->getBuffer() + RING_BUFFER_SAMPLES - numSamplesDelay : otherAgentBuffer->getNextOutput() - numSamplesDelay; - + int16_t *lowPassFrame = new int16_t[(BUFFER_LENGTH_SAMPLES_PER_CHANNEL * 2) / 4]; // calculate the low-pass filter intensity float lowPassIntensity = ((agentBearing - otherAgentBuffer->getBearing()) * BEARING_LOW_PASS_FACTOR) + (fabsf(angleToSource) * ANGLE_TO_SOURCE_LOW_PASS_FACTOR); @@ -162,11 +162,7 @@ void *sendBuffer(void *args) if (s + numSamplesDelay < BUFFER_LENGTH_SAMPLES_PER_CHANNEL) { delayedChannel[s + numSamplesDelay] = currentSample; } - } - - int16_t lowPassFrame[(BUFFER_LENGTH_SAMPLES_PER_CHANNEL * 2) / 4]; - - for (int s = 0; s < BUFFER_LENGTH_SAMPLES_PER_CHANNEL; s++) { + if ((s + 1) % 4 == 0) { int sampleIndex = ((s + 1) / 4) - 1; // this will be a sample in the lowPassFrame @@ -175,7 +171,6 @@ void *sendBuffer(void *args) } clientMix[s] = lowPassFrame[s / 4]; - clientMix[s + BUFFER_LENGTH_SAMPLES_PER_CHANNEL] = lowPassFrame[(s + BUFFER_LENGTH_SAMPLES_PER_CHANNEL) / 4]; } } } From 7086e075a80b5341e2e96f2c79e9354cf4dbfa83 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 1 Mar 2013 15:50:28 -0800 Subject: [PATCH 37/85] undo revert of old low pass filtering test This reverts commit 1c6fa5235745f699cb6469f7e67e62ec9c3f3787. --- mixer/src/main.cpp | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index 185eb0305b..2fb94ab71c 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -37,20 +37,12 @@ const long MIN_SAMPLE_VALUE = std::numeric_limits::min(); const float DISTANCE_RATIO = 3.0/4.2; const int PHASE_DELAY_AT_90 = 20; -const float BEARING_LOW_PASS_FACTOR = 0.1; -const float ANGLE_TO_SOURCE_LOW_PASS_FACTOR = 0.4; - 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; AgentList agentList(MIXER_LISTEN_PORT); -int16_t lowPassSampleCenteredAtPointer(int16_t *samplePointer) { - return (0.0625 * *(samplePointer - 3)) + (0.125 * *(samplePointer - 2)) + (0.1875 * *(samplePointer - 1)) + (0.25 * *samplePointer) + - (0.1875 * *(samplePointer + 1)) + (0.125 * *(samplePointer + 2)) + (0.0625 * *(samplePointer + 3)); -} - void *sendBuffer(void *args) { int sentBytes; @@ -142,13 +134,8 @@ void *sendBuffer(void *args) ? otherAgentBuffer->getBuffer() + RING_BUFFER_SAMPLES - numSamplesDelay : otherAgentBuffer->getNextOutput() - numSamplesDelay; - int16_t *lowPassFrame = new int16_t[(BUFFER_LENGTH_SAMPLES_PER_CHANNEL * 2) / 4]; - // calculate the low-pass filter intensity - float lowPassIntensity = ((agentBearing - otherAgentBuffer->getBearing()) * BEARING_LOW_PASS_FACTOR) + - (fabsf(angleToSource) * ANGLE_TO_SOURCE_LOW_PASS_FACTOR); - for (int s = 0; s < BUFFER_LENGTH_SAMPLES_PER_CHANNEL; s++) { - + if (s < numSamplesDelay) { // pull the earlier sample for the delayed channel @@ -162,15 +149,6 @@ void *sendBuffer(void *args) if (s + numSamplesDelay < BUFFER_LENGTH_SAMPLES_PER_CHANNEL) { delayedChannel[s + numSamplesDelay] = currentSample; } - - if ((s + 1) % 4 == 0) { - int sampleIndex = ((s + 1) / 4) - 1; - // this will be a sample in the lowPassFrame - lowPassFrame[sampleIndex] = lowPassSampleCenteredAtPointer(clientMix + s); - lowPassFrame[sampleIndex + (BUFFER_LENGTH_SAMPLES_PER_CHANNEL / 4)] = lowPassSampleCenteredAtPointer(clientMix + s + BUFFER_LENGTH_SAMPLES_PER_CHANNEL); - } - - clientMix[s] = lowPassFrame[s / 4]; } } } From a7deca0ced54e02016c1429d431fa0c25b87ef05 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 4 Mar 2013 10:37:48 -0800 Subject: [PATCH 38/85] add a broken flanger --- interface/src/Audio.cpp | 56 +++++++++++++++++++++++++++++++++++++++-- interface/src/Head.cpp | 6 ++--- interface/src/Head.h | 4 ++- 3 files changed, 60 insertions(+), 6 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 4a5d4907ed..d376d6f164 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -36,6 +36,10 @@ 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 int FLANGE_EFFECT_THRESHOLD = 200; +const int FLANGE_DELAY_MAX_SAMPLES = 100; +const float FLANGE_SAMPLE_WEIGHT = 0.70; + const short NUM_AUDIO_SOURCES = 2; const short ECHO_SERVER_TEST = 1; @@ -49,6 +53,8 @@ int starve_counter = 0; StDev stdev; bool stopAudioReceiveThread = false; +int samplesLeftForFlange = 0; + #define LOG_SAMPLE_DELAY 1 std::ofstream logFile; @@ -171,9 +177,55 @@ int audioCallback (const void *inputBuffer, ringBuffer->setStarted(true); // play whatever we have in the audio buffer - memcpy(outputLeft, ringBuffer->getNextOutput(), PACKET_LENGTH_BYTES_PER_CHANNEL); - memcpy(outputRight, ringBuffer->getNextOutput() + PACKET_LENGTH_SAMPLES_PER_CHANNEL, PACKET_LENGTH_BYTES_PER_CHANNEL); + // if we haven't fired off the flange effect, check if we should + if (!samplesLeftForFlange && fabsf(data->linkedHead->getLastMeasuredYaw()) > FLANGE_EFFECT_THRESHOLD) { + // we should flange for one second + samplesLeftForFlange = SAMPLE_RATE; + } + for (int s = 0; s < PACKET_LENGTH_SAMPLES_PER_CHANNEL; s++) { + + int leftSample = ringBuffer->getNextOutput()[s]; + int rightSample = ringBuffer->getNextOutput()[s + PACKET_LENGTH_SAMPLES_PER_CHANNEL]; + + if (samplesLeftForFlange > 0) { + int sampleFlangeDelay = (samplesLeftForFlange / (float) SAMPLE_RATE) * FLANGE_DELAY_MAX_SAMPLES; + + if (sampleFlangeDelay != FLANGE_DELAY_MAX_SAMPLES || s >= FLANGE_DELAY_MAX_SAMPLES) { + // we have a delayed sample to add to this sample + + int16_t *flangeFrame = ringBuffer->getNextOutput(); + int flangeIndex; + + if (s - sampleFlangeDelay < 0) { + // we need to grab the flange sample from earlier in the buffer + flangeFrame = ringBuffer->getNextOutput() - BUFFER_LENGTH_SAMPLES; + + if (flangeFrame < ringBuffer->getBuffer()) { + // we have wraparound + + flangeFrame = ringBuffer->getBuffer() + RING_BUFFER_SAMPLES - BUFFER_LENGTH_SAMPLES; + } + + flangeIndex = PACKET_LENGTH_SAMPLES_PER_CHANNEL + (s - sampleFlangeDelay); + } else { + flangeIndex = s - sampleFlangeDelay; + } + + int16_t leftFlangeSample = flangeFrame[flangeIndex]; + int16_t rightFlangeSample = flangeFrame[flangeIndex + PACKET_LENGTH_SAMPLES_PER_CHANNEL]; + + leftSample = (1 - FLANGE_SAMPLE_WEIGHT) * leftSample + (FLANGE_SAMPLE_WEIGHT * leftFlangeSample); + rightSample = (1 - FLANGE_SAMPLE_WEIGHT) * rightSample + (FLANGE_SAMPLE_WEIGHT * rightFlangeSample); + + samplesLeftForFlange--; + } + } + + outputLeft[s] = leftSample; + outputRight[s] = rightSample; + } + ringBuffer->setNextOutput(ringBuffer->getNextOutput() + PACKET_LENGTH_SAMPLES); if (ringBuffer->getNextOutput() == ringBuffer->getBuffer() + RING_BUFFER_SAMPLES) { diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index 1e5b3c4203..d3caf98f95 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -87,7 +87,7 @@ void Head::UpdatePos(float frametime, SerialInterface * serialInterface, int hea const float PITCH_ACCEL_COUPLING = 0.5; const float ROLL_ACCEL_COUPLING = -1.0; float measured_pitch_rate = serialInterface->getRelativeValue(PITCH_RATE); - float measured_yaw_rate = serialInterface->getRelativeValue(YAW_RATE); + yawRate = serialInterface->getRelativeValue(YAW_RATE); float measured_lateral_accel = serialInterface->getRelativeValue(ACCEL_X) - ROLL_ACCEL_COUPLING*serialInterface->getRelativeValue(ROLL_RATE); float measured_fwd_accel = serialInterface->getRelativeValue(ACCEL_Z) - @@ -115,11 +115,11 @@ void Head::UpdatePos(float frametime, SerialInterface * serialInterface, int hea if (head_mirror) { if ((Yaw < MAX_YAW) && (Yaw > MIN_YAW)) - addYaw(-measured_yaw_rate * HEAD_ROTATION_SCALE * frametime); + addYaw(-yawRate * HEAD_ROTATION_SCALE * frametime); addLean(-measured_lateral_accel * frametime * HEAD_LEAN_SCALE, -measured_fwd_accel*frametime * HEAD_LEAN_SCALE); } else { if ((Yaw < MAX_YAW) && (Yaw > MIN_YAW)) - addYaw(measured_yaw_rate * -HEAD_ROTATION_SCALE * frametime); + addYaw(yawRate * -HEAD_ROTATION_SCALE * frametime); addLean(measured_lateral_accel * frametime * -HEAD_LEAN_SCALE, measured_fwd_accel*frametime * HEAD_LEAN_SCALE); } } diff --git a/interface/src/Head.h b/interface/src/Head.h index a6aaec725c..b1e71fd9f5 100644 --- a/interface/src/Head.h +++ b/interface/src/Head.h @@ -58,6 +58,8 @@ class Head : public AgentData { float getAverageLoudness() {return averageLoudness;}; void setAverageLoudness(float al) {averageLoudness = al;}; void setLoudness(float l) {loudness = l;}; + float getLastMeasuredYaw() {return yawRate;}; + void SetNewHeadTarget(float, float); glm::vec3 getPos() { return position; }; @@ -71,7 +73,7 @@ class Head : public AgentData { float Yaw; float Roll; float PitchRate; - float YawRate; + float yawRate; float RollRate; float EyeballPitch[2]; float EyeballYaw[2]; From 4648ce033e79173cb62fe27cfed8930907270f5e Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 4 Mar 2013 10:37:55 -0800 Subject: [PATCH 39/85] remove the flanger that isn't working as expected This reverts commit a7deca0ced54e02016c1429d431fa0c25b87ef05. --- interface/src/Audio.cpp | 56 ++--------------------------------------- interface/src/Head.cpp | 6 ++--- interface/src/Head.h | 4 +-- 3 files changed, 6 insertions(+), 60 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index d376d6f164..4a5d4907ed 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -36,10 +36,6 @@ 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 int FLANGE_EFFECT_THRESHOLD = 200; -const int FLANGE_DELAY_MAX_SAMPLES = 100; -const float FLANGE_SAMPLE_WEIGHT = 0.70; - const short NUM_AUDIO_SOURCES = 2; const short ECHO_SERVER_TEST = 1; @@ -53,8 +49,6 @@ int starve_counter = 0; StDev stdev; bool stopAudioReceiveThread = false; -int samplesLeftForFlange = 0; - #define LOG_SAMPLE_DELAY 1 std::ofstream logFile; @@ -177,55 +171,9 @@ int audioCallback (const void *inputBuffer, ringBuffer->setStarted(true); // play whatever we have in the audio buffer - // if we haven't fired off the flange effect, check if we should - if (!samplesLeftForFlange && fabsf(data->linkedHead->getLastMeasuredYaw()) > FLANGE_EFFECT_THRESHOLD) { - // we should flange for one second - samplesLeftForFlange = SAMPLE_RATE; - } + memcpy(outputLeft, ringBuffer->getNextOutput(), PACKET_LENGTH_BYTES_PER_CHANNEL); + memcpy(outputRight, ringBuffer->getNextOutput() + PACKET_LENGTH_SAMPLES_PER_CHANNEL, PACKET_LENGTH_BYTES_PER_CHANNEL); - for (int s = 0; s < PACKET_LENGTH_SAMPLES_PER_CHANNEL; s++) { - - int leftSample = ringBuffer->getNextOutput()[s]; - int rightSample = ringBuffer->getNextOutput()[s + PACKET_LENGTH_SAMPLES_PER_CHANNEL]; - - if (samplesLeftForFlange > 0) { - int sampleFlangeDelay = (samplesLeftForFlange / (float) SAMPLE_RATE) * FLANGE_DELAY_MAX_SAMPLES; - - if (sampleFlangeDelay != FLANGE_DELAY_MAX_SAMPLES || s >= FLANGE_DELAY_MAX_SAMPLES) { - // we have a delayed sample to add to this sample - - int16_t *flangeFrame = ringBuffer->getNextOutput(); - int flangeIndex; - - if (s - sampleFlangeDelay < 0) { - // we need to grab the flange sample from earlier in the buffer - flangeFrame = ringBuffer->getNextOutput() - BUFFER_LENGTH_SAMPLES; - - if (flangeFrame < ringBuffer->getBuffer()) { - // we have wraparound - - flangeFrame = ringBuffer->getBuffer() + RING_BUFFER_SAMPLES - BUFFER_LENGTH_SAMPLES; - } - - flangeIndex = PACKET_LENGTH_SAMPLES_PER_CHANNEL + (s - sampleFlangeDelay); - } else { - flangeIndex = s - sampleFlangeDelay; - } - - int16_t leftFlangeSample = flangeFrame[flangeIndex]; - int16_t rightFlangeSample = flangeFrame[flangeIndex + PACKET_LENGTH_SAMPLES_PER_CHANNEL]; - - leftSample = (1 - FLANGE_SAMPLE_WEIGHT) * leftSample + (FLANGE_SAMPLE_WEIGHT * leftFlangeSample); - rightSample = (1 - FLANGE_SAMPLE_WEIGHT) * rightSample + (FLANGE_SAMPLE_WEIGHT * rightFlangeSample); - - samplesLeftForFlange--; - } - } - - outputLeft[s] = leftSample; - outputRight[s] = rightSample; - } - ringBuffer->setNextOutput(ringBuffer->getNextOutput() + PACKET_LENGTH_SAMPLES); if (ringBuffer->getNextOutput() == ringBuffer->getBuffer() + RING_BUFFER_SAMPLES) { diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index d3caf98f95..1e5b3c4203 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -87,7 +87,7 @@ void Head::UpdatePos(float frametime, SerialInterface * serialInterface, int hea const float PITCH_ACCEL_COUPLING = 0.5; const float ROLL_ACCEL_COUPLING = -1.0; float measured_pitch_rate = serialInterface->getRelativeValue(PITCH_RATE); - yawRate = serialInterface->getRelativeValue(YAW_RATE); + float measured_yaw_rate = serialInterface->getRelativeValue(YAW_RATE); float measured_lateral_accel = serialInterface->getRelativeValue(ACCEL_X) - ROLL_ACCEL_COUPLING*serialInterface->getRelativeValue(ROLL_RATE); float measured_fwd_accel = serialInterface->getRelativeValue(ACCEL_Z) - @@ -115,11 +115,11 @@ void Head::UpdatePos(float frametime, SerialInterface * serialInterface, int hea if (head_mirror) { if ((Yaw < MAX_YAW) && (Yaw > MIN_YAW)) - addYaw(-yawRate * HEAD_ROTATION_SCALE * frametime); + addYaw(-measured_yaw_rate * HEAD_ROTATION_SCALE * frametime); addLean(-measured_lateral_accel * frametime * HEAD_LEAN_SCALE, -measured_fwd_accel*frametime * HEAD_LEAN_SCALE); } else { if ((Yaw < MAX_YAW) && (Yaw > MIN_YAW)) - addYaw(yawRate * -HEAD_ROTATION_SCALE * frametime); + addYaw(measured_yaw_rate * -HEAD_ROTATION_SCALE * frametime); addLean(measured_lateral_accel * frametime * -HEAD_LEAN_SCALE, measured_fwd_accel*frametime * HEAD_LEAN_SCALE); } } diff --git a/interface/src/Head.h b/interface/src/Head.h index b1e71fd9f5..a6aaec725c 100644 --- a/interface/src/Head.h +++ b/interface/src/Head.h @@ -58,8 +58,6 @@ class Head : public AgentData { float getAverageLoudness() {return averageLoudness;}; void setAverageLoudness(float al) {averageLoudness = al;}; void setLoudness(float l) {loudness = l;}; - float getLastMeasuredYaw() {return yawRate;}; - void SetNewHeadTarget(float, float); glm::vec3 getPos() { return position; }; @@ -73,7 +71,7 @@ class Head : public AgentData { float Yaw; float Roll; float PitchRate; - float yawRate; + float YawRate; float RollRate; float EyeballPitch[2]; float EyeballYaw[2]; From 653812a79c9907c10a3e4d9230f4ec59e4bb9731 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 4 Mar 2013 11:34:38 -0800 Subject: [PATCH 40/85] explicitly define OS X base SDK and target --- CMakeLists.txt | 5 +++++ interface/CMakeLists.txt | 2 ++ 2 files changed, 7 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6e227c95f6..89e63a65e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,11 @@ cmake_minimum_required(VERSION 2.8) project(hifi) +if(APPLE) + set(CMAKE_OSX_DEPLOYMENT_TARGET 10.7) + set(CMAKE_OSX_SYSROOT macosx10.8) +endif() + add_subdirectory(space) add_subdirectory(domain) add_subdirectory(mixer) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 0685aca6cd..025f9c3674 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -12,6 +12,8 @@ if (APPLE) # link in required OS X frameworks and include the right GL headers set(CMAKE_EXE_LINKER_FLAGS "-framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework CoreServices -framework Carbon") set(GL_HEADERS "#include \n#include ") + set(CMAKE_OSX_DEPLOYMENT_TARGET 10.7) + set(CMAKE_OSX_SYSROOT macosx10.8) else (APPLE) # include the right GL headers for UNIX set(GL_HEADERS "#include \n#include \n#include ") From bb25365604a5496b61c36f8b43e8e8047de5deac Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 4 Mar 2013 12:03:36 -0800 Subject: [PATCH 41/85] don't recalculate distance coefficient for same two clients --- mixer/src/main.cpp | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index 2fb94ab71c..49ddd98bd8 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -72,6 +72,10 @@ void *sendBuffer(void *args) } } } + + int numAgents = agentList.getAgents().size(); + float distanceCoeffs[numAgents][numAgents]; + memset(distanceCoeffs, 0, sizeof(distanceCoeffs)); for (int i = 0; i < agentList.getAgents().size(); i++) { Agent *agent = &agentList.getAgents()[i]; @@ -83,17 +87,23 @@ void *sendBuffer(void *args) AudioRingBuffer *agentRingBuffer = (AudioRingBuffer *) agent->getLinkedData(); AudioRingBuffer *otherAgentBuffer = (AudioRingBuffer *)agentList.getAgents()[j].getLinkedData(); - float *agentPosition = agentRingBuffer->getPosition(); float *otherAgentPosition = otherAgentBuffer->getPosition(); // calculate the distance to the other agent - float distanceToAgent = sqrtf(powf(agentPosition[0] - otherAgentPosition[0], 2) + - powf(agentPosition[1] - otherAgentPosition[1], 2) + - powf(agentPosition[2] - otherAgentPosition[2], 2)); + // use the distance to the other agent to calculate the change in volume for this frame - float distanceCoeff = powf((logf(DISTANCE_RATIO * distanceToAgent) / logf(3)), 2); - distanceCoeff = std::max(1.0f, distanceCoeff); + int lowAgentIndex = std::min(i, j); + int highAgentIndex = std::max(i, j); + + if (distanceCoeffs[lowAgentIndex][highAgentIndex] != 0) { + float distanceToAgent = sqrtf(powf(agentPosition[0] - otherAgentPosition[0], 2) + + powf(agentPosition[1] - otherAgentPosition[1], 2) + + powf(agentPosition[2] - otherAgentPosition[2], 2)); + + distanceCoeffs[lowAgentIndex][highAgentIndex] = std::max(1.0f, powf((logf(DISTANCE_RATIO * distanceToAgent) / logf(3)), 2)); + } + // get the angle from the right-angle triangle float triangleAngle = atan2f(fabsf(agentPosition[2] - otherAgentPosition[2]), fabsf(agentPosition[0] - otherAgentPosition[0])) * (180 / M_PI); @@ -139,11 +149,11 @@ void *sendBuffer(void *args) if (s < numSamplesDelay) { // pull the earlier sample for the delayed channel - int earlierSample = delaySamplePointer[s] / distanceCoeff; + int earlierSample = delaySamplePointer[s] / distanceCoeffs[lowAgentIndex][highAgentIndex]; delayedChannel[s] = earlierSample; } - int16_t currentSample = (otherAgentBuffer->getNextOutput()[s] / distanceCoeff); + int16_t currentSample = (otherAgentBuffer->getNextOutput()[s] / distanceCoeffs[lowAgentIndex][highAgentIndex]); goodChannel[s] = currentSample; if (s + numSamplesDelay < BUFFER_LENGTH_SAMPLES_PER_CHANNEL) { From ff9eab04d9b58f99e3b49cb81aee568e28c12ac6 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 4 Mar 2013 12:25:41 -0800 Subject: [PATCH 42/85] fix iostream include --- shared/src/Agent.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shared/src/Agent.h b/shared/src/Agent.h index dafbeb768f..9a4dfde87a 100644 --- a/shared/src/Agent.h +++ b/shared/src/Agent.h @@ -9,9 +9,9 @@ #ifndef __hifi__Agent__ #define __hifi__Agent__ -#include -#include "AgentData.h" +#include #include +#include "AgentData.h" class Agent { public: From 2ebb43691d28b8d14abc330bf4432bbf50c87faa Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 4 Mar 2013 12:27:03 -0800 Subject: [PATCH 43/85] Revert "fix iostream include" This reverts commit ff9eab04d9b58f99e3b49cb81aee568e28c12ac6. --- shared/src/Agent.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shared/src/Agent.h b/shared/src/Agent.h index 9a4dfde87a..dafbeb768f 100644 --- a/shared/src/Agent.h +++ b/shared/src/Agent.h @@ -9,9 +9,9 @@ #ifndef __hifi__Agent__ #define __hifi__Agent__ -#include -#include +#include #include "AgentData.h" +#include class Agent { public: From fa53d2c39967502997ff817f79b038c44f8da36a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 4 Mar 2013 12:47:59 -0800 Subject: [PATCH 44/85] don't specify 10.8 for OS X SDK, use latest avail --- interface/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 025f9c3674..1c2c45f0e4 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -13,7 +13,7 @@ if (APPLE) set(CMAKE_EXE_LINKER_FLAGS "-framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework CoreServices -framework Carbon") set(GL_HEADERS "#include \n#include ") set(CMAKE_OSX_DEPLOYMENT_TARGET 10.7) - set(CMAKE_OSX_SYSROOT macosx10.8) + set(CMAKE_OSX_SYSROOT macosx) else (APPLE) # include the right GL headers for UNIX set(GL_HEADERS "#include \n#include \n#include ") From 5bd0b49cecd0faf74f399e14f2b2039f37b18a24 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 4 Mar 2013 12:49:19 -0800 Subject: [PATCH 45/85] general SDK specification for root CMakeLists --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 89e63a65e3..9f7bc3a473 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ project(hifi) if(APPLE) set(CMAKE_OSX_DEPLOYMENT_TARGET 10.7) - set(CMAKE_OSX_SYSROOT macosx10.8) + set(CMAKE_OSX_SYSROOT macosx) endif() add_subdirectory(space) From cbc6e07362b197adb7d9d0a03797b5d68413a900 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 4 Mar 2013 13:00:31 -0800 Subject: [PATCH 46/85] test for source of hifi-mini build failure --- CMakeLists.txt | 4 ++-- interface/CMakeLists.txt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f7bc3a473..78d3019a69 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,8 +3,8 @@ cmake_minimum_required(VERSION 2.8) project(hifi) if(APPLE) - set(CMAKE_OSX_DEPLOYMENT_TARGET 10.7) - set(CMAKE_OSX_SYSROOT macosx) + # set(CMAKE_OSX_DEPLOYMENT_TARGET 10.7) +# set(CMAKE_OSX_SYSROOT macosx) endif() add_subdirectory(space) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 1c2c45f0e4..1d0c2b7264 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -12,8 +12,8 @@ if (APPLE) # link in required OS X frameworks and include the right GL headers set(CMAKE_EXE_LINKER_FLAGS "-framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework CoreServices -framework Carbon") set(GL_HEADERS "#include \n#include ") - set(CMAKE_OSX_DEPLOYMENT_TARGET 10.7) - set(CMAKE_OSX_SYSROOT macosx) + # set(CMAKE_OSX_DEPLOYMENT_TARGET 10.7) + # set(CMAKE_OSX_SYSROOT macosx) else (APPLE) # include the right GL headers for UNIX set(GL_HEADERS "#include \n#include \n#include ") From 64ecfa3b50ab50eecbdd20f0e1627e184b4cb87c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 4 Mar 2013 13:05:03 -0800 Subject: [PATCH 47/85] Revert "test for source of hifi-mini build failure" This reverts commit cbc6e07362b197adb7d9d0a03797b5d68413a900. --- CMakeLists.txt | 4 ++-- interface/CMakeLists.txt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 78d3019a69..9f7bc3a473 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,8 +3,8 @@ cmake_minimum_required(VERSION 2.8) project(hifi) if(APPLE) - # set(CMAKE_OSX_DEPLOYMENT_TARGET 10.7) -# set(CMAKE_OSX_SYSROOT macosx) + set(CMAKE_OSX_DEPLOYMENT_TARGET 10.7) + set(CMAKE_OSX_SYSROOT macosx) endif() add_subdirectory(space) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 1d0c2b7264..1c2c45f0e4 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -12,8 +12,8 @@ if (APPLE) # link in required OS X frameworks and include the right GL headers set(CMAKE_EXE_LINKER_FLAGS "-framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework CoreServices -framework Carbon") set(GL_HEADERS "#include \n#include ") - # set(CMAKE_OSX_DEPLOYMENT_TARGET 10.7) - # set(CMAKE_OSX_SYSROOT macosx) + set(CMAKE_OSX_DEPLOYMENT_TARGET 10.7) + set(CMAKE_OSX_SYSROOT macosx) else (APPLE) # include the right GL headers for UNIX set(GL_HEADERS "#include \n#include \n#include ") From 28832177ac7b249287287461042cb42f0ad81b0f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 4 Mar 2013 13:26:11 -0800 Subject: [PATCH 48/85] force use of 10.7 SDK to make hifi-mini happy again --- CMakeLists.txt | 2 +- interface/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f7bc3a473..415fe7e101 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ project(hifi) if(APPLE) set(CMAKE_OSX_DEPLOYMENT_TARGET 10.7) - set(CMAKE_OSX_SYSROOT macosx) + set(CMAKE_OSX_SYSROOT macosx10.7) endif() add_subdirectory(space) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 1c2c45f0e4..aff2ef6fcf 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -13,7 +13,7 @@ if (APPLE) set(CMAKE_EXE_LINKER_FLAGS "-framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework CoreServices -framework Carbon") set(GL_HEADERS "#include \n#include ") set(CMAKE_OSX_DEPLOYMENT_TARGET 10.7) - set(CMAKE_OSX_SYSROOT macosx) + set(CMAKE_OSX_SYSROOT macosx10.7) else (APPLE) # include the right GL headers for UNIX set(GL_HEADERS "#include \n#include \n#include ") From 127dbf8da301865aa0ac10fa0b3a91c88c754668 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 4 Mar 2013 14:26:18 -0800 Subject: [PATCH 49/85] remove the deployment target specifier --- CMakeLists.txt | 1 - interface/CMakeLists.txt | 1 - 2 files changed, 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 415fe7e101..c4219e21e2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,6 @@ cmake_minimum_required(VERSION 2.8) project(hifi) if(APPLE) - set(CMAKE_OSX_DEPLOYMENT_TARGET 10.7) set(CMAKE_OSX_SYSROOT macosx10.7) endif() diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index aff2ef6fcf..6306138e14 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -12,7 +12,6 @@ if (APPLE) # link in required OS X frameworks and include the right GL headers set(CMAKE_EXE_LINKER_FLAGS "-framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework CoreServices -framework Carbon") set(GL_HEADERS "#include \n#include ") - set(CMAKE_OSX_DEPLOYMENT_TARGET 10.7) set(CMAKE_OSX_SYSROOT macosx10.7) else (APPLE) # include the right GL headers for UNIX From 171c919946d6bc32f32b4827cf810cb9f201743b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 4 Mar 2013 14:28:52 -0800 Subject: [PATCH 50/85] remove SDK specifiers alltogether to confirm cause of hifi-mini error --- CMakeLists.txt | 4 ---- interface/CMakeLists.txt | 1 - 2 files changed, 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c4219e21e2..6e227c95f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,10 +2,6 @@ cmake_minimum_required(VERSION 2.8) project(hifi) -if(APPLE) - set(CMAKE_OSX_SYSROOT macosx10.7) -endif() - add_subdirectory(space) add_subdirectory(domain) add_subdirectory(mixer) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 6306138e14..0685aca6cd 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -12,7 +12,6 @@ if (APPLE) # link in required OS X frameworks and include the right GL headers set(CMAKE_EXE_LINKER_FLAGS "-framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework CoreServices -framework Carbon") set(GL_HEADERS "#include \n#include ") - set(CMAKE_OSX_SYSROOT macosx10.7) else (APPLE) # include the right GL headers for UNIX set(GL_HEADERS "#include \n#include \n#include ") From 7064beba8bdf78f8a3ef3f1dbe5db339449d3795 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 4 Mar 2013 15:10:53 -0800 Subject: [PATCH 51/85] fix calcuation of distance attenuation coefficient --- mixer/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index 49ddd98bd8..dd6ad8c974 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -96,7 +96,7 @@ void *sendBuffer(void *args) int lowAgentIndex = std::min(i, j); int highAgentIndex = std::max(i, j); - if (distanceCoeffs[lowAgentIndex][highAgentIndex] != 0) { + if (distanceCoeffs[lowAgentIndex][highAgentIndex] == 0) { float distanceToAgent = sqrtf(powf(agentPosition[0] - otherAgentPosition[0], 2) + powf(agentPosition[1] - otherAgentPosition[1], 2) + powf(agentPosition[2] - otherAgentPosition[2], 2)); From 2903ff9f730037d4eb6c7be3d925f4219bf719a2 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Mon, 4 Mar 2013 17:00:30 -0800 Subject: [PATCH 52/85] Adding support for transmitter data --- interface/src/Hand.cpp | 54 +++++++++++++++++++++++++++++++++--------- interface/src/Hand.h | 4 +++- interface/src/main.cpp | 7 +++++- 3 files changed, 52 insertions(+), 13 deletions(-) diff --git a/interface/src/Hand.cpp b/interface/src/Hand.cpp index 157f0ee38e..bdbc33512c 100644 --- a/interface/src/Hand.cpp +++ b/interface/src/Hand.cpp @@ -7,6 +7,7 @@ // #include "Hand.h" +#include const float PHI = 1.618; @@ -24,12 +25,54 @@ Hand::Hand(glm::vec3 initcolor) scale.z = scale.y * 1.0; } +void Hand::reset() +{ + position.x = DEFAULT_X; + position.y = DEFAULT_Y; + position.z = DEFAULT_Z; + pitch = yaw = roll = 0; + pitchRate = yawRate = rollRate = 0; + setTarget(position); + velocity.x = velocity.y = velocity.z = 0; + transmitterPackets = 0; +} + + void Hand::addAngularVelocity (float pRate, float yRate, float rRate) { pitchRate += pRate; yawRate += yRate; rollRate += rRate; } +void Hand::processTransmitterData(char *packetData, int numBytes) { + // Read a packet from a transmitter app, process the data + float accX, accY, accZ, + graX, graY, graZ, + gyrX, gyrY, gyrZ, + linX, linY, linZ, + rot1, rot2, rot3, rot4; + sscanf((char *)packetData, "tacc %f %f %f gra %f %f %f gyr %f %f %f lin %f %f %f rot %f %f %f %f", + &accX, &accY, &accZ, + &graX, &graY, &graZ, + &gyrX, &gyrY, &gyrZ, + &linX, &linY, &linZ, + &rot1, &rot2, &rot3, &rot4); + + if (transmitterPackets++ == 0) { + gettimeofday(&transmitterTimer, NULL); + } + const int TRANSMITTER_COUNT = 100; + if (transmitterPackets % TRANSMITTER_COUNT == 0) { + // Every 100 packets, record the observed Hz of the transmitter data + timeval now; + gettimeofday(&now, NULL); + double msecsElapsed = diffclock(&transmitterTimer, &now); + std::cout << "Transmitter Hz: " << (float)TRANSMITTER_COUNT/(msecsElapsed/1000.0) << "\n"; + //memcpy(&transmitterTimer, &now, sizeof(timeval)); + transmitterTimer = now; + } +} + void Hand::render() { glPushMatrix(); @@ -44,17 +87,6 @@ void Hand::render() glPopMatrix(); } -void Hand::reset() -{ - position.x = DEFAULT_X; - position.y = DEFAULT_Y; - position.z = DEFAULT_Z; - pitch = yaw = roll = 0; - pitchRate = yawRate = rollRate = 0; - setTarget(position); - velocity.x = velocity.y = velocity.z = 0; -} - void Hand::simulate(float deltaTime) { const float VNOISE = 0.01; diff --git a/interface/src/Hand.h b/interface/src/Hand.h index 01478839ee..3769e1fd2e 100644 --- a/interface/src/Hand.h +++ b/interface/src/Hand.h @@ -28,11 +28,13 @@ public: glm::vec3 getPos() { return position; }; void setPos(glm::vec3 p) { position = p; }; void setTarget(glm::vec3 t) { target = t; }; + void processTransmitterData(char * packetData, int numBytes); private: glm::vec3 position, target, velocity, color, scale; float pitch, yaw, roll, pitchRate, yawRate, rollRate; float noise; - + timeval transmitterTimer; + int transmitterPackets; }; diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 52e602df6a..6d35793677 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -761,7 +761,12 @@ void *networkReceive(void *args) packetcount++; bytescount += bytesReceived; - agentList.processAgentData(&senderAddress, incomingPacket, bytesReceived); + if (incomingPacket[0] != 't') { + // Pass everything but transmitter data to the agent list + agentList.processAgentData(&senderAddress, incomingPacket, bytesReceived); + } else { + myHead.hand->processTransmitterData(incomingPacket, bytesReceived); + } } } From 4203fddb88c1bd7542b6f2e663f884a4578a03ff Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Mon, 4 Mar 2013 18:36:50 -0800 Subject: [PATCH 53/85] Transmitter now controls hand position and rotation. --- interface/src/Hand.cpp | 79 +++++++++++++++++++++++++----------------- interface/src/Hand.h | 2 ++ 2 files changed, 49 insertions(+), 32 deletions(-) diff --git a/interface/src/Hand.cpp b/interface/src/Hand.cpp index bdbc33512c..f7076aae64 100644 --- a/interface/src/Hand.cpp +++ b/interface/src/Hand.cpp @@ -14,6 +14,7 @@ const float PHI = 1.618; const float DEFAULT_X = 0; const float DEFAULT_Y = -1.5; const float DEFAULT_Z = 2.0; +const float DEFAULT_TRANSMITTER_HZ = 60.0; Hand::Hand(glm::vec3 initcolor) { @@ -35,8 +36,22 @@ void Hand::reset() setTarget(position); velocity.x = velocity.y = velocity.z = 0; transmitterPackets = 0; + transmitterHz = DEFAULT_TRANSMITTER_HZ; } +void Hand::render() +{ + glPushMatrix(); + glTranslatef(position.x, position.y, position.z); + glRotatef(yaw, 0, 1, 0); + glRotatef(pitch, 1, 0, 0); + glRotatef(roll, 0, 0, 1); + glColor3f(color.x, color.y, color.z); + glScalef(scale.x, scale.y, scale.z); + //glutSolidSphere(1.5, 20, 20); + glutSolidCube(1.0); + glPopMatrix(); +} void Hand::addAngularVelocity (float pRate, float yRate, float rRate) { pitchRate += pRate; @@ -67,36 +82,36 @@ void Hand::processTransmitterData(char *packetData, int numBytes) { timeval now; gettimeofday(&now, NULL); double msecsElapsed = diffclock(&transmitterTimer, &now); - std::cout << "Transmitter Hz: " << (float)TRANSMITTER_COUNT/(msecsElapsed/1000.0) << "\n"; + transmitterHz = (float)TRANSMITTER_COUNT/(msecsElapsed/1000.0); + //std::cout << "Transmitter Hz: " << (float)TRANSMITTER_COUNT/(msecsElapsed/1000.0) << "\n"; //memcpy(&transmitterTimer, &now, sizeof(timeval)); transmitterTimer = now; } -} - -void Hand::render() -{ - glPushMatrix(); - glTranslatef(position.x, position.y, position.z); - glRotatef(yaw, 0, 1, 0); - glRotatef(pitch, 1, 0, 0); - glRotatef(roll, 0, 0, 1); - glColor3f(color.x, color.y, color.z); - glScalef(scale.x, scale.y, scale.z); - //glutSolidSphere(1.5, 20, 20); - glutSolidCube(1.0); - glPopMatrix(); + // Add rotational forces to the hand + const float ANG_VEL_SENSITIVITY = 4.0; + float angVelScale = ANG_VEL_SENSITIVITY*(1.0/getTransmitterHz()); + addAngularVelocity(gyrX*angVelScale,gyrZ*angVelScale,-gyrY*angVelScale); + + // Add linear forces to the hand + const float LINEAR_VEL_SENSITIVITY = 50.0; + float linVelScale = LINEAR_VEL_SENSITIVITY*(1.0/getTransmitterHz()); + glm::vec3 linVel(linX*linVelScale, linZ*linVelScale, -linY*linVelScale); + addVelocity(linVel); + } void Hand::simulate(float deltaTime) { - const float VNOISE = 0.01; - const float RSPRING = 0.01; - const float LINEAR_SPRING_CONSTANT = 500; + const float ANGULAR_SPRING_CONSTANT = 0.25; + const float ANGULAR_DAMPING_COEFFICIENT = 5*2.0*powf(ANGULAR_SPRING_CONSTANT,0.5); + const float LINEAR_SPRING_CONSTANT = 100; const float LINEAR_DAMPING_COEFFICIENT = 2.0*powf(LINEAR_SPRING_CONSTANT,0.5); - const float RNOISE = 0.1; - + // If noise, add a bit of random velocity + const float RNOISE = 0.0; + const float VNOISE = 0.01; if (noise) { + glm::vec3 nVel(randFloat() - 0.5f, randFloat() - 0.5f, randFloat() - 0.5f); nVel *= VNOISE; addVelocity(nVel); @@ -111,24 +126,24 @@ void Hand::simulate(float deltaTime) yaw += yawRate; roll += rollRate; - // Use a spring to attempt to return the hand to the target position + // Use a linear spring to attempt to return the hand to the target position glm::vec3 springForce = target - position; springForce *= LINEAR_SPRING_CONSTANT; addVelocity(springForce * deltaTime); - // Critically damp the spring + // Critically damp the linear spring glm::vec3 dampingForce(velocity); dampingForce *= LINEAR_DAMPING_COEFFICIENT; addVelocity(-dampingForce * deltaTime); - // Decay Angular Velocity - pitchRate *= 1.0 - deltaTime; - yawRate *= 1.0 - deltaTime; - rollRate *= 1.0 - deltaTime; - - // Add spring effect to return hand rotation to zero - pitchRate -= pitch * RSPRING; - yawRate -= yaw * RSPRING; - rollRate -= roll * RSPRING; - + // Use angular spring to return hand to target rotation (0,0,0) + addAngularVelocity(-pitch * ANGULAR_SPRING_CONSTANT * deltaTime, + -yaw * ANGULAR_SPRING_CONSTANT * deltaTime, + -roll * ANGULAR_SPRING_CONSTANT * deltaTime); + + // Critically damp angular spring + addAngularVelocity(-pitchRate*ANGULAR_DAMPING_COEFFICIENT*deltaTime, + -yawRate*ANGULAR_DAMPING_COEFFICIENT*deltaTime, + -rollRate*ANGULAR_DAMPING_COEFFICIENT*deltaTime); + } \ No newline at end of file diff --git a/interface/src/Hand.h b/interface/src/Hand.h index 3769e1fd2e..aa64bc1620 100644 --- a/interface/src/Hand.h +++ b/interface/src/Hand.h @@ -29,11 +29,13 @@ public: void setPos(glm::vec3 p) { position = p; }; void setTarget(glm::vec3 t) { target = t; }; void processTransmitterData(char * packetData, int numBytes); + float getTransmitterHz() { return transmitterHz; }; private: glm::vec3 position, target, velocity, color, scale; float pitch, yaw, roll, pitchRate, yawRate, rollRate; float noise; timeval transmitterTimer; + float transmitterHz; int transmitterPackets; }; From 0fbb5345666429b008ec8d3b169b63dbbe9aaab7 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 6 Mar 2013 12:04:27 -0800 Subject: [PATCH 54/85] randomly draw 50000 voxels for glDrawElements test --- interface/src/VoxelSystem.cpp | 80 +++++++++++++++++++++++++++++++++-- interface/src/VoxelSystem.h | 4 ++ interface/src/main.cpp | 15 +------ 3 files changed, 82 insertions(+), 17 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index d654f71a5e..c20eb30fbd 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -8,6 +8,28 @@ #include "VoxelSystem.h" +const float MAX_UNIT_ANY_AXIS = 20.0f; +const float CUBE_WIDTH = 0.05f; +const int VERTICES_PER_VOXEL = 8; +const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL; +const int INDICES_PER_VOXEL = 3 * 12; + +GLfloat identityVertices[] = { -1, -1, 1, + 1, -1, 1, + 1, -1, -1, + -1, -1, -1, + 1, 1, 1, + -1, 1, 1, + -1, 1, -1, + 1, 1, -1 }; + +GLubyte identityIndices[] = { 0,1,2, 0,2,3, + 0,4,1, 0,4,5, + 0,3,6, 0,5,6, + 1,2,4, 2,4,7, + 2,3,6, 2,6,7, + 4,5,6, 4,6,7 }; + bool onSphereShell(float radius, float scale, glm::vec3 * position) { float vRadius = glm::length(*position); @@ -18,6 +40,49 @@ void VoxelSystem::init() { root = new Voxel; } +void VoxelSystem::init(int numberOfRandomVoxels) { + // create the arrays needed to pass to glDrawElements later + // position / color are random for now + + voxelsRendered = numberOfRandomVoxels; + + // there are 3 points for each vertices, 24 vertices in each cube + verticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * numberOfRandomVoxels]; + + // there are 12 triangles in each cube, with three indices for each triangle + indicesArray = new GLuint[INDICES_PER_VOXEL * numberOfRandomVoxels]; + + // new seed based on time now so voxels are different each time + srand((unsigned)time(0)); + + for (int n = 0; n < numberOfRandomVoxels; n++) { + // pick a random point for the center of the cube + glm::vec3 position = glm::vec3( + ((float) rand() / ((float) RAND_MAX / MAX_UNIT_ANY_AXIS)), + ((float) rand() / ((float) RAND_MAX / MAX_UNIT_ANY_AXIS)), + ((float) rand() / ((float) RAND_MAX / MAX_UNIT_ANY_AXIS)) + ); + + GLfloat *currentVerticesPos = verticesArray + (n * VERTEX_POINTS_PER_VOXEL); + + // fill the vertices array + for (int v = 0; v < VERTEX_POINTS_PER_VOXEL; v++) { + currentVerticesPos[v] = position[v % 3] + (identityVertices[v] * CUBE_WIDTH); + } + + // fill the indices array + int voxelIndexOffset = n * INDICES_PER_VOXEL; + GLuint *currentIndicesPos = indicesArray + voxelIndexOffset; + int startIndex = (n * VERTICES_PER_VOXEL); + + for (int i = 0; i < INDICES_PER_VOXEL; i++) { + // add indices for this side of the cube + currentIndicesPos[i] = startIndex + identityIndices[i]; + } + } + +} + // // Recursively initialize the voxel tree // @@ -118,11 +183,18 @@ int VoxelSystem::render(Voxel * voxel, float scale, glm::vec3 * distance) { return vRendered; } +void VoxelSystem::render() { + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, verticesArray); + + // draw a cube + glDrawElements(GL_TRIANGLES, 36 * voxelsRendered, GL_UNSIGNED_INT, indicesArray); + + // deactivate vertex arrays after drawing + glDisableClientState(GL_VERTEX_ARRAY); +} + void VoxelSystem::simulate(float deltaTime) { } - - - - diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 8dc3e97c8c..43b5ff18e0 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -26,13 +26,17 @@ class VoxelSystem { public: void simulate(float deltaTime); int render(Voxel * voxel, float scale, glm::vec3 * distance); + void render(); void init(); + void init(int numberOfRandomVoxels); int initVoxels(Voxel * root, float scale, glm::vec3 * position); void setVoxelsRendered(int v) {voxelsRendered = v;}; int getVoxelsRendered() {return voxelsRendered;}; Voxel * root; private: int voxelsRendered; + GLfloat *verticesArray; + GLuint *indicesArray; }; #endif diff --git a/interface/src/main.cpp b/interface/src/main.cpp index e189b5c715..1a3f560089 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -319,10 +319,7 @@ void initDisplay(void) void init(void) { - voxels.init(); - glm::vec3 position(0,0,0); - int voxelsMade = voxels.initVoxels(NULL, 10.0, &position); - std::cout << voxelsMade << " voxels made. \n"; + voxels.init(50000); myHead.setRenderYaw(start_yaw); @@ -575,15 +572,7 @@ void display(void) if (!display_head) cloud.render(); // Draw voxels - glPushMatrix(); - glTranslatef(WORLD_SIZE/2.0, WORLD_SIZE/2.0, WORLD_SIZE/2.0); - glm::vec3 distance(5.0 + location[0], 5.0 + location[1], 5.0 + location[2]); - //std::cout << "length: " << glm::length(distance) << "\n"; - int voxelsRendered = voxels.render(NULL, 10.0, &distance); - voxels.setVoxelsRendered(voxelsRendered); - //glColor4f(0,0,1,0.5); - //glutSolidCube(10.0); - glPopMatrix(); + voxels.render(); // Draw field vectors if (display_field) field.render(); From e16cd4ffc354e628a291441cdeaf7c95ced2ca12 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 6 Mar 2013 13:56:11 -0800 Subject: [PATCH 55/85] use vertex buffer objects to speed up voxel rendering --- interface/src/VoxelSystem.cpp | 44 +++++++++++++++++++++++++++++------ interface/src/VoxelSystem.h | 4 ++-- interface/src/main.cpp | 2 +- 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index c20eb30fbd..f93b667869 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -9,7 +9,7 @@ #include "VoxelSystem.h" const float MAX_UNIT_ANY_AXIS = 20.0f; -const float CUBE_WIDTH = 0.05f; +const float CUBE_WIDTH = 0.005f; const int VERTICES_PER_VOXEL = 8; const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL; const int INDICES_PER_VOXEL = 3 * 12; @@ -47,10 +47,10 @@ void VoxelSystem::init(int numberOfRandomVoxels) { voxelsRendered = numberOfRandomVoxels; // there are 3 points for each vertices, 24 vertices in each cube - verticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * numberOfRandomVoxels]; + GLfloat *verticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * numberOfRandomVoxels]; // there are 12 triangles in each cube, with three indices for each triangle - indicesArray = new GLuint[INDICES_PER_VOXEL * numberOfRandomVoxels]; + GLuint *indicesArray = new GLuint[INDICES_PER_VOXEL * numberOfRandomVoxels]; // new seed based on time now so voxels are different each time srand((unsigned)time(0)); @@ -81,6 +81,27 @@ void VoxelSystem::init(int numberOfRandomVoxels) { } } + // generate new VBO for the verticesArray + glGenBuffers(1, &vboVerticesID); + + // bind VBO in order to use + glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); + + // upload data to VBO + glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * numberOfRandomVoxels, verticesArray, GL_STATIC_DRAW); + + // generate new VBO for the indicesArray + glGenBuffers(1, &vboIndicesID); + + // bind VBO in order to use + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID); + + // upload data to VBO + glBufferData(GL_ELEMENT_ARRAY_BUFFER, numberOfRandomVoxels * INDICES_PER_VOXEL * sizeof(GLuint), indicesArray, GL_STATIC_DRAW); + + // delete the verticesArray, indicesArray + delete[] verticesArray; + delete[] indicesArray; } // @@ -184,14 +205,23 @@ int VoxelSystem::render(Voxel * voxel, float scale, glm::vec3 * distance) { } void VoxelSystem::render() { - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, verticesArray); + // bind VBOs for vertices and indices array + glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID); - // draw a cube - glDrawElements(GL_TRIANGLES, 36 * voxelsRendered, GL_UNSIGNED_INT, indicesArray); + // draw the cubes + glEnableClientState(GL_VERTEX_ARRAY); + + glVertexPointer(3, GL_FLOAT, 0, 0); + + glDrawElements(GL_TRIANGLES, 36 * voxelsRendered, GL_UNSIGNED_INT, 0); // deactivate vertex arrays after drawing glDisableClientState(GL_VERTEX_ARRAY); + + // bind with 0 to switch back to normal operation + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } void VoxelSystem::simulate(float deltaTime) { diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 43b5ff18e0..dc51164318 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -35,8 +35,8 @@ public: Voxel * root; private: int voxelsRendered; - GLfloat *verticesArray; - GLuint *indicesArray; + GLuint vboVerticesID; + GLuint vboIndicesID; }; #endif diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 1a3f560089..4dee7872ff 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -319,7 +319,7 @@ void initDisplay(void) void init(void) { - voxels.init(50000); + voxels.init(200000); myHead.setRenderYaw(start_yaw); From f27af9c9031edb7aacb6409d4fcce7cabc62194f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 6 Mar 2013 14:13:27 -0800 Subject: [PATCH 56/85] use fred's fancy new formula for distance attenuation --- mixer/src/main.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index dd6ad8c974..4d47405a2b 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -101,7 +101,7 @@ void *sendBuffer(void *args) powf(agentPosition[1] - otherAgentPosition[1], 2) + powf(agentPosition[2] - otherAgentPosition[2], 2)); - distanceCoeffs[lowAgentIndex][highAgentIndex] = std::max(1.0f, powf((logf(DISTANCE_RATIO * distanceToAgent) / logf(3)), 2)); + distanceCoeffs[lowAgentIndex][highAgentIndex] = std::min(1.0f, powf(0.5, (logf(DISTANCE_RATIO * distanceToAgent) / logf(3)) - 1)); } @@ -149,11 +149,11 @@ void *sendBuffer(void *args) if (s < numSamplesDelay) { // pull the earlier sample for the delayed channel - int earlierSample = delaySamplePointer[s] / distanceCoeffs[lowAgentIndex][highAgentIndex]; + int earlierSample = delaySamplePointer[s] * distanceCoeffs[lowAgentIndex][highAgentIndex]; delayedChannel[s] = earlierSample; } - int16_t currentSample = (otherAgentBuffer->getNextOutput()[s] / distanceCoeffs[lowAgentIndex][highAgentIndex]); + int16_t currentSample = (otherAgentBuffer->getNextOutput()[s] * distanceCoeffs[lowAgentIndex][highAgentIndex]); goodChannel[s] = currentSample; if (s + numSamplesDelay < BUFFER_LENGTH_SAMPLES_PER_CHANNEL) { @@ -200,8 +200,8 @@ void *reportAliveToDS(void *args) { gettimeofday(&lastSend, NULL); *output = 'M'; - packSocket(output + 1, 895283510, htons(MIXER_LISTEN_PORT)); -// packSocket(output + 1, 788637888, htons(MIXER_LISTEN_PORT)); +// 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); double usecToSleep = 1000000 - (usecTimestampNow() - usecTimestamp(&lastSend)); From f004479e39bf33176c9d65651c898066f07cd360 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 6 Mar 2013 14:34:14 -0800 Subject: [PATCH 57/85] bump up to 300000 voxels, with color --- interface/src/VoxelSystem.cpp | 63 +++++++++++++++++++++++------------ interface/src/VoxelSystem.h | 1 + interface/src/main.cpp | 2 +- 3 files changed, 44 insertions(+), 22 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index f93b667869..a46591d50f 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -9,9 +9,10 @@ #include "VoxelSystem.h" const float MAX_UNIT_ANY_AXIS = 20.0f; -const float CUBE_WIDTH = 0.005f; +const float CUBE_WIDTH = 0.01f; const int VERTICES_PER_VOXEL = 8; const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL; +const int COLOR_VALUES_PER_VOXEL = 3 * VERTICES_PER_VOXEL; const int INDICES_PER_VOXEL = 3 * 12; GLfloat identityVertices[] = { -1, -1, 1, @@ -40,6 +41,10 @@ void VoxelSystem::init() { root = new Voxel; } +float randomFloat(float maximumValue) { + return ((float) rand() / ((float) RAND_MAX / maximumValue)); +} + void VoxelSystem::init(int numberOfRandomVoxels) { // create the arrays needed to pass to glDrawElements later // position / color are random for now @@ -49,6 +54,9 @@ void VoxelSystem::init(int numberOfRandomVoxels) { // there are 3 points for each vertices, 24 vertices in each cube GLfloat *verticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * numberOfRandomVoxels]; + // we need a color for each vertex in each voxel + GLfloat *colorsArray = new GLfloat[COLOR_VALUES_PER_VOXEL * numberOfRandomVoxels]; + // there are 12 triangles in each cube, with three indices for each triangle GLuint *indicesArray = new GLuint[INDICES_PER_VOXEL * numberOfRandomVoxels]; @@ -58,17 +66,29 @@ void VoxelSystem::init(int numberOfRandomVoxels) { for (int n = 0; n < numberOfRandomVoxels; n++) { // pick a random point for the center of the cube glm::vec3 position = glm::vec3( - ((float) rand() / ((float) RAND_MAX / MAX_UNIT_ANY_AXIS)), - ((float) rand() / ((float) RAND_MAX / MAX_UNIT_ANY_AXIS)), - ((float) rand() / ((float) RAND_MAX / MAX_UNIT_ANY_AXIS)) + randomFloat(MAX_UNIT_ANY_AXIS * 2) - MAX_UNIT_ANY_AXIS, + randomFloat(MAX_UNIT_ANY_AXIS * 2) - MAX_UNIT_ANY_AXIS, + randomFloat(MAX_UNIT_ANY_AXIS * 2) - MAX_UNIT_ANY_AXIS ); + // fill the vertices array GLfloat *currentVerticesPos = verticesArray + (n * VERTEX_POINTS_PER_VOXEL); - // fill the vertices array for (int v = 0; v < VERTEX_POINTS_PER_VOXEL; v++) { currentVerticesPos[v] = position[v % 3] + (identityVertices[v] * CUBE_WIDTH); } + + // fill the colors array + GLfloat *currentColorPos = colorsArray + (n * COLOR_VALUES_PER_VOXEL); + float voxelR = randomFloat(1); + float voxelG = randomFloat(1); + float voxelB = randomFloat(1); + + for (int c = 0; c < VERTICES_PER_VOXEL; c++) { + currentColorPos[0 + (c * 3)] = voxelR; + currentColorPos[1 + (c * 3)] = voxelG; + currentColorPos[2 + (c * 3)] = voxelB; + } // fill the indices array int voxelIndexOffset = n * INDICES_PER_VOXEL; @@ -81,27 +101,25 @@ void VoxelSystem::init(int numberOfRandomVoxels) { } } - // generate new VBO for the verticesArray + // VBO for the verticesArray glGenBuffers(1, &vboVerticesID); - - // bind VBO in order to use glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); - - // upload data to VBO glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * numberOfRandomVoxels, verticesArray, GL_STATIC_DRAW); - // generate new VBO for the indicesArray + // VBO for colorsArray + glGenBuffers(1, &vboColorsID); + glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); + glBufferData(GL_ARRAY_BUFFER, VERTICES_PER_VOXEL * sizeof(GLfloat) * numberOfRandomVoxels, colorsArray, GL_STATIC_DRAW); + + // VBO for the indicesArray glGenBuffers(1, &vboIndicesID); - - // bind VBO in order to use glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID); - - // upload data to VBO glBufferData(GL_ELEMENT_ARRAY_BUFFER, numberOfRandomVoxels * INDICES_PER_VOXEL * sizeof(GLuint), indicesArray, GL_STATIC_DRAW); // delete the verticesArray, indicesArray delete[] verticesArray; delete[] indicesArray; + delete[] colorsArray; } // @@ -205,19 +223,22 @@ int VoxelSystem::render(Voxel * voxel, float scale, glm::vec3 * distance) { } void VoxelSystem::render() { - // bind VBOs for vertices and indices array - glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID); - // draw the cubes - glEnableClientState(GL_VERTEX_ARRAY); - + glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); glVertexPointer(3, GL_FLOAT, 0, 0); + glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); + glColorPointer(3, GL_FLOAT, 0, 0); + glDrawElements(GL_TRIANGLES, 36 * voxelsRendered, GL_UNSIGNED_INT, 0); - // deactivate vertex arrays after drawing + // deactivate vertex and color arrays after drawing glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); // bind with 0 to switch back to normal operation glBindBuffer(GL_ARRAY_BUFFER, 0); diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index dc51164318..d3a7cde77e 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -36,6 +36,7 @@ public: private: int voxelsRendered; GLuint vboVerticesID; + GLuint vboColorsID; GLuint vboIndicesID; }; diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 4dee7872ff..2bc99d8dad 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -319,7 +319,7 @@ void initDisplay(void) void init(void) { - voxels.init(200000); + voxels.init(300000); myHead.setRenderYaw(start_yaw); From f98f64e8f7e8a1f7836b3a20e3f12b0661482edd Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Wed, 6 Mar 2013 14:40:24 -0800 Subject: [PATCH 58/85] Added red 'laser pointer' to hand --- interface/src/Hand.cpp | 11 +++++++++++ interface/src/Hand.h | 2 ++ interface/src/main.cpp | 12 ++++++++---- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/interface/src/Hand.cpp b/interface/src/Hand.cpp index f7076aae64..4c6e293fc8 100644 --- a/interface/src/Hand.cpp +++ b/interface/src/Hand.cpp @@ -24,6 +24,7 @@ Hand::Hand(glm::vec3 initcolor) scale.x = 0.07; scale.y = scale.x * 5.0; scale.z = scale.y * 1.0; + renderPointer = true; } void Hand::reset() @@ -41,6 +42,7 @@ void Hand::reset() void Hand::render() { + const float POINTER_LENGTH = 10.0; glPushMatrix(); glTranslatef(position.x, position.y, position.z); glRotatef(yaw, 0, 1, 0); @@ -50,6 +52,15 @@ void Hand::render() glScalef(scale.x, scale.y, scale.z); //glutSolidSphere(1.5, 20, 20); glutSolidCube(1.0); + if (renderPointer) { + glBegin(GL_TRIANGLES); + glColor3f(1,0,0); + glNormal3f(0,-1,0); + glVertex3f(-0.4,0,0); + glVertex3f(0.4,0,0); + glVertex3f(0,0,-POINTER_LENGTH); + glEnd(); + } glPopMatrix(); } diff --git a/interface/src/Hand.h b/interface/src/Hand.h index aa64bc1620..7019cdea22 100644 --- a/interface/src/Hand.h +++ b/interface/src/Hand.h @@ -30,6 +30,7 @@ public: void setTarget(glm::vec3 t) { target = t; }; void processTransmitterData(char * packetData, int numBytes); float getTransmitterHz() { return transmitterHz; }; + void setRenderPointer(bool p) { renderPointer = p; }; private: glm::vec3 position, target, velocity, color, scale; float pitch, yaw, roll, pitchRate, yawRate, rollRate; @@ -37,6 +38,7 @@ private: timeval transmitterTimer; float transmitterHz; int transmitterPackets; + bool renderPointer; }; diff --git a/interface/src/main.cpp b/interface/src/main.cpp index e189b5c715..099a26ee33 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -98,10 +98,10 @@ ParticleSystem balls(0, false, // Wrap? 0.02, // Noise 0.3, // Size scale - 0.0 // Gravity + 0.0 // Gravity ); -Cloud cloud(0, // Particles +Cloud cloud(20000, // Particles box, // Bounding Box false // Wrap ); @@ -540,8 +540,9 @@ void display(void) glEnable (GL_DEPTH_TEST); glEnable(GL_LIGHTING); glEnable(GL_LINE_SMOOTH); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); + glPushMatrix(); glLoadIdentity(); @@ -569,6 +570,7 @@ void display(void) glColor3f(1,0,0); glutSolidSphere(0.25, 15, 15); + // Draw cloud of dots glDisable( GL_POINT_SPRITE_ARB ); glDisable( GL_TEXTURE_2D ); @@ -614,7 +616,8 @@ void display(void) //glm::vec3 test(0.5, 0.5, 0.5); //render_vector(&test); - + + glPopMatrix(); // Render 2D overlay: I/O level bar graphs and text @@ -683,6 +686,7 @@ void display(void) glPopMatrix(); + glutSwapBuffers(); framecount++; } From 89d205f304c336d0fadc65b9476c194b41bf2d30 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Wed, 6 Mar 2013 14:45:24 -0800 Subject: [PATCH 59/85] turn cloud back off --- interface/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 099a26ee33..30e75321dd 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -101,7 +101,7 @@ ParticleSystem balls(0, 0.0 // Gravity ); -Cloud cloud(20000, // Particles +Cloud cloud(0, // Particles box, // Bounding Box false // Wrap ); From 160e9f110073f4babdb4301d067ce67e282d8b6c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 6 Mar 2013 14:55:44 -0800 Subject: [PATCH 60/85] mixer needs to report its local address as EC2 box --- mixer/src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index 4d47405a2b..2d1ac025b5 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -200,8 +200,8 @@ void *reportAliveToDS(void *args) { gettimeofday(&lastSend, NULL); *output = 'M'; -// packSocket(output + 1, 895283510, htons(MIXER_LISTEN_PORT)); - packSocket(output + 1, 788637888, htons(MIXER_LISTEN_PORT)); + 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); double usecToSleep = 1000000 - (usecTimestampNow() - usecTimestamp(&lastSend)); From 26fd44f0301b66a40b259e90fdec616bfda3ed7b Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Wed, 6 Mar 2013 16:58:38 -0800 Subject: [PATCH 61/85] 100,000 voxel death star with concentric shells --- interface/src/VoxelSystem.cpp | 36 ++++++++++++++++++++++------------- interface/src/main.cpp | 5 +++-- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index a46591d50f..786c6a1d5e 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -8,8 +8,10 @@ #include "VoxelSystem.h" -const float MAX_UNIT_ANY_AXIS = 20.0f; -const float CUBE_WIDTH = 0.01f; +const float MAX_Y_AXIS = 2.0; +const float MAX_X_AXIS = 20.0; +const float MAX_Z_AXIS = 20.0; + const int VERTICES_PER_VOXEL = 8; const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL; const int COLOR_VALUES_PER_VOXEL = 3 * VERTICES_PER_VOXEL; @@ -50,7 +52,7 @@ void VoxelSystem::init(int numberOfRandomVoxels) { // position / color are random for now voxelsRendered = numberOfRandomVoxels; - + // there are 3 points for each vertices, 24 vertices in each cube GLfloat *verticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * numberOfRandomVoxels]; @@ -65,24 +67,32 @@ void VoxelSystem::init(int numberOfRandomVoxels) { for (int n = 0; n < numberOfRandomVoxels; n++) { // pick a random point for the center of the cube + const float DEATH_STAR_RADIUS = 4.0; + const float MAX_CUBE = 0.05; + float azimuth = randFloat()*2*PI; + float altitude = randFloat()*PI - PI/2; + float radius = DEATH_STAR_RADIUS; + float thisScale = MAX_CUBE*1/(float)(rand()%8 + 1); + float radius_twiddle = (DEATH_STAR_RADIUS/100)*powf(2, (float)(rand()%8)); + radius += radius_twiddle + (randFloat()*DEATH_STAR_RADIUS/12 - DEATH_STAR_RADIUS/24); glm::vec3 position = glm::vec3( - randomFloat(MAX_UNIT_ANY_AXIS * 2) - MAX_UNIT_ANY_AXIS, - randomFloat(MAX_UNIT_ANY_AXIS * 2) - MAX_UNIT_ANY_AXIS, - randomFloat(MAX_UNIT_ANY_AXIS * 2) - MAX_UNIT_ANY_AXIS + radius * cosf(azimuth) * cosf(altitude), + radius * sinf(azimuth) * cosf(altitude), + radius * sinf(altitude) ); - // fill the vertices array + // fill the vertices array, and scale the voxels GLfloat *currentVerticesPos = verticesArray + (n * VERTEX_POINTS_PER_VOXEL); - for (int v = 0; v < VERTEX_POINTS_PER_VOXEL; v++) { - currentVerticesPos[v] = position[v % 3] + (identityVertices[v] * CUBE_WIDTH); + currentVerticesPos[v] = position[v % 3] + (identityVertices[v] * thisScale); } // fill the colors array + const float MIN_BRIGHTNESS = 0.25; GLfloat *currentColorPos = colorsArray + (n * COLOR_VALUES_PER_VOXEL); - float voxelR = randomFloat(1); - float voxelG = randomFloat(1); - float voxelB = randomFloat(1); + float voxelR = MIN_BRIGHTNESS + randomFloat(1)*(1.0 - MIN_BRIGHTNESS); + float voxelG = voxelR; + float voxelB = voxelR; for (int c = 0; c < VERTICES_PER_VOXEL; c++) { currentColorPos[0 + (c * 3)] = voxelR; @@ -109,7 +119,7 @@ void VoxelSystem::init(int numberOfRandomVoxels) { // VBO for colorsArray glGenBuffers(1, &vboColorsID); glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); - glBufferData(GL_ARRAY_BUFFER, VERTICES_PER_VOXEL * sizeof(GLfloat) * numberOfRandomVoxels, colorsArray, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, COLOR_VALUES_PER_VOXEL * sizeof(GLfloat) * numberOfRandomVoxels, colorsArray, GL_STATIC_DRAW); // VBO for the indicesArray glGenBuffers(1, &vboIndicesID); diff --git a/interface/src/main.cpp b/interface/src/main.cpp index ec2be98786..36ee7ee3af 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -319,7 +319,8 @@ void initDisplay(void) void init(void) { - voxels.init(300000); + // Number of voxels to create + voxels.init(100000); myHead.setRenderYaw(start_yaw); @@ -537,7 +538,7 @@ void display(void) glEnable (GL_DEPTH_TEST); glEnable(GL_LIGHTING); glEnable(GL_LINE_SMOOTH); - //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glPushMatrix(); From 4a0aba9fb6f6087d3716d5c203ab21c479b0a55a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 7 Mar 2013 10:35:59 -0800 Subject: [PATCH 62/85] explicitly include GLUT framework for apple builds --- interface/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index d3bb79281b..d5ac0ddc7f 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -10,7 +10,7 @@ project(interface) if (APPLE) # link in required OS X frameworks and include the right GL headers - set(CMAKE_EXE_LINKER_FLAGS "-framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework CoreServices -framework Carbon") + set(CMAKE_EXE_LINKER_FLAGS "-framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework CoreServices -framework Carbon -framework GLUT") set(GL_HEADERS "#include \n#include ") else (APPLE) # include the right GL headers for UNIX From 615d1d5152f58b3820987e85e8c562ab2514e313 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 7 Mar 2013 11:05:02 -0800 Subject: [PATCH 63/85] mix together client samples, don't overwrite --- mixer/src/main.cpp | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index 2d1ac025b5..f3ee26e3e9 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -43,6 +43,15 @@ const int DOMAINSERVER_PORT = 40102; AgentList agentList(MIXER_LISTEN_PORT); +void plateauAdditionOfSamples(int16_t &mixSample, int16_t sampleToAdd) { + long sumSample = sampleToAdd + mixSample; + + long normalizedSample = std::max((long)INT16_MAX, sumSample); + normalizedSample = std::min((long)INT16_MIN, sumSample); + + mixSample = normalizedSample; +} + void *sendBuffer(void *args) { int sentBytes; @@ -144,20 +153,21 @@ void *sendBuffer(void *args) ? otherAgentBuffer->getBuffer() + RING_BUFFER_SAMPLES - numSamplesDelay : otherAgentBuffer->getNextOutput() - numSamplesDelay; + for (int s = 0; s < BUFFER_LENGTH_SAMPLES_PER_CHANNEL; s++) { if (s < numSamplesDelay) { // pull the earlier sample for the delayed channel int earlierSample = delaySamplePointer[s] * distanceCoeffs[lowAgentIndex][highAgentIndex]; - delayedChannel[s] = earlierSample; + plateauAdditionOfSamples(delayedChannel[s], earlierSample); } int16_t currentSample = (otherAgentBuffer->getNextOutput()[s] * distanceCoeffs[lowAgentIndex][highAgentIndex]); - goodChannel[s] = currentSample; + plateauAdditionOfSamples(goodChannel[s], currentSample); if (s + numSamplesDelay < BUFFER_LENGTH_SAMPLES_PER_CHANNEL) { - delayedChannel[s + numSamplesDelay] = currentSample; + plateauAdditionOfSamples(delayedChannel[s + numSamplesDelay], currentSample); } } } @@ -228,10 +238,6 @@ int main(int argc, const char * argv[]) agentList.startSilentAgentRemovalThread(); - // setup the agentSocket to report to domain server - pthread_t reportAliveThread; - pthread_create(&reportAliveThread, NULL, reportAliveToDS, NULL); - // Lookup the IP address of things we have hostnames if (atoi(DOMAIN_IP) == 0) { struct hostent* pHostInfo; @@ -247,6 +253,10 @@ int main(int argc, const char * argv[]) } else { printf("Using static domainserver IP: %s\n", DOMAIN_IP); } + + // setup the agentSocket to report to domain server + pthread_t reportAliveThread; + pthread_create(&reportAliveThread, NULL, reportAliveToDS, NULL); unsigned char *packetData = new unsigned char[MAX_PACKET_SIZE]; From c1ca2daa00d0d76e775b94d308500a0af39d47d2 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 7 Mar 2013 11:07:45 -0800 Subject: [PATCH 64/85] include stdint for INT16_MAX and INT16_MIN --- mixer/src/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index f3ee26e3e9..833e5c59eb 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include From 5fe311638e3fcc7dc08d116ddb5ab11b9c909a75 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 7 Mar 2013 11:10:16 -0800 Subject: [PATCH 65/85] fall back to the working MIN/MAX for int16_t --- mixer/src/main.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index 833e5c59eb..df45511618 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -47,8 +46,8 @@ AgentList agentList(MIXER_LISTEN_PORT); void plateauAdditionOfSamples(int16_t &mixSample, int16_t sampleToAdd) { long sumSample = sampleToAdd + mixSample; - long normalizedSample = std::max((long)INT16_MAX, sumSample); - normalizedSample = std::min((long)INT16_MIN, sumSample); + long normalizedSample = std::max(MAX_SAMPLE_VALUE, sumSample); + normalizedSample = std::min(MIN_SAMPLE_VALUE, sumSample); mixSample = normalizedSample; } From a5708c0450a5f0f75a8bec7bf76a857069922c65 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 7 Mar 2013 11:24:59 -0800 Subject: [PATCH 66/85] take proper max/min values for samples --- mixer/src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index df45511618..9631df8af0 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -46,8 +46,8 @@ AgentList agentList(MIXER_LISTEN_PORT); void plateauAdditionOfSamples(int16_t &mixSample, int16_t sampleToAdd) { long sumSample = sampleToAdd + mixSample; - long normalizedSample = std::max(MAX_SAMPLE_VALUE, sumSample); - normalizedSample = std::min(MIN_SAMPLE_VALUE, sumSample); + long normalizedSample = std::min(MAX_SAMPLE_VALUE, sumSample); + normalizedSample = std::max(MIN_SAMPLE_VALUE, sumSample); mixSample = normalizedSample; } From 686404be2bc5c8c4d49e203dda4e29a07c1e0ede Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 8 Mar 2013 14:32:06 -0800 Subject: [PATCH 67/85] add a voxel server --- CMakeLists.txt | 1 + interface/src/Util.cpp | 5 - interface/src/VoxelSystem.cpp | 281 ++++++++++++---------------------- interface/src/VoxelSystem.h | 21 ++- interface/src/main.cpp | 34 ++-- shared/src/AgentList.cpp | 8 +- shared/src/AgentList.h | 1 + shared/src/SharedUtil.cpp | 5 + shared/src/SharedUtil.h | 1 + voxel/CMakeLists.txt | 10 ++ voxel/src/main.cpp | 192 +++++++++++++++++++++++ 11 files changed, 353 insertions(+), 206 deletions(-) create mode 100644 voxel/CMakeLists.txt create mode 100644 voxel/src/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 6e227c95f6..cd284ff3e4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,4 +5,5 @@ project(hifi) add_subdirectory(space) add_subdirectory(domain) add_subdirectory(mixer) +add_subdirectory(voxel) add_subdirectory(interface) \ No newline at end of file diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index b6ea560eff..4ef06dfed4 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -55,11 +55,6 @@ float StDev::getStDev() { return 0; } - -float randFloat () { - return (rand()%10000)/10000.f; -} - // Return the azimuth angle in degrees between two points. 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; diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 786c6a1d5e..c0c6f5159f 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -7,24 +7,25 @@ // #include "VoxelSystem.h" +#include -const float MAX_Y_AXIS = 2.0; -const float MAX_X_AXIS = 20.0; -const float MAX_Z_AXIS = 20.0; +const int MAX_VOXELS_PER_SYSTEM = 500000; const int VERTICES_PER_VOXEL = 8; const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL; const int COLOR_VALUES_PER_VOXEL = 3 * VERTICES_PER_VOXEL; const int INDICES_PER_VOXEL = 3 * 12; -GLfloat identityVertices[] = { -1, -1, 1, - 1, -1, 1, - 1, -1, -1, - -1, -1, -1, - 1, 1, 1, - -1, 1, 1, - -1, 1, -1, - 1, 1, -1 }; +const float CUBE_WIDTH = 0.025f; + +float identityVertices[] = { -1, -1, 1, + 1, -1, 1, + 1, -1, -1, + -1, -1, -1, + 1, 1, 1, + -1, 1, 1, + -1, 1, -1, + 1, 1, -1 }; GLubyte identityIndices[] = { 0,1,2, 0,2,3, 0,4,1, 0,4,5, @@ -33,73 +34,71 @@ GLubyte identityIndices[] = { 0,1,2, 0,2,3, 2,3,6, 2,6,7, 4,5,6, 4,6,7 }; +VoxelSystem::VoxelSystem() { + voxelsRendered = 0; +} -bool onSphereShell(float radius, float scale, glm::vec3 * position) { - float vRadius = glm::length(*position); - return ((vRadius + scale/2.0 > radius) && (vRadius - scale/2.0 < radius)); +VoxelSystem::~VoxelSystem() { + delete[] verticesArray; + delete[] colorsArray; +} + +void VoxelSystem::parseData(void *data, int size) { + // ignore the first char, it's a V to tell us that this is voxel data + char *voxelDataPtr = (char *) data + 1; + + float *position = new float[3]; + char *color = new char[3]; + + // get pointers to position of last append of data + GLfloat *parseVerticesPtr = lastAddPointer; + GLubyte *parseColorsPtr = colorsArray + (lastAddPointer - verticesArray); + + int voxelsInData = 0; + + // pull voxels out of the received data and put them into our internal memory structure + while ((voxelDataPtr - (char *) data) < size) { + + memcpy(position, voxelDataPtr, 3 * sizeof(float)); + voxelDataPtr += 3 * sizeof(float); + memcpy(color, voxelDataPtr, 3); + voxelDataPtr += 3; + + for (int v = 0; v < VERTEX_POINTS_PER_VOXEL; v++) { + parseVerticesPtr[v] = position[v % 3] + (identityVertices[v] * CUBE_WIDTH); + } + + parseVerticesPtr += VERTEX_POINTS_PER_VOXEL; + + for (int c = 0; c < COLOR_VALUES_PER_VOXEL; c++) { + parseColorsPtr[c] = color[c % 3]; + } + + parseColorsPtr += COLOR_VALUES_PER_VOXEL; + + voxelsInData++; + } + + // increase the lastAddPointer to the new spot, increase the number of rendered voxels + lastAddPointer = parseVerticesPtr; + voxelsRendered += voxelsInData; +} + +VoxelSystem* VoxelSystem::clone() const { + // this still needs to be implemented, will need to be used if VoxelSystem is attached to agent + return NULL; } void VoxelSystem::init() { - root = new Voxel; -} - -float randomFloat(float maximumValue) { - return ((float) rand() / ((float) RAND_MAX / maximumValue)); -} - -void VoxelSystem::init(int numberOfRandomVoxels) { - // create the arrays needed to pass to glDrawElements later - // position / color are random for now + // prep the data structures for incoming voxel data + lastDrawPointer = lastAddPointer = verticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; + colorsArray = new GLubyte[COLOR_VALUES_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; - voxelsRendered = numberOfRandomVoxels; - - // there are 3 points for each vertices, 24 vertices in each cube - GLfloat *verticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * numberOfRandomVoxels]; + GLuint *indicesArray = new GLuint[INDICES_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; - // we need a color for each vertex in each voxel - GLfloat *colorsArray = new GLfloat[COLOR_VALUES_PER_VOXEL * numberOfRandomVoxels]; - - // there are 12 triangles in each cube, with three indices for each triangle - GLuint *indicesArray = new GLuint[INDICES_PER_VOXEL * numberOfRandomVoxels]; - - // new seed based on time now so voxels are different each time - srand((unsigned)time(0)); - - for (int n = 0; n < numberOfRandomVoxels; n++) { - // pick a random point for the center of the cube - const float DEATH_STAR_RADIUS = 4.0; - const float MAX_CUBE = 0.05; - float azimuth = randFloat()*2*PI; - float altitude = randFloat()*PI - PI/2; - float radius = DEATH_STAR_RADIUS; - float thisScale = MAX_CUBE*1/(float)(rand()%8 + 1); - float radius_twiddle = (DEATH_STAR_RADIUS/100)*powf(2, (float)(rand()%8)); - radius += radius_twiddle + (randFloat()*DEATH_STAR_RADIUS/12 - DEATH_STAR_RADIUS/24); - glm::vec3 position = glm::vec3( - radius * cosf(azimuth) * cosf(altitude), - radius * sinf(azimuth) * cosf(altitude), - radius * sinf(altitude) - ); - - // fill the vertices array, and scale the voxels - GLfloat *currentVerticesPos = verticesArray + (n * VERTEX_POINTS_PER_VOXEL); - for (int v = 0; v < VERTEX_POINTS_PER_VOXEL; v++) { - currentVerticesPos[v] = position[v % 3] + (identityVertices[v] * thisScale); - } - - // fill the colors array - const float MIN_BRIGHTNESS = 0.25; - GLfloat *currentColorPos = colorsArray + (n * COLOR_VALUES_PER_VOXEL); - float voxelR = MIN_BRIGHTNESS + randomFloat(1)*(1.0 - MIN_BRIGHTNESS); - float voxelG = voxelR; - float voxelB = voxelR; - - for (int c = 0; c < VERTICES_PER_VOXEL; c++) { - currentColorPos[0 + (c * 3)] = voxelR; - currentColorPos[1 + (c * 3)] = voxelG; - currentColorPos[2 + (c * 3)] = voxelB; - } - + // populate the indicesArray + // this will not change given new voxels, so we can set it all up now + for (int n = 0; n < MAX_VOXELS_PER_SYSTEM; n++) { // fill the indices array int voxelIndexOffset = n * INDICES_PER_VOXEL; GLuint *currentIndicesPos = indicesArray + voxelIndexOffset; @@ -114,136 +113,54 @@ void VoxelSystem::init(int numberOfRandomVoxels) { // VBO for the verticesArray glGenBuffers(1, &vboVerticesID); glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); - glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * numberOfRandomVoxels, verticesArray, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * MAX_VOXELS_PER_SYSTEM, NULL, GL_DYNAMIC_DRAW); // VBO for colorsArray glGenBuffers(1, &vboColorsID); glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); - glBufferData(GL_ARRAY_BUFFER, COLOR_VALUES_PER_VOXEL * sizeof(GLfloat) * numberOfRandomVoxels, colorsArray, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, COLOR_VALUES_PER_VOXEL * sizeof(GLubyte) * MAX_VOXELS_PER_SYSTEM, NULL, GL_DYNAMIC_DRAW); // VBO for the indicesArray glGenBuffers(1, &vboIndicesID); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, numberOfRandomVoxels * INDICES_PER_VOXEL * sizeof(GLuint), indicesArray, GL_STATIC_DRAW); - - // delete the verticesArray, indicesArray - delete[] verticesArray; + glBufferData(GL_ELEMENT_ARRAY_BUFFER, INDICES_PER_VOXEL * sizeof(GLuint) * MAX_VOXELS_PER_SYSTEM, indicesArray, GL_STATIC_DRAW); + + // delete the indices array that is no longer needed delete[] indicesArray; - delete[] colorsArray; -} - -// -// Recursively initialize the voxel tree -// -int VoxelSystem::initVoxels(Voxel * voxel, float scale, glm::vec3 * position) { - glm::vec3 averageColor(0,0,0); - int childrenCreated = 0; - int newVoxels = 0; - if (voxel == NULL) voxel = root; - averageColor[0] = averageColor[1] = averageColor[2] = 0.0; - - const float RADIUS = 3.9; - - // - // First, randomly decide whether to stop here without recursing for children - // - if (onSphereShell(RADIUS, scale, position) && (scale < 0.25) && (randFloat() < 0.01)) - { - voxel->color.x = 0.1; - voxel->color.y = 0.5 + randFloat()*0.5; - voxel->color.z = 0.1; - for (unsigned char i = 0; i < NUM_CHILDREN; i++) voxel->children[i] = NULL; - return 0; - } else { - // Decide whether to make kids, recurse into them - for (unsigned char i = 0; i < NUM_CHILDREN; i++) { - if (scale > 0.01) { - glm::vec3 shift(scale/2.0*((i&4)>>2)-scale/4.0, - scale/2.0*((i&2)>>1)-scale/4.0, - scale/2.0*(i&1)-scale/4.0); - *position += shift; - // Test to see whether the child is also on edge of sphere - if (onSphereShell(RADIUS, scale/2.0, position)) { - voxel->children[i] = new Voxel; - newVoxels++; - childrenCreated++; - newVoxels += initVoxels(voxel->children[i], scale/2.0, position); - averageColor += voxel->children[i]->color; - } else voxel->children[i] = NULL; - *position -= shift; - } else { - // No child made: Set pointer to null, nothing to see here. - voxel->children[i] = NULL; - } - } - if (childrenCreated > 0) { - // If there were children created, the color of this voxel node is average of children - averageColor *= 1.0/childrenCreated; - voxel->color = averageColor; - return newVoxels; - } else { - // Tested and didn't make any children, so choose my color as a leaf, return - voxel->color.x = voxel->color.y = voxel->color.z = 0.5 + randFloat()*0.5; - for (unsigned char i = 0; i < NUM_CHILDREN; i++) voxel->children[i] = NULL; - return 0; - - } - } -} - -// -// The Render Discard is the ratio of the size of the voxel to the distance from the camera -// at which the voxel will no longer be shown. Smaller = show more detail. -// - -const float RENDER_DISCARD = 0.04; //0.01; - -// -// Returns the total number of voxels actually rendered -// -int VoxelSystem::render(Voxel * voxel, float scale, glm::vec3 * distance) { - // If null passed in, start at root - if (voxel == NULL) voxel = root; - unsigned char i; - bool renderedChildren = false; - int vRendered = 0; - // Recursively render children - for (i = 0; i < NUM_CHILDREN; i++) { - glm::vec3 shift(scale/2.0*((i&4)>>2)-scale/4.0, - scale/2.0*((i&2)>>1)-scale/4.0, - scale/2.0*(i&1)-scale/4.0); - if ((voxel->children[i] != NULL) && (scale / glm::length(*distance) > RENDER_DISCARD)) { - glTranslatef(shift.x, shift.y, shift.z); - *distance += shift; - vRendered += render(voxel->children[i], scale/2.0, distance); - *distance -= shift; - glTranslatef(-shift.x, -shift.y, -shift.z); - renderedChildren = true; - } - } - // Render this voxel if the children were not rendered - if (!renderedChildren) - { - // This is the place where we need to copy this data to a VBO to make this FAST - glColor4f(voxel->color.x, voxel->color.y, voxel->color.z, 1.0); - glutSolidCube(scale); - vRendered++; - } - return vRendered; } void VoxelSystem::render() { + // check if there are new voxels to draw + int vertexValuesToDraw = lastAddPointer - lastDrawPointer; + + if (vertexValuesToDraw > 0) { + // calculate the offset into each VBO, in vertex point values + int vertexBufferOffset = lastDrawPointer - verticesArray; + + // bind the vertices VBO, copy in new data + glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); + glBufferSubData(GL_ARRAY_BUFFER, vertexBufferOffset * sizeof(float), vertexValuesToDraw * sizeof(float), lastDrawPointer); + + // bind the colors VBO, copy in new data + glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); + glBufferSubData(GL_ARRAY_BUFFER, vertexBufferOffset * sizeof(GLubyte), vertexValuesToDraw * sizeof(GLubyte), (colorsArray + (lastDrawPointer - verticesArray))); + + // increment the lastDrawPointer to the lastAddPointer value used for this draw + lastDrawPointer += vertexValuesToDraw; + } + + // tell OpenGL where to find vertex and color information glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID); - glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); glVertexPointer(3, GL_FLOAT, 0, 0); glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); - glColorPointer(3, GL_FLOAT, 0, 0); + glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0); + // draw the number of voxels we have + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID); glDrawElements(GL_TRIANGLES, 36 * voxelsRendered, GL_UNSIGNED_INT, 0); // deactivate vertex and color arrays after drawing diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index d3a7cde77e..f18a104e99 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -9,11 +9,13 @@ #ifndef __interface__Cube__ #define __interface__Cube__ +#include "InterfaceConfig.h" #include +#include +#include +#include #include "Util.h" #include "world.h" -#include "InterfaceConfig.h" -#include const int NUM_CHILDREN = 8; @@ -22,19 +24,28 @@ struct Voxel { Voxel * children[NUM_CHILDREN]; }; -class VoxelSystem { +class VoxelSystem : public AgentData { public: + VoxelSystem(); + ~VoxelSystem(); + + void parseData(void *data, int size); + VoxelSystem* clone() const; + + void init(); void simulate(float deltaTime); int render(Voxel * voxel, float scale, glm::vec3 * distance); void render(); - void init(); - void init(int numberOfRandomVoxels); int initVoxels(Voxel * root, float scale, glm::vec3 * position); void setVoxelsRendered(int v) {voxelsRendered = v;}; int getVoxelsRendered() {return voxelsRendered;}; Voxel * root; private: int voxelsRendered; + GLfloat *verticesArray; + GLubyte *colorsArray; + GLfloat *lastAddPointer; + GLfloat *lastDrawPointer; GLuint vboVerticesID; GLuint vboColorsID; GLuint vboIndicesID; diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 36ee7ee3af..9ea0ee4996 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -319,8 +319,7 @@ void initDisplay(void) void init(void) { - // Number of voxels to create - voxels.init(100000); + voxels.init(); myHead.setRenderYaw(start_yaw); @@ -333,11 +332,13 @@ void init(void) field = Field(); printf( "Field Initialized.\n" ); - if (noise_on) - { + if (noise_on) { myHead.setNoise(noise); } + char output[] = "I"; + char address[] = "10.0.0.10"; + agentList.getAgentSocket().send(address, 40106, output, 1); #ifdef MARKER_CAPTURE @@ -751,7 +752,7 @@ void key(unsigned char k, int x, int y) // Receive packets from other agents/servers and decide what to do with them! // void *networkReceive(void *args) -{ +{ sockaddr senderAddress; ssize_t bytesReceived; char *incomingPacket = new char[MAX_PACKET_SIZE]; @@ -761,11 +762,13 @@ void *networkReceive(void *args) packetcount++; bytescount += bytesReceived; - if (incomingPacket[0] != 't') { - // Pass everything but transmitter data to the agent list - agentList.processAgentData(&senderAddress, incomingPacket, bytesReceived); + if (incomingPacket[0] == 't') { + // Pass everything but transmitter data to the agent list + myHead.hand->processTransmitterData(incomingPacket, bytesReceived); + } else if (incomingPacket[0] == 'V') { + voxels.parseData(incomingPacket, bytesReceived); } else { - myHead.hand->processTransmitterData(incomingPacket, bytesReceived); + agentList.processAgentData(&senderAddress, incomingPacket, bytesReceived); } } } @@ -874,6 +877,12 @@ void audioMixerUpdate(in_addr_t newMixerAddress, in_port_t newMixerPort) { audio.updateMixerParams(newMixerAddress, newMixerPort); } +void voxelServerAddCallback(sockaddr *voxelServerAddress) { + char voxelAsk[] = "I"; + printf("Asking VS for data!\n"); + agentList.getAgentSocket().send(voxelServerAddress, voxelAsk, 1); +} + int main(int argc, char** argv) { struct ifaddrs * ifAddrStruct=NULL; @@ -929,12 +938,10 @@ int main(int argc, char** argv) // the callback for our instance of AgentList is attachNewHeadToAgent agentList.linkedDataCreateCallback = &attachNewHeadToAgent; agentList.audioMixerSocketUpdate = &audioMixerUpdate; + agentList.voxelServerAddCallback = &voxelServerAddCallback; // start the thread which checks for silent agents agentList.startSilentAgentRemovalThread(); - - // create thread for receipt of data via UDP - pthread_create(&networkReceiveThread, NULL, networkReceive, NULL); glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); @@ -958,6 +965,9 @@ int main(int argc, char** argv) init(); + // create thread for receipt of data via UDP + pthread_create(&networkReceiveThread, NULL, networkReceive, NULL); + printf( "Init() complete.\n" ); glutTimerFunc(1000, Timer, 0); diff --git a/shared/src/AgentList.cpp b/shared/src/AgentList.cpp index d1c4db24ce..49179cf1c5 100644 --- a/shared/src/AgentList.cpp +++ b/shared/src/AgentList.cpp @@ -11,7 +11,7 @@ #include #include "SharedUtil.h" -const char * SOLO_AGENT_TYPES_STRING = "M"; +const char * SOLO_AGENT_TYPES_STRING = "MV"; bool stopAgentRemovalThread = false; pthread_mutex_t vectorChangeMutex = PTHREAD_MUTEX_INITIALIZER; @@ -19,11 +19,13 @@ pthread_mutex_t vectorChangeMutex = PTHREAD_MUTEX_INITIALIZER; AgentList::AgentList() : agentSocket(AGENT_SOCKET_LISTEN_PORT) { linkedDataCreateCallback = NULL; audioMixerSocketUpdate = NULL; + voxelServerAddCallback = NULL; } AgentList::AgentList(int socketListenPort) : agentSocket(socketListenPort) { linkedDataCreateCallback = NULL; audioMixerSocketUpdate = NULL; + voxelServerAddCallback = NULL; } AgentList::~AgentList() { @@ -149,6 +151,8 @@ bool AgentList::addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, // to use the local socket information the domain server gave us sockaddr_in *localSocketIn = (sockaddr_in *)localSocket; audioMixerSocketUpdate(localSocketIn->sin_addr.s_addr, localSocketIn->sin_port); + } else if (newAgent.getType() == 'V' && voxelServerAddCallback != NULL) { + voxelServerAddCallback(localSocket); } std::cout << "Added agent - " << &newAgent << "\n"; @@ -160,7 +164,7 @@ bool AgentList::addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, return true; } else { - if (agent->getType() == 'M') { + if (agent->getType() == 'M' || agent->getType() == 'V') { // until the Audio class also uses our agentList, we need to update // the lastRecvTimeUsecs for the audio mixer so it doesn't get killed and re-added continously agent->setLastRecvTimeUsecs(usecTimestampNow()); diff --git a/shared/src/AgentList.h b/shared/src/AgentList.h index 4fb6a2d989..d4c9b69d23 100644 --- a/shared/src/AgentList.h +++ b/shared/src/AgentList.h @@ -27,6 +27,7 @@ class AgentList { void(*linkedDataCreateCallback)(Agent *); void(*audioMixerSocketUpdate)(in_addr_t, in_port_t); + void(*voxelServerAddCallback)(sockaddr *); std::vector& getAgents(); UDPSocket& getAgentSocket(); diff --git a/shared/src/SharedUtil.cpp b/shared/src/SharedUtil.cpp index d9de883024..f74f949d34 100644 --- a/shared/src/SharedUtil.cpp +++ b/shared/src/SharedUtil.cpp @@ -16,4 +16,9 @@ double usecTimestampNow() { timeval now; gettimeofday(&now, NULL); return (now.tv_sec * 1000000.0 + now.tv_usec); +} + + +float randFloat () { + return (rand()%10000)/10000.f; } \ No newline at end of file diff --git a/shared/src/SharedUtil.h b/shared/src/SharedUtil.h index c8b88a8a55..d5525ffdb9 100644 --- a/shared/src/SharedUtil.h +++ b/shared/src/SharedUtil.h @@ -14,5 +14,6 @@ double usecTimestamp(timeval *time); double usecTimestampNow(); +float randFloat(); #endif /* defined(__hifi__SharedUtil__) */ diff --git a/voxel/CMakeLists.txt b/voxel/CMakeLists.txt new file mode 100644 index 0000000000..627dafdfcd --- /dev/null +++ b/voxel/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 2.8) + +project(voxel) + +file(GLOB VOXEL_SRCS src/*.cpp src/*.h) + +add_executable(voxel ${VOXEL_SRCS}) + +include(../LinkHifiShared.cmake) +link_hifi_shared_library(voxel) \ No newline at end of file diff --git a/voxel/src/main.cpp b/voxel/src/main.cpp new file mode 100644 index 0000000000..6fed2f9d3a --- /dev/null +++ b/voxel/src/main.cpp @@ -0,0 +1,192 @@ +// +// main.cpp +// Voxel Server +// +// Created by Stephen Birara on 03/06/13. +// Copyright (c) 2012 High Fidelity, Inc. All rights reserved. +// + +#include +#include +#include +#include +#include +#include +#include + +const int VOXEL_LISTEN_PORT = 40106; + +const int NUMBER_OF_VOXELS = 250000; + +const float MAX_UNIT_ANY_AXIS = 20.0f; + +const int VERTICES_PER_VOXEL = 8; +const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL; +const int COLOR_VALUES_PER_VOXEL = 3 * VERTICES_PER_VOXEL; + +const int VOXEL_SIZE_BYTES = 3 + (3 * sizeof(float)); +const int VOXELS_PER_PACKET = (MAX_PACKET_SIZE - 1) / VOXEL_SIZE_BYTES; + +const int MIN_BRIGHTNESS = 64; +const float DEATH_STAR_RADIUS = 4.0; +const float MAX_CUBE = 0.05; + +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; + +AgentList agentList(VOXEL_LISTEN_PORT); +in_addr_t localAddress; + +unsigned char randomColorValue() { + return MIN_BRIGHTNESS + (rand() % (255 - MIN_BRIGHTNESS)) +} + +void *reportAliveToDS(void *args) { + + timeval lastSend; + unsigned char output[7]; + + while (true) { + gettimeofday(&lastSend, NULL); + + *output = 'V'; + packSocket(output + 1, localAddress, htons(VOXEL_LISTEN_PORT)); + agentList.getAgentSocket().send(DOMAIN_IP, DOMAINSERVER_PORT, output, 7); + + double usecToSleep = 1000000 - (usecTimestampNow() - usecTimestamp(&lastSend)); + + if (usecToSleep > 0) { + usleep(usecToSleep); + } else { + std::cout << "No sleep required!"; + } + } +} + +int main(int argc, const char * argv[]) +{ + // get the local address of the voxel server + struct ifaddrs * ifAddrStruct=NULL; + struct ifaddrs * ifa=NULL; + + getifaddrs(&ifAddrStruct); + + for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) { + if (ifa ->ifa_addr->sa_family==AF_INET) { // check it is IP4 + // is a valid IP4 Address + localAddress = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr; + } + } + + // Lookup the IP address of things we have hostnames + if (atoi(DOMAIN_IP) == 0) { + struct hostent* pHostInfo; + if ((pHostInfo = gethostbyname(DOMAIN_HOSTNAME)) != NULL) { + sockaddr_in tempAddress; + memcpy(&tempAddress.sin_addr, pHostInfo->h_addr_list[0], pHostInfo->h_length); + strcpy(DOMAIN_IP, inet_ntoa(tempAddress.sin_addr)); + printf("Domain server %s: %s\n", DOMAIN_HOSTNAME, DOMAIN_IP); + + } else { + printf("Failed lookup domainserver\n"); + } + } else { + printf("Using static domainserver IP: %s\n", DOMAIN_IP); + } + + // setup the agentSocket to report to domain server + pthread_t reportAliveThread; + pthread_create(&reportAliveThread, NULL, reportAliveToDS, NULL); + + // new seed based on time now so voxels are different each time + srand((unsigned)time(0)); + + // create the vertex and color arrays to send back to requesting clients + + // setup data structures for our array of points and array of colors + float *pointsArray = new float[NUMBER_OF_VOXELS * 3]; + char *colorsArray = new char[NUMBER_OF_VOXELS * 3]; + + for (int n = 0; n < NUMBER_OF_VOXELS; n++) { + + // pick a random point for the center of the cube + float azimuth = randFloat() * 2 * M_PI; + float altitude = randFloat() * M_PI - M_PI/2; + float radius = DEATH_STAR_RADIUS; + float radius_twiddle = (DEATH_STAR_RADIUS/100) * powf(2, (float)(rand()%8)); + float thisScale = MAX_CUBE * 1 / (float)(rand() % 8 + 1); + radius += radius_twiddle + (randFloat() * DEATH_STAR_RADIUS/12 - DEATH_STAR_RADIUS / 24); + + // fill the vertices array + float *currentPointsPos = pointsArray + (n * 3); + currentPointsPos[0] = radius * cosf(azimuth) * cosf(altitude); + currentPointsPos[1] = radius * sinf(azimuth) * cosf(altitude); + currentPointsPos[2] = radius * sinf(altitude); + + // fill the colors array + char *currentColorPos = colorsArray + (n * 3); + currentColorPos[0] = randomColorValue(); + currentColorPos[1] = randomColorValue(); + currentColorPos[2] = randomColorValue(); + } + + // we need space for each voxel and for the 'V' characters at the beginning of each voxel packet + int voxelDataBytes = VOXEL_SIZE_BYTES * NUMBER_OF_VOXELS + ceil(NUMBER_OF_VOXELS / VOXELS_PER_PACKET); + char *voxelData = new char[voxelDataBytes]; + + // setup the interleaved voxelData packet + for (int v = 0; v < NUMBER_OF_VOXELS; v++) { + char *startPointer = voxelData + (v * VOXEL_SIZE_BYTES) + ((v / VOXELS_PER_PACKET) + 1); + + // if this is the start of a voxel packet we need to prepend with a 'V' + if (v % VOXELS_PER_PACKET == 0) { + *(startPointer - 1) = 'V'; + } + + memcpy(startPointer, pointsArray + (v * 3), sizeof(float) * 3); + memcpy(startPointer + (3 * sizeof(float)), colorsArray + (v * 3), 3); + } + + // delete the pointsArray and colorsArray that we no longer need + delete[] pointsArray; + delete[] colorsArray; + + sockaddr_in agentPublicAddress; + + char *packetData = new char[MAX_PACKET_SIZE]; + ssize_t receivedBytes; + + int sentVoxels = 0; + + // loop to send to agents requesting data + while (true) { + if (agentList.getAgentSocket().receive((sockaddr *)&agentPublicAddress, packetData, &receivedBytes)) { + if (packetData[0] == 'I') { + printf("Sending voxels to agent at address %s\n", inet_ntoa(agentPublicAddress.sin_addr)); + + // send the agent all voxels for now + // each packet has VOXELS_PER_PACKET, unless it's the last + while (sentVoxels != NUMBER_OF_VOXELS) { + int voxelsToSend = std::min(VOXELS_PER_PACKET, NUMBER_OF_VOXELS - sentVoxels); + + agentList.getAgentSocket().send((sockaddr *)&agentPublicAddress, + voxelData + (sentVoxels * VOXEL_SIZE_BYTES) + ((sentVoxels / VOXELS_PER_PACKET)), + (voxelsToSend * VOXEL_SIZE_BYTES + 1)); + + // sleep for 500 microseconds to not overload send and have lost packets + usleep(500); + + sentVoxels += voxelsToSend; + } + + printf("Sent %d voxels to agent.\n", sentVoxels); + sentVoxels = 0; + } + } + } + + pthread_join(reportAliveThread, NULL); + + return 0; +} \ No newline at end of file From 39e81794734ac8bb83bb5150b686eba1a1147de3 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 8 Mar 2013 14:33:37 -0800 Subject: [PATCH 68/85] add a missing semicolon --- voxel/src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/voxel/src/main.cpp b/voxel/src/main.cpp index 6fed2f9d3a..689395ac5b 100644 --- a/voxel/src/main.cpp +++ b/voxel/src/main.cpp @@ -32,14 +32,14 @@ const float DEATH_STAR_RADIUS = 4.0; const float MAX_CUBE = 0.05; char DOMAIN_HOSTNAME[] = "highfidelity.below92.com"; -char DOMAIN_IP[100] = ""; // IP Address will be re-set by lookup on startup +char DOMAIN_IP[100] = "192.168.1.47"; // IP Address will be re-set by lookup on startup const int DOMAINSERVER_PORT = 40102; AgentList agentList(VOXEL_LISTEN_PORT); in_addr_t localAddress; unsigned char randomColorValue() { - return MIN_BRIGHTNESS + (rand() % (255 - MIN_BRIGHTNESS)) + return MIN_BRIGHTNESS + (rand() % (255 - MIN_BRIGHTNESS)); } void *reportAliveToDS(void *args) { From 5535b8a4f5e6f1cbe872575c3903f05e6286b158 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 8 Mar 2013 15:37:41 -0800 Subject: [PATCH 69/85] allow client to request loopback from mixer --- interface/src/Audio.cpp | 14 ++++++++++++++ interface/src/Audio.h | 4 ++++ interface/src/AudioData.cpp | 2 ++ interface/src/AudioData.h | 2 ++ interface/src/main.cpp | 7 ++++++- mixer/src/main.cpp | 26 +++++++++++++++++++++----- 6 files changed, 49 insertions(+), 6 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 4a5d4907ed..15d6240ee8 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -39,6 +39,8 @@ const short JITTER_BUFFER_SAMPLES = JITTER_BUFFER_LENGTH_MSECS * (SAMPLE_RATE / const short NUM_AUDIO_SOURCES = 2; const short ECHO_SERVER_TEST = 1; +const int AGENT_LOOPBACK_MODIFIER = 307; + const char LOCALHOST_MIXER[] = "0.0.0.0"; const char WORKCLUB_MIXER[] = "192.168.1.19"; const char EC2_WEST_MIXER[] = "54.241.92.53"; @@ -116,6 +118,10 @@ int audioCallback (const void *inputBuffer, correctedYaw += 360; } + if (data->mixerLoopbackFlag) { + correctedYaw = correctedYaw > 0 ? correctedYaw + AGENT_LOOPBACK_MODIFIER : correctedYaw - AGENT_LOOPBACK_MODIFIER; + } + memcpy(currentPacketPtr, &correctedYaw, sizeof(float)); currentPacketPtr += sizeof(float); @@ -261,6 +267,14 @@ void *receiveAudioViaUDP(void *args) { pthread_exit(0); } +void Audio::setMixerLoopbackFlag(bool newMixerLoopbackFlag) { + audioData->mixerLoopbackFlag = newMixerLoopbackFlag; +} + +bool Audio::getMixerLoopbackFlag() { + return audioData->mixerLoopbackFlag; +} + /** * Initialize portaudio and start an audio stream. * Should be called at the beginning of program exection. diff --git a/interface/src/Audio.h b/interface/src/Audio.h index 4bc93b37b0..4061d7afee 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -23,6 +23,9 @@ public: void render(); void render(int screenWidth, int screenHeight); + bool getMixerLoopbackFlag(); + void setMixerLoopbackFlag(bool newMixerLoopbackFlag); + void getInputLoudness(float * lastLoudness, float * averageLoudness); void updateMixerParams(in_addr_t mixerAddress, in_port_t mixerPort); @@ -30,6 +33,7 @@ public: bool terminate(); private: bool initialized; + AudioData *audioData; // protects constructor so that public init method is used diff --git a/interface/src/AudioData.cpp b/interface/src/AudioData.cpp index ae1b9d6517..3a2984a15a 100644 --- a/interface/src/AudioData.cpp +++ b/interface/src/AudioData.cpp @@ -17,6 +17,8 @@ AudioData::AudioData() { wasStarved = 0; measuredJitter = 0; jitterBuffer = 0; + + mixerLoopbackFlag = false; } diff --git a/interface/src/AudioData.h b/interface/src/AudioData.h index 2047ffc6e3..ef55d3a7f8 100644 --- a/interface/src/AudioData.h +++ b/interface/src/AudioData.h @@ -38,6 +38,8 @@ class AudioData { float lastInputLoudness; float averagedInputLoudness; + + bool mixerLoopbackFlag; }; #endif /* defined(__interface__AudioData__) */ diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 9ea0ee4996..d747f17002 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -720,7 +720,12 @@ void key(unsigned char k, int x, int y) } } - if (k == 'h') display_head = !display_head; + + if (k == 'h') { + display_head = !display_head; + audio.setMixerLoopbackFlag(display_head); + } + if (k == 'm') head_mirror = !head_mirror; if (k == 'f') display_field = !display_field; diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index 9631df8af0..f02ff3b325 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -37,6 +37,8 @@ const long MIN_SAMPLE_VALUE = std::numeric_limits::min(); const float DISTANCE_RATIO = 3.0/4.2; const int PHASE_DELAY_AT_90 = 20; +const int AGENT_LOOPBACK_MODIFIER = 307; + 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; @@ -89,11 +91,23 @@ void *sendBuffer(void *args) for (int i = 0; i < agentList.getAgents().size(); i++) { Agent *agent = &agentList.getAgents()[i]; + AudioRingBuffer *agentRingBuffer = (AudioRingBuffer *) agent->getLinkedData(); + float agentBearing = agentRingBuffer->getBearing(); + bool agentWantsLoopback = false; + + if (agentBearing > 180 || agentBearing < -180) { + // we were passed an invalid bearing because this agent wants loopback (pressed the H key) + agentWantsLoopback = true; + + // correct the bearing + agentBearing = agentBearing > 0 ? agentBearing - AGENT_LOOPBACK_MODIFIER : agentBearing + AGENT_LOOPBACK_MODIFIER; + } + int16_t clientMix[BUFFER_LENGTH_SAMPLES_PER_CHANNEL * 2] = {}; + for (int j = 0; j < agentList.getAgents().size(); j++) { - if (i != j) { - AudioRingBuffer *agentRingBuffer = (AudioRingBuffer *) agent->getLinkedData(); + if (i != j || ( i == j && agentWantsLoopback)) { AudioRingBuffer *otherAgentBuffer = (AudioRingBuffer *)agentList.getAgents()[j].getLinkedData(); float *agentPosition = agentRingBuffer->getPosition(); @@ -118,7 +132,9 @@ void *sendBuffer(void *args) float triangleAngle = atan2f(fabsf(agentPosition[2] - otherAgentPosition[2]), fabsf(agentPosition[0] - otherAgentPosition[0])) * (180 / M_PI); float angleToSource; - float agentBearing = agentRingBuffer->getBearing(); + if (agentWantsLoopback) { + + } // find the angle we need for calculation based on the orientation of the triangle if (otherAgentPosition[0] > agentPosition[0]) { @@ -210,8 +226,8 @@ void *reportAliveToDS(void *args) { gettimeofday(&lastSend, NULL); *output = 'M'; - packSocket(output + 1, 895283510, htons(MIXER_LISTEN_PORT)); -// packSocket(output + 1, 788637888, htons(MIXER_LISTEN_PORT)); +// 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); double usecToSleep = 1000000 - (usecTimestampNow() - usecTimestamp(&lastSend)); From 7eb0875a0bb30ee3ef993cf74b6059636dc91170 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 8 Mar 2013 15:42:31 -0800 Subject: [PATCH 70/85] include cstdlib for use of rand --- shared/src/SharedUtil.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/shared/src/SharedUtil.cpp b/shared/src/SharedUtil.cpp index f74f949d34..4515eafe40 100644 --- a/shared/src/SharedUtil.cpp +++ b/shared/src/SharedUtil.cpp @@ -7,6 +7,7 @@ // #include "SharedUtil.h" +#include double usecTimestamp(timeval *time) { return (time->tv_sec * 1000000.0 + time->tv_usec); From a161ea8dc6b048d7198dd493d4a907112d049b10 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 8 Mar 2013 15:50:48 -0800 Subject: [PATCH 71/85] mixer needs to report itself as on EC2 --- mixer/src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index f02ff3b325..b177a19a19 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -226,8 +226,8 @@ void *reportAliveToDS(void *args) { gettimeofday(&lastSend, NULL); *output = 'M'; -// packSocket(output + 1, 895283510, htons(MIXER_LISTEN_PORT)); - packSocket(output + 1, 788637888, htons(MIXER_LISTEN_PORT)); + 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); double usecToSleep = 1000000 - (usecTimestampNow() - usecTimestamp(&lastSend)); From f014fcd0ac67f2e151d887e034f4a055bc188db2 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Fri, 8 Mar 2013 15:58:49 -0800 Subject: [PATCH 72/85] transmitter tweaks --- interface/src/Hand.cpp | 45 +++++++++++++++++++++++++++++++---- interface/src/VoxelSystem.cpp | 2 ++ interface/src/main.cpp | 2 +- shared/src/AgentList.cpp | 4 +++- 4 files changed, 47 insertions(+), 6 deletions(-) diff --git a/interface/src/Hand.cpp b/interface/src/Hand.cpp index 4c6e293fc8..b0d8acf8bd 100644 --- a/interface/src/Hand.cpp +++ b/interface/src/Hand.cpp @@ -20,7 +20,7 @@ Hand::Hand(glm::vec3 initcolor) { color = initcolor; reset(); - noise = 0.2; + noise = 0.0; //0.2; scale.x = 0.07; scale.y = scale.x * 5.0; scale.z = scale.y * 1.0; @@ -42,7 +42,7 @@ void Hand::reset() void Hand::render() { - const float POINTER_LENGTH = 10.0; + const float POINTER_LENGTH = 20.0; glPushMatrix(); glTranslatef(position.x, position.y, position.z); glRotatef(yaw, 0, 1, 0); @@ -60,8 +60,27 @@ void Hand::render() glVertex3f(0.4,0,0); glVertex3f(0,0,-POINTER_LENGTH); glEnd(); + glPushMatrix(); + glTranslatef(0,0,-POINTER_LENGTH); + glutSolidCube(1.0); + glPopMatrix(); } glPopMatrix(); + + if (1) { + // Render debug info from the transmitter + /* + glPushMatrix(); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + //gluOrtho2D(0, WIDTH, HEIGHT, 0); + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + glPopMatrix(); + */ + + } + } void Hand::addAngularVelocity (float pRate, float yRate, float rRate) { @@ -100,11 +119,16 @@ void Hand::processTransmitterData(char *packetData, int numBytes) { } // Add rotational forces to the hand const float ANG_VEL_SENSITIVITY = 4.0; + const float ANG_VEL_THRESHOLD = 0.0; float angVelScale = ANG_VEL_SENSITIVITY*(1.0/getTransmitterHz()); - addAngularVelocity(gyrX*angVelScale,gyrZ*angVelScale,-gyrY*angVelScale); + //addAngularVelocity(gyrX*angVelScale,gyrZ*angVelScale,-gyrY*angVelScale); + addAngularVelocity(0, + fabs(gyrZ*angVelScale)>ANG_VEL_THRESHOLD?gyrZ*angVelScale:0, + 0); // Add linear forces to the hand - const float LINEAR_VEL_SENSITIVITY = 50.0; + //const float LINEAR_VEL_SENSITIVITY = 50.0; + const float LINEAR_VEL_SENSITIVITY = 0.0; float linVelScale = LINEAR_VEL_SENSITIVITY*(1.0/getTransmitterHz()); glm::vec3 linVel(linX*linVelScale, linZ*linVelScale, -linY*linVelScale); addVelocity(linVel); @@ -137,6 +161,8 @@ void Hand::simulate(float deltaTime) yaw += yawRate; roll += rollRate; + // The spring method + if (0) { // Use a linear spring to attempt to return the hand to the target position glm::vec3 springForce = target - position; springForce *= LINEAR_SPRING_CONSTANT; @@ -156,5 +182,16 @@ void Hand::simulate(float deltaTime) addAngularVelocity(-pitchRate*ANGULAR_DAMPING_COEFFICIENT*deltaTime, -yawRate*ANGULAR_DAMPING_COEFFICIENT*deltaTime, -rollRate*ANGULAR_DAMPING_COEFFICIENT*deltaTime); + } + + // The absolute threshold method + if (1) { + const float YAW_LIMIT = 20; + if (yaw > YAW_LIMIT) { yaw = YAW_LIMIT; yawRate = 0.0; } + if (yaw < -YAW_LIMIT) { yaw = -YAW_LIMIT; yawRate = 0.0; } + // Damp Yaw Rate + yawRate *= 0.99; + } + } \ No newline at end of file diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 786c6a1d5e..4918f0bbf9 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -244,6 +244,8 @@ void VoxelSystem::render() { glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); glColorPointer(3, GL_FLOAT, 0, 0); + glNormal3f(0, 1, 0); + glDrawElements(GL_TRIANGLES, 36 * voxelsRendered, GL_UNSIGNED_INT, 0); // deactivate vertex and color arrays after drawing diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 36ee7ee3af..0554d4ffff 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -101,7 +101,7 @@ ParticleSystem balls(0, 0.0 // Gravity ); -Cloud cloud(0, // Particles +Cloud cloud(0, // Particles box, // Bounding Box false // Wrap ); diff --git a/shared/src/AgentList.cpp b/shared/src/AgentList.cpp index d1c4db24ce..b58477d2f5 100644 --- a/shared/src/AgentList.cpp +++ b/shared/src/AgentList.cpp @@ -55,13 +55,15 @@ void AgentList::processAgentData(sockaddr *senderAddress, void *packetData, size case 'P': { // ping from another agent + //std::cout << "Got ping from " << inet_ntoa(((sockaddr_in *)senderAddress)->sin_addr) << "\n"; char reply[] = "R"; - agentSocket.send(senderAddress, reply, 1); + agentSocket.send(senderAddress, reply, 1); break; } case 'R': { // ping reply from another agent + //std::cout << "Got ping reply from " << inet_ntoa(((sockaddr_in *)senderAddress)->sin_addr) << "\n"; handlePingReply(senderAddress); break; } From 5652d0dcd398ce565362a0a166fa0e8e69af403c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 8 Mar 2013 17:18:28 -0800 Subject: [PATCH 73/85] add a flange effect when turning head with gyros --- interface/src/Audio.cpp | 57 ++++++++++++++++++++++++++++++++++------- interface/src/Head.cpp | 6 ++--- interface/src/Head.h | 3 ++- voxel/src/main.cpp | 2 +- 4 files changed, 54 insertions(+), 14 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 15d6240ee8..7db5a87ee5 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -36,20 +36,18 @@ 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 short NUM_AUDIO_SOURCES = 2; -const short ECHO_SERVER_TEST = 1; +const int FLANGE_EFFECT_THRESHOLD = 200; +const float FLANGE_RATE = 4; +const float FLANGE_SAMPLE_WEIGHT = 0.50; const int AGENT_LOOPBACK_MODIFIER = 307; -const char LOCALHOST_MIXER[] = "0.0.0.0"; -const char WORKCLUB_MIXER[] = "192.168.1.19"; -const char EC2_WEST_MIXER[] = "54.241.92.53"; - const int AUDIO_UDP_LISTEN_PORT = 55444; int starve_counter = 0; StDev stdev; bool stopAudioReceiveThread = false; +int samplesLeftForFlange = 0; #define LOG_SAMPLE_DELAY 1 @@ -177,8 +175,49 @@ int audioCallback (const void *inputBuffer, ringBuffer->setStarted(true); // play whatever we have in the audio buffer - memcpy(outputLeft, ringBuffer->getNextOutput(), PACKET_LENGTH_BYTES_PER_CHANNEL); - memcpy(outputRight, ringBuffer->getNextOutput() + PACKET_LENGTH_SAMPLES_PER_CHANNEL, PACKET_LENGTH_BYTES_PER_CHANNEL); + // if we haven't fired off the flange effect, check if we should + if (!samplesLeftForFlange && fabsf(data->linkedHead->getLastMeasuredYaw()) > FLANGE_EFFECT_THRESHOLD) { + // we should flange for one second + samplesLeftForFlange = SAMPLE_RATE; + } + + for (int s = 0; s < PACKET_LENGTH_SAMPLES_PER_CHANNEL; s++) { + + int leftSample = ringBuffer->getNextOutput()[s]; + int rightSample = ringBuffer->getNextOutput()[s + PACKET_LENGTH_SAMPLES_PER_CHANNEL]; + + if (samplesLeftForFlange > 0) { + float exponent = (SAMPLE_RATE - samplesLeftForFlange - (SAMPLE_RATE / FLANGE_RATE)) / (SAMPLE_RATE / FLANGE_RATE); + int sampleFlangeDelay = (SAMPLE_RATE / 1000.0) * powf(2, exponent); + + if (samplesLeftForFlange != SAMPLE_RATE || s >= (SAMPLE_RATE / 2000)) { + // we have a delayed sample to add to this sample + + int16_t *flangeFrame = ringBuffer->getNextOutput(); + int flangeIndex = s - sampleFlangeDelay; + + if (flangeIndex < 0) { + // we need to grab the flange sample from earlier in the buffer + flangeFrame = ringBuffer->getNextOutput() != ringBuffer->getBuffer() + ? ringBuffer->getNextOutput() - PACKET_LENGTH_SAMPLES + : ringBuffer->getNextOutput() + RING_BUFFER_SAMPLES - PACKET_LENGTH_SAMPLES; + + flangeIndex = PACKET_LENGTH_SAMPLES_PER_CHANNEL + (s - sampleFlangeDelay); + } + + int16_t leftFlangeSample = flangeFrame[flangeIndex]; + int16_t rightFlangeSample = flangeFrame[flangeIndex + PACKET_LENGTH_SAMPLES_PER_CHANNEL]; + + leftSample = (1 - FLANGE_SAMPLE_WEIGHT) * leftSample + (FLANGE_SAMPLE_WEIGHT * leftFlangeSample); + rightSample = (1 - FLANGE_SAMPLE_WEIGHT) * rightSample + (FLANGE_SAMPLE_WEIGHT * rightFlangeSample); + + samplesLeftForFlange--; + } + } + + outputLeft[s] = leftSample; + outputRight[s] = rightSample; + } ringBuffer->setNextOutput(ringBuffer->getNextOutput() + PACKET_LENGTH_SAMPLES); @@ -336,7 +375,7 @@ void Audio::getInputLoudness(float * lastLoudness, float * averageLoudness) { void Audio::render(int screenWidth, int screenHeight) { - if (initialized && ECHO_SERVER_TEST) { + if (initialized) { glBegin(GL_LINES); glColor3f(1,1,1); diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index 1e5b3c4203..d3caf98f95 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -87,7 +87,7 @@ void Head::UpdatePos(float frametime, SerialInterface * serialInterface, int hea const float PITCH_ACCEL_COUPLING = 0.5; const float ROLL_ACCEL_COUPLING = -1.0; float measured_pitch_rate = serialInterface->getRelativeValue(PITCH_RATE); - float measured_yaw_rate = serialInterface->getRelativeValue(YAW_RATE); + yawRate = serialInterface->getRelativeValue(YAW_RATE); float measured_lateral_accel = serialInterface->getRelativeValue(ACCEL_X) - ROLL_ACCEL_COUPLING*serialInterface->getRelativeValue(ROLL_RATE); float measured_fwd_accel = serialInterface->getRelativeValue(ACCEL_Z) - @@ -115,11 +115,11 @@ void Head::UpdatePos(float frametime, SerialInterface * serialInterface, int hea if (head_mirror) { if ((Yaw < MAX_YAW) && (Yaw > MIN_YAW)) - addYaw(-measured_yaw_rate * HEAD_ROTATION_SCALE * frametime); + addYaw(-yawRate * HEAD_ROTATION_SCALE * frametime); addLean(-measured_lateral_accel * frametime * HEAD_LEAN_SCALE, -measured_fwd_accel*frametime * HEAD_LEAN_SCALE); } else { if ((Yaw < MAX_YAW) && (Yaw > MIN_YAW)) - addYaw(measured_yaw_rate * -HEAD_ROTATION_SCALE * frametime); + addYaw(yawRate * -HEAD_ROTATION_SCALE * frametime); addLean(measured_lateral_accel * frametime * -HEAD_LEAN_SCALE, measured_fwd_accel*frametime * HEAD_LEAN_SCALE); } } diff --git a/interface/src/Head.h b/interface/src/Head.h index a6aaec725c..2b1863b2bd 100644 --- a/interface/src/Head.h +++ b/interface/src/Head.h @@ -58,6 +58,7 @@ class Head : public AgentData { float getAverageLoudness() {return averageLoudness;}; void setAverageLoudness(float al) {averageLoudness = al;}; void setLoudness(float l) {loudness = l;}; + float getLastMeasuredYaw() {return yawRate;}; void SetNewHeadTarget(float, float); glm::vec3 getPos() { return position; }; @@ -71,7 +72,7 @@ class Head : public AgentData { float Yaw; float Roll; float PitchRate; - float YawRate; + float yawRate; float RollRate; float EyeballPitch[2]; float EyeballYaw[2]; diff --git a/voxel/src/main.cpp b/voxel/src/main.cpp index 689395ac5b..0a8fdf5d19 100644 --- a/voxel/src/main.cpp +++ b/voxel/src/main.cpp @@ -32,7 +32,7 @@ const float DEATH_STAR_RADIUS = 4.0; const float MAX_CUBE = 0.05; char DOMAIN_HOSTNAME[] = "highfidelity.below92.com"; -char DOMAIN_IP[100] = "192.168.1.47"; // 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; AgentList agentList(VOXEL_LISTEN_PORT); From 5d02d563b304bd51456ad2464b39b42929800891 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Sun, 10 Mar 2013 15:04:23 -0700 Subject: [PATCH 74/85] remove the flange until it's ready for primetime This reverts commit 5652d0dcd398ce565362a0a166fa0e8e69af403c. --- interface/src/Audio.cpp | 57 +++++++---------------------------------- interface/src/Head.cpp | 6 ++--- interface/src/Head.h | 3 +-- voxel/src/main.cpp | 2 +- 4 files changed, 14 insertions(+), 54 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 7db5a87ee5..15d6240ee8 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -36,18 +36,20 @@ 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 int FLANGE_EFFECT_THRESHOLD = 200; -const float FLANGE_RATE = 4; -const float FLANGE_SAMPLE_WEIGHT = 0.50; +const short NUM_AUDIO_SOURCES = 2; +const short ECHO_SERVER_TEST = 1; const int AGENT_LOOPBACK_MODIFIER = 307; +const char LOCALHOST_MIXER[] = "0.0.0.0"; +const char WORKCLUB_MIXER[] = "192.168.1.19"; +const char EC2_WEST_MIXER[] = "54.241.92.53"; + const int AUDIO_UDP_LISTEN_PORT = 55444; int starve_counter = 0; StDev stdev; bool stopAudioReceiveThread = false; -int samplesLeftForFlange = 0; #define LOG_SAMPLE_DELAY 1 @@ -175,49 +177,8 @@ int audioCallback (const void *inputBuffer, ringBuffer->setStarted(true); // play whatever we have in the audio buffer - // if we haven't fired off the flange effect, check if we should - if (!samplesLeftForFlange && fabsf(data->linkedHead->getLastMeasuredYaw()) > FLANGE_EFFECT_THRESHOLD) { - // we should flange for one second - samplesLeftForFlange = SAMPLE_RATE; - } - - for (int s = 0; s < PACKET_LENGTH_SAMPLES_PER_CHANNEL; s++) { - - int leftSample = ringBuffer->getNextOutput()[s]; - int rightSample = ringBuffer->getNextOutput()[s + PACKET_LENGTH_SAMPLES_PER_CHANNEL]; - - if (samplesLeftForFlange > 0) { - float exponent = (SAMPLE_RATE - samplesLeftForFlange - (SAMPLE_RATE / FLANGE_RATE)) / (SAMPLE_RATE / FLANGE_RATE); - int sampleFlangeDelay = (SAMPLE_RATE / 1000.0) * powf(2, exponent); - - if (samplesLeftForFlange != SAMPLE_RATE || s >= (SAMPLE_RATE / 2000)) { - // we have a delayed sample to add to this sample - - int16_t *flangeFrame = ringBuffer->getNextOutput(); - int flangeIndex = s - sampleFlangeDelay; - - if (flangeIndex < 0) { - // we need to grab the flange sample from earlier in the buffer - flangeFrame = ringBuffer->getNextOutput() != ringBuffer->getBuffer() - ? ringBuffer->getNextOutput() - PACKET_LENGTH_SAMPLES - : ringBuffer->getNextOutput() + RING_BUFFER_SAMPLES - PACKET_LENGTH_SAMPLES; - - flangeIndex = PACKET_LENGTH_SAMPLES_PER_CHANNEL + (s - sampleFlangeDelay); - } - - int16_t leftFlangeSample = flangeFrame[flangeIndex]; - int16_t rightFlangeSample = flangeFrame[flangeIndex + PACKET_LENGTH_SAMPLES_PER_CHANNEL]; - - leftSample = (1 - FLANGE_SAMPLE_WEIGHT) * leftSample + (FLANGE_SAMPLE_WEIGHT * leftFlangeSample); - rightSample = (1 - FLANGE_SAMPLE_WEIGHT) * rightSample + (FLANGE_SAMPLE_WEIGHT * rightFlangeSample); - - samplesLeftForFlange--; - } - } - - outputLeft[s] = leftSample; - outputRight[s] = rightSample; - } + memcpy(outputLeft, ringBuffer->getNextOutput(), PACKET_LENGTH_BYTES_PER_CHANNEL); + memcpy(outputRight, ringBuffer->getNextOutput() + PACKET_LENGTH_SAMPLES_PER_CHANNEL, PACKET_LENGTH_BYTES_PER_CHANNEL); ringBuffer->setNextOutput(ringBuffer->getNextOutput() + PACKET_LENGTH_SAMPLES); @@ -375,7 +336,7 @@ void Audio::getInputLoudness(float * lastLoudness, float * averageLoudness) { void Audio::render(int screenWidth, int screenHeight) { - if (initialized) { + if (initialized && ECHO_SERVER_TEST) { glBegin(GL_LINES); glColor3f(1,1,1); diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index d3caf98f95..1e5b3c4203 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -87,7 +87,7 @@ void Head::UpdatePos(float frametime, SerialInterface * serialInterface, int hea const float PITCH_ACCEL_COUPLING = 0.5; const float ROLL_ACCEL_COUPLING = -1.0; float measured_pitch_rate = serialInterface->getRelativeValue(PITCH_RATE); - yawRate = serialInterface->getRelativeValue(YAW_RATE); + float measured_yaw_rate = serialInterface->getRelativeValue(YAW_RATE); float measured_lateral_accel = serialInterface->getRelativeValue(ACCEL_X) - ROLL_ACCEL_COUPLING*serialInterface->getRelativeValue(ROLL_RATE); float measured_fwd_accel = serialInterface->getRelativeValue(ACCEL_Z) - @@ -115,11 +115,11 @@ void Head::UpdatePos(float frametime, SerialInterface * serialInterface, int hea if (head_mirror) { if ((Yaw < MAX_YAW) && (Yaw > MIN_YAW)) - addYaw(-yawRate * HEAD_ROTATION_SCALE * frametime); + addYaw(-measured_yaw_rate * HEAD_ROTATION_SCALE * frametime); addLean(-measured_lateral_accel * frametime * HEAD_LEAN_SCALE, -measured_fwd_accel*frametime * HEAD_LEAN_SCALE); } else { if ((Yaw < MAX_YAW) && (Yaw > MIN_YAW)) - addYaw(yawRate * -HEAD_ROTATION_SCALE * frametime); + addYaw(measured_yaw_rate * -HEAD_ROTATION_SCALE * frametime); addLean(measured_lateral_accel * frametime * -HEAD_LEAN_SCALE, measured_fwd_accel*frametime * HEAD_LEAN_SCALE); } } diff --git a/interface/src/Head.h b/interface/src/Head.h index 2b1863b2bd..a6aaec725c 100644 --- a/interface/src/Head.h +++ b/interface/src/Head.h @@ -58,7 +58,6 @@ class Head : public AgentData { float getAverageLoudness() {return averageLoudness;}; void setAverageLoudness(float al) {averageLoudness = al;}; void setLoudness(float l) {loudness = l;}; - float getLastMeasuredYaw() {return yawRate;}; void SetNewHeadTarget(float, float); glm::vec3 getPos() { return position; }; @@ -72,7 +71,7 @@ class Head : public AgentData { float Yaw; float Roll; float PitchRate; - float yawRate; + float YawRate; float RollRate; float EyeballPitch[2]; float EyeballYaw[2]; diff --git a/voxel/src/main.cpp b/voxel/src/main.cpp index 0a8fdf5d19..689395ac5b 100644 --- a/voxel/src/main.cpp +++ b/voxel/src/main.cpp @@ -32,7 +32,7 @@ const float DEATH_STAR_RADIUS = 4.0; const float MAX_CUBE = 0.05; char DOMAIN_HOSTNAME[] = "highfidelity.below92.com"; -char DOMAIN_IP[100] = ""; // IP Address will be re-set by lookup on startup +char DOMAIN_IP[100] = "192.168.1.47"; // IP Address will be re-set by lookup on startup const int DOMAINSERVER_PORT = 40102; AgentList agentList(VOXEL_LISTEN_PORT); From 593e53a5fcad245f985fad99c5bc84dca9ffbb22 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 11 Mar 2013 11:53:14 -0700 Subject: [PATCH 75/85] drop mixer jitter buffer to 2 ms --- mixer/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index b177a19a19..21143b80f9 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -20,7 +20,7 @@ const unsigned short MIXER_LISTEN_PORT = 55443; const float SAMPLE_RATE = 22050.0; -const short JITTER_BUFFER_MSECS = 20; +const short JITTER_BUFFER_MSECS = 2; const short JITTER_BUFFER_SAMPLES = JITTER_BUFFER_MSECS * (SAMPLE_RATE / 1000.0); const int BUFFER_LENGTH_BYTES = 1024; From 674bd8d798586755503b0e645c1bc0d8b6d82963 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Mon, 11 Mar 2013 16:19:55 -0700 Subject: [PATCH 76/85] transmitter full movement, and audio jitter buffer tweaks/debugging data --- interface/src/Audio.cpp | 70 ++++++++++++++++++++++++++++++----------- interface/src/Hand.cpp | 37 +++++++++++++++++----- interface/src/Hand.h | 2 +- interface/src/Head.cpp | 4 +-- interface/src/Head.h | 2 +- interface/src/main.cpp | 4 +-- 6 files changed, 88 insertions(+), 31 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 7db5a87ee5..b03d96f5ab 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -14,10 +14,13 @@ #include #include "Audio.h" #include "Util.h" +#include #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 diff --git a/interface/src/Hand.cpp b/interface/src/Hand.cpp index b0d8acf8bd..ea57c91a9b 100644 --- a/interface/src/Hand.cpp +++ b/interface/src/Hand.cpp @@ -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; } } \ No newline at end of file diff --git a/interface/src/Hand.h b/interface/src/Hand.h index 7019cdea22..3c32c3553d 100644 --- a/interface/src/Hand.h +++ b/interface/src/Hand.h @@ -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; }; diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index d3caf98f95..029653592a 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -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) { diff --git a/interface/src/Head.h b/interface/src/Head.h index 2b1863b2bd..bf905c93d4 100644 --- a/interface/src/Head.h +++ b/interface/src/Head.h @@ -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 diff --git a/interface/src/main.cpp b/interface/src/main.cpp index df4d95b7da..abe1206afa 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -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); From 74452b7cc5a18106fbd421831d787716e64d528a Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Mon, 11 Mar 2013 16:24:55 -0700 Subject: [PATCH 77/85] manual merge removed ECHO_SERVER_TEST --- interface/src/Audio.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index b1176556f3..40c9faac7f 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -42,8 +42,6 @@ const short JITTER_BUFFER_SAMPLES = JITTER_BUFFER_LENGTH_MSECS * const float AUDIO_CALLBACK_MSECS = (float)BUFFER_LENGTH_SAMPLES / (float)SAMPLE_RATE * 1000.0; -const short NUM_AUDIO_SOURCES = 2; -const short ECHO_SERVER_TEST = 1; const int AGENT_LOOPBACK_MODIFIER = 307; @@ -365,7 +363,7 @@ void Audio::getInputLoudness(float * lastLoudness, float * averageLoudness) { void Audio::render(int screenWidth, int screenHeight) { - if (initialized && ECHO_SERVER_TEST) { + if (initialized) { glBegin(GL_LINES); glColor3f(1,1,1); From 5f393734e02f8fbffcd873be5f6ef352584af0ca Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 11 Mar 2013 17:12:24 -0700 Subject: [PATCH 78/85] print out difference between buffer callbacks on mixer --- mixer/src/main.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index 21143b80f9..3196cded08 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -58,13 +58,17 @@ void *sendBuffer(void *args) { int sentBytes; int nextFrame = 0; - timeval startTime; + timeval startTime, lastSend; gettimeofday(&startTime, NULL); + gettimeofday(&lastSend, NULL); while (true) { sentBytes = 0; + printf("Last send was %f us ago", usecTimestampNow() - usecTimestamp(&lastSend)); + gettimeofday(&lastSend, NULL); + for (int i = 0; i < agentList.getAgents().size(); i++) { AudioRingBuffer *agentBuffer = (AudioRingBuffer *) agentList.getAgents()[i].getLinkedData(); From eaf27a942efc8df31a25b5858c9df48cf8f6db44 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 11 Mar 2013 17:18:49 -0700 Subject: [PATCH 79/85] add trailing new line to mixer output --- mixer/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index 3196cded08..155f63f9e0 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -66,7 +66,7 @@ void *sendBuffer(void *args) while (true) { sentBytes = 0; - printf("Last send was %f us ago", usecTimestampNow() - usecTimestamp(&lastSend)); + printf("Last send was %f ms ago\n", (usecTimestampNow() - usecTimestamp(&lastSend)) / 1000); gettimeofday(&lastSend, NULL); for (int i = 0; i < agentList.getAgents().size(); i++) { From 4be337d34bc6b4d6797fd8f20d41f910fb86c5e1 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 11 Mar 2013 17:27:27 -0700 Subject: [PATCH 80/85] only hold the threshold number of frames for audio output --- interface/src/Audio.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 40c9faac7f..60f28ca5df 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -193,6 +193,21 @@ int audioCallback (const void *inputBuffer, } // play whatever we have in the audio buffer + // check if we have more than we need to play out + int thresholdFrames = ceilf((PACKET_LENGTH_SAMPLES + JITTER_BUFFER_SAMPLES) / (float)PACKET_LENGTH_SAMPLES); + int thresholdSamples = thresholdFrames * PACKET_LENGTH_SAMPLES; + + if (ringBuffer->diffLastWriteNextOutput() > thresholdSamples) { + // we need to push the next output forwards + int samplesToPush = ringBuffer->diffLastWriteNextOutput() - thresholdSamples; + + if (ringBuffer->getNextOutput() + samplesToPush > ringBuffer->getBuffer()) { + ringBuffer->setNextOutput(ringBuffer->getBuffer() + (samplesToPush - (ringBuffer->getBuffer() + RING_BUFFER_SAMPLES - ringBuffer->getNextOutput()))); + } else { + ringBuffer->setNextOutput(ringBuffer->getNextOutput() + samplesToPush); + } + } + memcpy(outputLeft, ringBuffer->getNextOutput(), PACKET_LENGTH_BYTES_PER_CHANNEL); memcpy(outputRight, ringBuffer->getNextOutput() + PACKET_LENGTH_SAMPLES_PER_CHANNEL, PACKET_LENGTH_BYTES_PER_CHANNEL); From 14e3160d502a2afa60728da730f5a8ef1d38d43c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 11 Mar 2013 17:46:57 -0700 Subject: [PATCH 81/85] only keep the threshold number of frames on mixer as well --- mixer/src/main.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index 155f63f9e0..5735b6e03d 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -81,6 +81,22 @@ void *sendBuffer(void *args) printf("Buffer %d starved.\n", i); agentBuffer->setStarted(false); } 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 agentBuffer->setStarted(true); agentBuffer->setAddedToMix(true); From 73f6d9311dd785d5cfaed754cded6f2fb392d086 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 11 Mar 2013 18:56:14 -0700 Subject: [PATCH 82/85] local loopback test from mixer for sanity check --- mixer/src/main.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index 5735b6e03d..50b7b554fc 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -39,6 +39,8 @@ const int PHASE_DELAY_AT_90 = 20; const int AGENT_LOOPBACK_MODIFIER = 307; +const int LOOPBACK_SANITY_CHECK = 1; + 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; @@ -299,14 +301,24 @@ int main(int argc, const char * argv[]) pthread_t sendBufferThread; pthread_create(&sendBufferThread, NULL, sendBuffer, NULL); + int16_t *loopbackAudioPacket; + if (LOOPBACK_SANITY_CHECK) { + loopbackAudioPacket = new int16_t[1024]; + } + sockaddr *agentAddress = new sockaddr; while (true) { if(agentList.getAgentSocket().receive(agentAddress, packetData, &receivedBytes)) { if (packetData[0] == 'I') { // add or update the existing interface agent - agentList.addOrUpdateAgent(agentAddress, agentAddress, packetData[0]); - agentList.updateAgentWithData(agentAddress, (void *)packetData, receivedBytes); + if (!LOOPBACK_SANITY_CHECK) { + 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); + } } } } From 83952e7e32968252f793a59b28ce3782bb1343f6 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 11 Mar 2013 19:10:49 -0700 Subject: [PATCH 83/85] stop the loopback sanity check, timing off --- mixer/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index 50b7b554fc..793119f6f6 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -39,7 +39,7 @@ const int PHASE_DELAY_AT_90 = 20; const int AGENT_LOOPBACK_MODIFIER = 307; -const int LOOPBACK_SANITY_CHECK = 1; +const int LOOPBACK_SANITY_CHECK = 0; char DOMAIN_HOSTNAME[] = "highfidelity.below92.com"; char DOMAIN_IP[100] = ""; // IP Address will be re-set by lookup on startup From 7503db3e19e00892c1cedeb1e6fa56fa556f7e7c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 11 Mar 2013 19:26:21 -0700 Subject: [PATCH 84/85] output time difference in receive of packets from client --- mixer/src/main.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index 793119f6f6..7d9462fd49 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -63,14 +63,10 @@ void *sendBuffer(void *args) timeval startTime, lastSend; gettimeofday(&startTime, NULL); - gettimeofday(&lastSend, NULL); while (true) { 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++) { AudioRingBuffer *agentBuffer = (AudioRingBuffer *) agentList.getAgents()[i].getLinkedData(); @@ -307,10 +303,16 @@ int main(int argc, const char * argv[]) } sockaddr *agentAddress = new sockaddr; + timeval lastReceive; + gettimeofday(&lastReceive, NULL); while (true) { if(agentList.getAgentSocket().receive(agentAddress, packetData, &receivedBytes)) { if (packetData[0] == 'I') { + + printf("Last receive was %f ms ago\n", (usecTimestampNow() - usecTimestamp(&lastReceive)) / 1000); + gettimeofday(&lastreceive, NULL); + // add or update the existing interface agent if (!LOOPBACK_SANITY_CHECK) { agentList.addOrUpdateAgent(agentAddress, agentAddress, packetData[0]); From 53b89193f3991d537e8f303cfc492928369d78b6 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 11 Mar 2013 19:27:23 -0700 Subject: [PATCH 85/85] fix typo for last receive --- mixer/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index 7d9462fd49..566b48dfed 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -311,7 +311,7 @@ int main(int argc, const char * argv[]) if (packetData[0] == 'I') { printf("Last receive was %f ms ago\n", (usecTimestampNow() - usecTimestamp(&lastReceive)) / 1000); - gettimeofday(&lastreceive, NULL); + gettimeofday(&lastReceive, NULL); // add or update the existing interface agent if (!LOOPBACK_SANITY_CHECK) {