Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Jeffrey Ventrella 2013-04-23 20:44:50 -07:00
commit 428cb89895
9 changed files with 256 additions and 109 deletions

View file

@ -133,7 +133,7 @@ int main(int argc, const char * argv[])
if (DEBUG_TO_SELF ||
!agent->matches((sockaddr *)&agentPublicAddress, (sockaddr *)&agentLocalAddress, agentType)) {
if (memchr(SOLO_AGENT_TYPES_STRING, agent->getType(), 1) == NULL) {
if (memchr(SOLO_AGENT_TYPES, agent->getType(), sizeof(SOLO_AGENT_TYPES)) == NULL) {
// this is an agent of which there can be multiple, just add them to the packet
// don't send avatar agents to other avatars, that will come from avatar mixer
if (agentType != AGENT_TYPE_AVATAR || agent->getType() != AGENT_TYPE_AVATAR) {

View file

@ -13,20 +13,31 @@
#include <PacketHeaders.h>
#include <AgentList.h>
#include <AvatarData.h>
#include <AudioInjector.h>
const int EVE_AGENT_LIST_PORT = 55441;
const float DATA_SEND_INTERVAL_MSECS = 10;
const int EVE_AGENT_LISTEN_PORT = 55441;
const float RANDOM_POSITION_MAX_DIMENSION = 5.0f;
const float DATA_SEND_INTERVAL_MSECS = 15;
const float MIN_AUDIO_SEND_INTERVAL_SECS = 10;
const int MIN_ITERATIONS_BETWEEN_AUDIO_SENDS = (MIN_AUDIO_SEND_INTERVAL_SECS * 1000) / DATA_SEND_INTERVAL_MSECS;
const int MAX_AUDIO_SEND_INTERVAL_SECS = 15;
const float MAX_ITERATIONS_BETWEEN_AUDIO_SENDS = (MAX_AUDIO_SEND_INTERVAL_SECS * 1000) / DATA_SEND_INTERVAL_MSECS;
bool stopReceiveAgentDataThread;
bool injectAudioThreadRunning = false;
void *receiveAgentData(void *args)
{
int TEMP_AUDIO_LISTEN_PORT = 55439;
// UDPSocket audioSocket(TEMP_AUDIO_LISTEN_PORT);
void *receiveAgentData(void *args) {
sockaddr senderAddress;
ssize_t bytesReceived;
unsigned char incomingPacket[MAX_PACKET_SIZE];
AgentList *agentList = AgentList::getInstance();
Agent *avatarMixer = NULL;
AgentList* agentList = AgentList::getInstance();
Agent* avatarMixer = NULL;
while (!::stopReceiveAgentDataThread) {
if (agentList->getAgentSocket().receive(&senderAddress, incomingPacket, &bytesReceived)) {
@ -54,9 +65,35 @@ void *receiveAgentData(void *args)
return NULL;
}
int main(int argc, char* argv[]) {
void *injectAudio(void *args) {
::injectAudioThreadRunning = true;
AudioInjector* eveAudioInjector = (AudioInjector *)args;
// look for an audio mixer in our agent list
Agent* audioMixer = AgentList::getInstance()->soloAgentOfType(AGENT_TYPE_AUDIO_MIXER);
if (audioMixer != NULL) {
// until the audio mixer is setup for ping-reply, activate the public socket if it's not active
if (audioMixer->getActiveSocket() == NULL) {
audioMixer->activatePublicSocket();
}
// we have an active audio mixer we can send data to
// eveAudioInjector->injectAudio(&::audioSocket, audioMixer->getActiveSocket());
}
::injectAudioThreadRunning = false;
pthread_exit(0);
return NULL;
}
int main(int argc, const char* argv[]) {
// new seed for random audio sleep times
srand(time(0));
// create an AgentList instance to handle communication with other agents
AgentList *agentList = AgentList::createInstance(AGENT_TYPE_AVATAR, EVE_AGENT_LIST_PORT);
AgentList* agentList = AgentList::createInstance(AGENT_TYPE_AVATAR, EVE_AGENT_LISTEN_PORT);
// start telling the domain server that we are alive
agentList->startDomainServerCheckInThread();
@ -74,16 +111,23 @@ int main(int argc, char* argv[]) {
AvatarData eve = AvatarData();
// move eve away from the origin
eve.setBodyPosition(glm::vec3(3, 0, -3));
// pick a random point inside a 10x10 grid
// turn her back towards the origin
eve.setBodyYaw(-45);
eve.setBodyPosition(glm::vec3(randFloatInRange(-RANDOM_POSITION_MAX_DIMENSION, RANDOM_POSITION_MAX_DIMENSION),
0,
randFloatInRange(-RANDOM_POSITION_MAX_DIMENSION, RANDOM_POSITION_MAX_DIMENSION)));
// face any instance of eve down the z-axis
eve.setBodyYaw(0);
// put her hand out so somebody can shake it
eve.setHandPosition(glm::vec3(eve.getBodyPosition()[0] - 0.2,
0.25,
eve.getBodyPosition()[2] + 0.1));
// read eve's audio data
AudioInjector eveAudioInjector("eve.raw");
unsigned char broadcastPacket[MAX_PACKET_SIZE];
broadcastPacket[0] = PACKET_HEADER_HEAD_DATA;
@ -92,6 +136,9 @@ int main(int argc, char* argv[]) {
timeval thisSend;
double numMicrosecondsSleep = 0;
// int numIterationsLeftBeforeAudioSend = 0;
// pthread_t injectAudioThread;
while (true) {
// update the thisSend timeval to the current time
gettimeofday(&thisSend, NULL);
@ -104,10 +151,21 @@ int main(int argc, char* argv[]) {
// use the getBroadcastData method in the AvatarData class to populate the broadcastPacket buffer
numBytesToSend = eve.getBroadcastData((broadcastPacket + 1));
// use the UDPSocket instance attached to our agent list to send avatar data to mixer
agentList->getAgentSocket().send(avatarMixer->getActiveSocket(), broadcastPacket, numBytesToSend);
}
// temporarily disable Eve's audio sending until the file is actually available on EC2 box
// if (numIterationsLeftBeforeAudioSend == 0) {
// if (!::injectAudioThreadRunning) {
// pthread_create(&injectAudioThread, NULL, injectAudio, (void*) &eveAudioInjector);
//
// numIterationsLeftBeforeAudioSend = randIntInRange(MIN_ITERATIONS_BETWEEN_AUDIO_SENDS,
// MAX_ITERATIONS_BETWEEN_AUDIO_SENDS);
// }
// } else {
// numIterationsLeftBeforeAudioSend--;
// }
// sleep for the correct amount of time to have data send be consistently timed
if ((numMicrosecondsSleep = (DATA_SEND_INTERVAL_MSECS * 1000) - (usecTimestampNow() - usecTimestamp(&thisSend))) > 0) {

View file

@ -14,4 +14,4 @@ link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
# link the threads library
find_package(Threads REQUIRED)
target_link_libraries(injector ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(${TARGET_NAME} ${CMAKE_THREAD_LIBS_INIT})

View file

@ -1,5 +1,5 @@
//
// injector.cpp
// main.cpp
// Audio Injector
//
// Created by Leonardo Murillo on 3/5/13.
@ -11,39 +11,27 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <vector>
#include <fstream>
#include <algorithm>
#include <arpa/inet.h>
#include <string.h>
#include <sstream>
#include "UDPSocket.h"
#include "UDPSocket.cpp"
#include <SharedUtil.h>
#include <PacketHeaders.h>
#include <UDPSocket.h>
#include <AudioInjector.h>
char EC2_WEST_AUDIO_SERVER[] = "54.241.92.53";
const int AUDIO_UDP_LISTEN_PORT = 55443;
const int BUFFER_LENGTH_BYTES = 512;
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;
// Command line parameter defaults
bool loopAudio = true;
float sleepIntervalMin = 1.00;
float sleepIntervalMax = 2.00;
float positionInUniverse[] = {0, 0, 0, 0};
unsigned char attenuationModifier = 255;
char *sourceAudioFile;
char *sourceAudioFile = NULL;
const char *allowedParameters = ":rb::t::c::a::f:";
char *charBuffer;
int16_t *buffer;
long length;
UDPSocket *streamSocket;
float floatArguments[4] = {0.0f, 0.0f, 0.0f, 0.0f};
unsigned char attenuationModifier = 255;
void usage(void)
{
@ -62,19 +50,19 @@ bool processParameters(int parameterCount, char* parameterData[])
while ((p = getopt(parameterCount, parameterData, allowedParameters)) != -1) {
switch (p) {
case 'r':
loopAudio = false;
::loopAudio = false;
std::cout << "[DEBUG] Random sleep mode enabled" << std::endl;
break;
case 'b':
sleepIntervalMin = atof(optarg);
::sleepIntervalMin = atof(optarg);
std::cout << "[DEBUG] Min delay between plays " << sleepIntervalMin << "sec" << std::endl;
break;
case 't':
sleepIntervalMax = atof(optarg);
::sleepIntervalMax = atof(optarg);
std::cout << "[DEBUG] Max delay between plays " << sleepIntervalMax << "sec" << std::endl;
break;
case 'f':
sourceAudioFile = optarg;
::sourceAudioFile = optarg;
std::cout << "[DEBUG] Opening file: " << sourceAudioFile << std::endl;
break;
case 'c':
@ -84,7 +72,7 @@ bool processParameters(int parameterCount, char* parameterData[])
int i = 0;
while (std::getline(ss, token, ',')) {
positionInUniverse[i] = atof(token.c_str());
::floatArguments[i] = atof(token.c_str());
++i;
if (i == 4) {
break;
@ -94,7 +82,7 @@ bool processParameters(int parameterCount, char* parameterData[])
break;
}
case 'a':
attenuationModifier = atoi(optarg);
::attenuationModifier = atoi(optarg);
std::cout << "[DEBUG] Attenuation modifier: " << optarg << std::endl;
break;
default:
@ -105,77 +93,42 @@ bool processParameters(int parameterCount, char* parameterData[])
return true;
};
void loadFile(void) {
std::fstream sourceFile;
sourceFile.open(sourceAudioFile, std::ios::in | std::ios::binary);
sourceFile.seekg(0, std::ios::end);
length = sourceFile.tellg();
sourceFile.seekg(0, std::ios::beg);
long sizeOfShortArray = length / 2;
buffer = new int16_t[sizeOfShortArray];
sourceFile.read((char *)buffer, length);
}
void stream(void)
{
timeval startTime;
int leadingBytes = 1 + (sizeof(float) * 4);
unsigned char dataPacket[BUFFER_LENGTH_BYTES + leadingBytes];
dataPacket[0] = PACKET_HEADER_INJECT_AUDIO;
unsigned char *currentPacketPtr = dataPacket + 1;
for (int p = 0; p < 4; p++) {
memcpy(currentPacketPtr, &positionInUniverse[p], sizeof(float));
currentPacketPtr += sizeof(float);
}
*currentPacketPtr = attenuationModifier;
currentPacketPtr++;
for (int i = 0; i < length; i += BUFFER_LENGTH_SAMPLES) {
gettimeofday(&startTime, NULL);
memcpy(currentPacketPtr, &buffer[i], BUFFER_LENGTH_BYTES);
streamSocket->send(EC2_WEST_AUDIO_SERVER, AUDIO_UDP_LISTEN_PORT, dataPacket, sizeof(dataPacket));
double usecToSleep = usecTimestamp(&startTime) + BUFFER_SEND_INTERVAL_USECS - usecTimestampNow();
usleep(usecToSleep);
}
};
int main(int argc, char* argv[])
{
int main(int argc, const char* argv[]) {
srand(time(0));
int AUDIO_UDP_SEND_PORT = 1500 + (rand() % (int)(1500 - 2000 + 1));
streamSocket = new UDPSocket(AUDIO_UDP_SEND_PORT);
UDPSocket streamSocket(AUDIO_UDP_SEND_PORT);
if (processParameters(argc, argv)) {
if (sourceAudioFile) {
loadFile();
} else {
sockaddr_in mixerSocket;
mixerSocket.sin_family = AF_INET;
mixerSocket.sin_addr.s_addr = inet_addr(EC2_WEST_AUDIO_SERVER);
mixerSocket.sin_port = htons((uint16_t)AUDIO_UDP_LISTEN_PORT);
if (processParameters(argc, argv)) {
if (::sourceAudioFile == NULL) {
std::cout << "[FATAL] Source audio file not specified" << std::endl;
exit(-1);
}
for (int i = 0; i < sizeof(positionInUniverse)/sizeof(positionInUniverse[0]); ++i) {
std::cout << "Position " << positionInUniverse[i] << std::endl;
}
float delay;
int usecDelay;
while (true) {
stream();
} else {
AudioInjector injector(sourceAudioFile);
if (loopAudio) {
delay = 0;
} else {
delay = randFloatInRange(sleepIntervalMin, sleepIntervalMax);
injector.setPosition(::floatArguments);
injector.setBearing(*(::floatArguments + 3));
injector.setAttenuationModifier(::attenuationModifier);
float delay = 0;
int usecDelay = 0;
while (true) {
injector.injectAudio(&streamSocket, (sockaddr*) &mixerSocket);
if (!::loopAudio) {
delay = randFloatInRange(::sleepIntervalMin, ::sleepIntervalMax);
usecDelay = delay * 1000 * 1000;
usleep(usecDelay);
}
}
usecDelay = delay * 1000 * 1000;
usleep(usecDelay);
}
}
}
return 0;
}

View file

@ -35,8 +35,6 @@ float browThickness = 0.16;
bool usingBigSphereCollisionTest = true;
char iris_texture_file[] = "resources/images/green_eye.png";
vector<unsigned char> iris_texture;

View file

@ -24,7 +24,7 @@
using shared_lib::printLog;
const char SOLO_AGENT_TYPES_STRING[] = {
const char SOLO_AGENT_TYPES[3] = {
AGENT_TYPE_AVATAR_MIXER,
AGENT_TYPE_AUDIO_MIXER,
AGENT_TYPE_VOXEL
@ -305,8 +305,8 @@ void AgentList::handlePingReply(sockaddr *agentAddress) {
}
}
Agent* AgentList::soloAgentOfType(char agentType) {
if (memchr(SOLO_AGENT_TYPES_STRING, agentType, 1)) {
Agent* AgentList::soloAgentOfType(char agentType) {
if (memchr(SOLO_AGENT_TYPES, agentType, sizeof(SOLO_AGENT_TYPES)) != NULL) {
for(std::vector<Agent>::iterator agent = agents.begin(); agent != agents.end(); agent++) {
if (agent->getType() == agentType) {
return &*agent;
@ -428,7 +428,7 @@ void *checkInWithDomainServer(void *args) {
sockaddr_in tempAddress;
memcpy(&tempAddress.sin_addr, pHostInfo->h_addr_list[0], pHostInfo->h_length);
strcpy(DOMAIN_IP, inet_ntoa(tempAddress.sin_addr));
printLog("Domain server: %s \n", DOMAIN_HOSTNAME);
printLog("Domain server: %s - %s\n", DOMAIN_HOSTNAME, DOMAIN_IP);
} else {
printLog("Failed lookup domainserver\n");

View file

@ -22,7 +22,7 @@
const int MAX_PACKET_SIZE = 1500;
const unsigned int AGENT_SOCKET_LISTEN_PORT = 40103;
const int AGENT_SILENCE_THRESHOLD_USECS = 2 * 1000000;
extern const char SOLO_AGENT_TYPES_STRING[];
extern const char SOLO_AGENT_TYPES[3];
extern char DOMAIN_HOSTNAME[];
extern char DOMAIN_IP[100]; // IP Address will be re-set by lookup on startup

View file

@ -0,0 +1,103 @@
//
// AudioInjector.cpp
// hifi
//
// Created by Stephen Birarda on 4/23/13.
//
//
#include <sys/time.h>
#include <fstream>
#include <cstring>
#include "SharedUtil.h"
#include "PacketHeaders.h"
#include "AudioInjector.h"
const int BUFFER_LENGTH_BYTES = 512;
const int BUFFER_LENGTH_SAMPLES = BUFFER_LENGTH_BYTES / sizeof(int16_t);
const float SAMPLE_RATE = 22050.0f;
const float BUFFER_SEND_INTERVAL_USECS = (BUFFER_LENGTH_SAMPLES / SAMPLE_RATE) * 1000000;
AudioInjector::AudioInjector(const char* filename) :
_numTotalBytesAudio(0),
_bearing(0),
_attenuationModifier(255)
{
_position[0] = 0.0f;
_position[1] = 0.0f;
_position[2] = 0.0f;
std::fstream sourceFile;
sourceFile.open(filename, std::ios::in | std::ios::binary);
sourceFile.seekg(0, std::ios::end);
_numTotalBytesAudio = sourceFile.tellg();
if (_numTotalBytesAudio == -1) {
printf("Error reading audio data from file %s\n", filename);
_audioSampleArray = NULL;
} else {
printf("Read %d bytes from audio file\n", _numTotalBytesAudio);
sourceFile.seekg(0, std::ios::beg);
long sizeOfShortArray = _numTotalBytesAudio / 2;
_audioSampleArray = new int16_t[sizeOfShortArray];
sourceFile.read((char *)_audioSampleArray, _numTotalBytesAudio);
}
}
AudioInjector::~AudioInjector() {
delete[] _audioSampleArray;
}
void AudioInjector::setPosition(float* position) {
_position[0] = position[0];
_position[1] = position[1];
_position[2] = position[2];
}
void AudioInjector::injectAudio(UDPSocket* injectorSocket, sockaddr* destinationSocket) const {
if (_audioSampleArray != NULL) {
timeval startTime;
// one byte for header, 3 positional floats, 1 bearing float, 1 attenuation modifier byte
int leadingBytes = 1 + (sizeof(float) * 4) + 1;
unsigned char dataPacket[BUFFER_LENGTH_BYTES + leadingBytes];
dataPacket[0] = PACKET_HEADER_INJECT_AUDIO;
unsigned char *currentPacketPtr = dataPacket + 1;
for (int i = 0; i < 3; i++) {
memcpy(currentPacketPtr, &_position[i], sizeof(float));
currentPacketPtr += sizeof(float);
}
*currentPacketPtr = _attenuationModifier;
currentPacketPtr++;
memcpy(currentPacketPtr, &_bearing, sizeof(float));
currentPacketPtr += sizeof(float);
for (int i = 0; i < _numTotalBytesAudio; i += BUFFER_LENGTH_BYTES) {
gettimeofday(&startTime, NULL);
int numBytesToCopy = BUFFER_LENGTH_BYTES;
if (_numTotalBytesAudio - i < BUFFER_LENGTH_BYTES) {
numBytesToCopy = _numTotalBytesAudio - i;
memset(currentPacketPtr + numBytesToCopy, 0, BUFFER_LENGTH_BYTES - numBytesToCopy);
}
memcpy(currentPacketPtr, _audioSampleArray + (i / 2), numBytesToCopy);
injectorSocket->send(destinationSocket, dataPacket, sizeof(dataPacket));
double usecToSleep = BUFFER_SEND_INTERVAL_USECS - (usecTimestampNow() - usecTimestamp(&startTime));
if (usecToSleep > 0) {
usleep(usecToSleep);
}
}
}
}

View file

@ -0,0 +1,35 @@
//
// AudioInjector.h
// hifi
//
// Created by Stephen Birarda on 4/23/13.
//
//
#ifndef __hifi__AudioInjector__
#define __hifi__AudioInjector__
#include <iostream>
#include <netinet/in.h>
#include "UDPSocket.h"
class AudioInjector {
public:
AudioInjector(const char* filename);
~AudioInjector();
void setPosition(float* position);
void setBearing(float bearing) { _bearing = bearing; }
void setAttenuationModifier(unsigned char attenuationModifier) { _attenuationModifier = attenuationModifier; }
void injectAudio(UDPSocket* injectorSocket, sockaddr* destinationSocket) const;
private:
int16_t* _audioSampleArray;
int _numTotalBytesAudio;
float _position[3];
float _bearing;
unsigned char _attenuationModifier;
};
#endif /* defined(__hifi__AudioInjector__) */