mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 03:44:02 +02:00
add trigger based firing to audio injector
This commit is contained in:
parent
7611972bca
commit
c0a9914efd
1 changed files with 139 additions and 29 deletions
|
@ -14,14 +14,16 @@
|
|||
#include <string.h>
|
||||
#include <sstream>
|
||||
|
||||
#include <AgentList.h>
|
||||
#include <AgentTypes.h>
|
||||
#include <AvatarData.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <PacketHeaders.h>
|
||||
#include <UDPSocket.h>
|
||||
#include <AudioInjector.h>
|
||||
#include <AudioInjectionManager.h>
|
||||
|
||||
char EC2_WEST_AUDIO_SERVER[] = "54.241.92.53";
|
||||
const int AUDIO_UDP_LISTEN_PORT = 55443;
|
||||
const int AVATAR_MIXER_DATA_SEND_INTERVAL_MSECS = 15;
|
||||
|
||||
const int DEFAULT_INJECTOR_VOLUME = 0xFF;
|
||||
|
||||
|
@ -30,12 +32,12 @@ bool loopAudio = true;
|
|||
float sleepIntervalMin = 1.00;
|
||||
float sleepIntervalMax = 2.00;
|
||||
char *sourceAudioFile = NULL;
|
||||
const char *allowedParameters = ":rb::t::c::a::f:";
|
||||
const char *allowedParameters = ":rb::t::c::a::f::d:";
|
||||
float floatArguments[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
unsigned char volume = DEFAULT_INJECTOR_VOLUME;
|
||||
float triggerDistance = 0;
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
void usage(void) {
|
||||
std::cout << "High Fidelity - Interface audio injector" << std::endl;
|
||||
std::cout << " -r Random sleep mode. If not specified will default to constant loop." << std::endl;
|
||||
std::cout << " -b FLOAT Min. number of seconds to sleep. Only valid in random sleep mode. Default 1.0" << std::endl;
|
||||
|
@ -43,10 +45,10 @@ void usage(void)
|
|||
std::cout << " -c FLOAT,FLOAT,FLOAT,FLOAT X,Y,Z,YAW position in universe where audio will be originating from and direction. Defaults to 0,0,0,0" << std::endl;
|
||||
std::cout << " -a 0-255 Attenuation curve modifier, defaults to 255" << std::endl;
|
||||
std::cout << " -f FILENAME Name of audio source file. Required - RAW format, 22050hz 16bit signed mono" << std::endl;
|
||||
std::cout << " -d FLOAT Trigger distance for injection. If not specified will loop constantly" << std::endl;
|
||||
}
|
||||
|
||||
bool processParameters(int parameterCount, char* parameterData[])
|
||||
{
|
||||
bool processParameters(int parameterCount, char* parameterData[]) {
|
||||
int p;
|
||||
while ((p = getopt(parameterCount, parameterData, allowedParameters)) != -1) {
|
||||
switch (p) {
|
||||
|
@ -86,6 +88,10 @@ bool processParameters(int parameterCount, char* parameterData[])
|
|||
::volume = atoi(optarg);
|
||||
std::cout << "[DEBUG] Attenuation modifier: " << optarg << std::endl;
|
||||
break;
|
||||
case 'd':
|
||||
::triggerDistance = atof(optarg);
|
||||
std::cout << "[DEBUG] Trigger distance: " << optarg << std::endl;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
return false;
|
||||
|
@ -94,45 +100,149 @@ bool processParameters(int parameterCount, char* parameterData[])
|
|||
return true;
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
bool stopReceiveAgentDataThread;
|
||||
|
||||
void *receiveAgentData(void *args) {
|
||||
sockaddr senderAddress;
|
||||
ssize_t bytesReceived;
|
||||
unsigned char incomingPacket[MAX_PACKET_SIZE];
|
||||
|
||||
AgentList* agentList = AgentList::getInstance();
|
||||
|
||||
while (!::stopReceiveAgentDataThread) {
|
||||
if (agentList->getAgentSocket()->receive(&senderAddress, incomingPacket, &bytesReceived)) {
|
||||
switch (incomingPacket[0]) {
|
||||
case PACKET_HEADER_BULK_AVATAR_DATA:
|
||||
// this is the positional data for other agents
|
||||
// pass that off to the agentList processBulkAgentData method
|
||||
agentList->processBulkAgentData(&senderAddress, incomingPacket, bytesReceived);
|
||||
break;
|
||||
default:
|
||||
// have the agentList handle list of agents from DS, replies from other agents, etc.
|
||||
agentList->processAgentData(&senderAddress, incomingPacket, bytesReceived);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pthread_exit(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void createAvatarDataForAgent(Agent* agent) {
|
||||
if (!agent->getLinkedData()) {
|
||||
agent->setLinkedData(new AvatarData(agent));
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
// new seed for random audio sleep times
|
||||
srand(time(0));
|
||||
|
||||
int AUDIO_UDP_SEND_PORT = 1500 + (rand() % (int)(1500 - 2000 + 1));
|
||||
|
||||
UDPSocket streamSocket(AUDIO_UDP_SEND_PORT);
|
||||
|
||||
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 (processParameters(argc, argv)) {
|
||||
if (::sourceAudioFile == NULL) {
|
||||
std::cout << "[FATAL] Source audio file not specified" << std::endl;
|
||||
exit(-1);
|
||||
} else {
|
||||
AudioInjector injector(sourceAudioFile);
|
||||
|
||||
// create an AgentList instance to handle communication with other agents
|
||||
AgentList* agentList = AgentList::createInstance(AGENT_TYPE_AUDIO_INJECTOR, AUDIO_UDP_SEND_PORT);
|
||||
|
||||
pthread_t receiveAgentDataThread;
|
||||
pthread_create(&receiveAgentDataThread, NULL, receiveAgentData, NULL);
|
||||
|
||||
// start telling the domain server that we are alive
|
||||
agentList->startDomainServerCheckInThread();
|
||||
|
||||
// start the agent list thread that will kill off agents when they stop talking
|
||||
agentList->startSilentAgentRemovalThread();
|
||||
|
||||
injector.setPosition(glm::vec3(::floatArguments[0], ::floatArguments[1], ::floatArguments[2]));
|
||||
injector.setBearing(*(::floatArguments + 3));
|
||||
injector.setVolume(::volume);
|
||||
|
||||
float delay = 0;
|
||||
int usecDelay = 0;
|
||||
|
||||
// register the callback for agent data creation
|
||||
agentList->linkedDataCreateCallback = createAvatarDataForAgent;
|
||||
|
||||
unsigned char broadcastPacket = PACKET_HEADER_INJECT_AUDIO;
|
||||
|
||||
timeval thisSend;
|
||||
double numMicrosecondsSleep = 0;
|
||||
|
||||
while (true) {
|
||||
injector.injectAudio(&streamSocket, (sockaddr*) &mixerSocket);
|
||||
|
||||
if (!::loopAudio) {
|
||||
delay = randFloatInRange(::sleepIntervalMin, ::sleepIntervalMax);
|
||||
usecDelay = delay * 1000 * 1000;
|
||||
usleep(usecDelay);
|
||||
if (::triggerDistance) {
|
||||
|
||||
// update the thisSend timeval to the current time
|
||||
gettimeofday(&thisSend, NULL);
|
||||
|
||||
// find the current avatar mixer
|
||||
Agent* avatarMixer = agentList->soloAgentOfType(AGENT_TYPE_AVATAR_MIXER);
|
||||
|
||||
// make sure we actually have an avatar mixer with an active socket
|
||||
if (avatarMixer && avatarMixer->getActiveSocket() != NULL) {
|
||||
// use the UDPSocket instance attached to our agent list to ask avatar mixer for a list of avatars
|
||||
agentList->getAgentSocket()->send(avatarMixer->getActiveSocket(),
|
||||
&broadcastPacket,
|
||||
sizeof(broadcastPacket));
|
||||
}
|
||||
|
||||
if (!injector.isInjectingAudio()) {
|
||||
// enumerate the other agents to decide if one is close enough that we should inject
|
||||
for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
|
||||
AvatarData* avatarData = (AvatarData*) agent->getLinkedData();
|
||||
|
||||
if (avatarData) {
|
||||
glm::vec3 tempVector = injector.getPosition() - avatarData->getPosition();
|
||||
float squareDistance = glm::dot(tempVector, tempVector);
|
||||
|
||||
if (squareDistance <= ::triggerDistance) {
|
||||
// look for an audio mixer in our agent list
|
||||
Agent* audioMixer = AgentList::getInstance()->soloAgentOfType(AGENT_TYPE_AUDIO_MIXER);
|
||||
|
||||
if (audioMixer) {
|
||||
// we have an active audio mixer we can send data to
|
||||
AudioInjectionManager::threadInjector(&injector);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sleep for the correct amount of time to have data send be consistently timed
|
||||
if ((numMicrosecondsSleep = (AVATAR_MIXER_DATA_SEND_INTERVAL_MSECS * 1000) -
|
||||
(usecTimestampNow() - usecTimestamp(&thisSend))) > 0) {
|
||||
usleep(numMicrosecondsSleep);
|
||||
}
|
||||
} else {
|
||||
// look for an audio mixer in our agent list
|
||||
Agent* audioMixer = AgentList::getInstance()->soloAgentOfType(AGENT_TYPE_AUDIO_MIXER);
|
||||
|
||||
if (audioMixer) {
|
||||
injector.injectAudio(agentList->getAgentSocket(), audioMixer->getActiveSocket());
|
||||
}
|
||||
|
||||
float delay = 0;
|
||||
int usecDelay = 0;
|
||||
|
||||
if (!::loopAudio) {
|
||||
delay = randFloatInRange(::sleepIntervalMin, ::sleepIntervalMax);
|
||||
usecDelay = delay * 1000 * 1000;
|
||||
usleep(usecDelay);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// stop the receive agent data thread
|
||||
stopReceiveAgentDataThread = true;
|
||||
pthread_join(receiveAgentDataThread, NULL);
|
||||
|
||||
// stop the agent list's threads
|
||||
agentList->stopDomainServerCheckInThread();
|
||||
agentList->stopSilentAgentRemovalThread();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue