This commit is contained in:
Philip Rosedale 2013-05-16 17:06:40 -06:00
commit 9011484590
15 changed files with 261 additions and 157 deletions

View file

@ -11,7 +11,4 @@ setup_hifi_project(${TARGET_NAME})
# link the shared hifi library
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
# link the threads library
find_package(Threads REQUIRED)
target_link_libraries(${TARGET_NAME} ${CMAKE_THREAD_LIBS_INIT})
link_hifi_library(audio ${TARGET_NAME} ${ROOT_DIR})

View file

@ -12,7 +12,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <pthread.h>
#include <errno.h>
#include <fstream>
#include <limits>

View file

@ -17,4 +17,5 @@ include_glm(${TARGET_NAME} ${ROOT_DIR})
# link the required hifi libraries
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
link_hifi_library(avatars ${TARGET_NAME} ${ROOT_DIR})
link_hifi_library(avatars ${TARGET_NAME} ${ROOT_DIR})
link_hifi_library(audio ${TARGET_NAME} ${ROOT_DIR})

View file

@ -15,6 +15,7 @@
#include <PacketHeaders.h>
#include <AgentList.h>
#include <AvatarData.h>
#include <AudioInjectionManager.h>
#include <AudioInjector.h>
const int EVE_AGENT_LISTEN_PORT = 55441;
@ -34,6 +35,7 @@ const int HAND_TIMER_SLEEP_ITERATIONS = 50;
const float EVE_PELVIS_HEIGHT = 0.565925f;
const float AUDIO_INJECT_PROXIMITY = 0.4f;
const int EVE_VOLUME_BYTE = 190;
bool stopReceiveAgentDataThread;
@ -106,20 +108,19 @@ int main(int argc, const char* argv[]) {
// put her hand out so somebody can shake it
eve.setHandPosition(glm::vec3(eve.getPosition()[0] - 0.2,
0.5,
eve.getPosition()[2] + 0.1));
eve.getPosition()[2] + 0.1));
// prepare the audio injection manager by giving it a handle to our agent socket
AudioInjectionManager::setInjectorSocket(agentList->getAgentSocket());
// read eve's audio data
AudioInjector eveAudioInjector("/etc/highfidelity/eve/resources/eve.raw");
// lower Eve's volume by setting the attentuation modifier (this is a value out of 255)
eveAudioInjector.setAttenuationModifier(190);
// pass the agentList UDPSocket pointer to the audio injector
eveAudioInjector.setInjectorSocket(agentList->getAgentSocket());
eveAudioInjector.setVolume(EVE_VOLUME_BYTE);
// set the position of the audio injector
float injectorPosition[3];
memcpy(injectorPosition, &eve.getPosition(), sizeof(injectorPosition));
eveAudioInjector.setPosition(injectorPosition);
eveAudioInjector.setPosition(eve.getPosition());
// register the callback for agent data creation
agentList->linkedDataCreateCallback = createAvatarDataForAgent;
@ -165,15 +166,11 @@ int main(int argc, const char* argv[]) {
Agent* audioMixer = AgentList::getInstance()->soloAgentOfType(AGENT_TYPE_AUDIO_MIXER);
if (audioMixer) {
// until the audio mixer is setup for ping-reply, activate the public socket if it's not active
if (!audioMixer->getActiveSocket()) {
audioMixer->activatePublicSocket();
}
eveAudioInjector.setDestinationSocket(audioMixer->getActiveSocket());
// update the destination socket for the AIM, in case the mixer has changed
AudioInjectionManager::setDestinationSocket(*audioMixer->getPublicSocket());
// we have an active audio mixer we can send data to
eveAudioInjector.threadInjectionOfAudio();
AudioInjectionManager::threadInjector(&eveAudioInjector);
}
}
}

View file

@ -3,15 +3,19 @@ cmake_minimum_required(VERSION 2.8)
set(ROOT_DIR ..)
set(MACRO_DIR ${ROOT_DIR}/cmake/macros)
# setup for find modules
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/")
set(TARGET_NAME injector)
include(${MACRO_DIR}/SetupHifiProject.cmake)
setup_hifi_project(${TARGET_NAME})
# set up the external glm library
include(${MACRO_DIR}/IncludeGLM.cmake)
include_glm(${TARGET_NAME} ${ROOT_DIR})
# link the shared hifi library
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
# link the threads library
find_package(Threads REQUIRED)
target_link_libraries(${TARGET_NAME} ${CMAKE_THREAD_LIBS_INIT})
link_hifi_library(audio ${TARGET_NAME} ${ROOT_DIR})

View file

@ -6,7 +6,6 @@
// Copyright (c) 2013 Leonardo Murillo. All rights reserved.
//
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
@ -15,15 +14,17 @@
#include <string.h>
#include <sstream>
#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 DEFAULT_INJECTOR_VOLUME = 0xFF;
// Command line parameter defaults
bool loopAudio = true;
float sleepIntervalMin = 1.00;
@ -31,7 +32,7 @@ float sleepIntervalMax = 2.00;
char *sourceAudioFile = NULL;
const char *allowedParameters = ":rb::t::c::a::f:";
float floatArguments[4] = {0.0f, 0.0f, 0.0f, 0.0f};
unsigned char attenuationModifier = 255;
unsigned char volume = DEFAULT_INJECTOR_VOLUME;
void usage(void)
{
@ -82,7 +83,7 @@ bool processParameters(int parameterCount, char* parameterData[])
break;
}
case 'a':
::attenuationModifier = atoi(optarg);
::volume = atoi(optarg);
std::cout << "[DEBUG] Attenuation modifier: " << optarg << std::endl;
break;
default:
@ -112,19 +113,17 @@ int main(int argc, char* argv[]) {
exit(-1);
} else {
AudioInjector injector(sourceAudioFile);
injector.setInjectorSocket(&streamSocket);
injector.setDestinationSocket((sockaddr*) &mixerSocket);
injector.setPosition(::floatArguments);
injector.setPosition(glm::vec3(::floatArguments[0], ::floatArguments[1], ::floatArguments[2]));
injector.setBearing(*(::floatArguments + 3));
injector.setAttenuationModifier(::attenuationModifier);
injector.setVolume(::volume);
float delay = 0;
int usecDelay = 0;
while (true) {
injector.injectAudio();
injector.injectAudio(&streamSocket, (sockaddr*) &mixerSocket);
if (!::loopAudio) {
delay = randFloatInRange(::sleepIntervalMin, ::sleepIntervalMax);
usecDelay = delay * 1000 * 1000;

View file

@ -71,6 +71,7 @@ include(${MACRO_DIR}/LinkHifiLibrary.cmake)
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR})
link_hifi_library(avatars ${TARGET_NAME} ${ROOT_DIR})
link_hifi_library(audio ${TARGET_NAME} ${ROOT_DIR})
# find required libraries
find_package(GLM REQUIRED)

View file

@ -0,0 +1,22 @@
cmake_minimum_required(VERSION 2.8)
set(ROOT_DIR ../..)
set(MACRO_DIR ${ROOT_DIR}/cmake/macros)
# setup for find modules
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/modules/")
set(TARGET_NAME audio)
include(${MACRO_DIR}/SetupHifiLibrary.cmake)
setup_hifi_library(${TARGET_NAME})
include(${MACRO_DIR}/IncludeGLM.cmake)
include_glm(${TARGET_NAME} ${ROOT_DIR})
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
# link the threads library
find_package(Threads REQUIRED)
target_link_libraries(${TARGET_NAME} ${CMAKE_THREAD_LIBS_INIT})

View file

@ -0,0 +1,64 @@
//
// AudioInjectionManager.cpp
// hifi
//
// Created by Stephen Birarda on 5/16/13.
// Copyright (c) 2012 High Fidelity, Inc. All rights reserved.
//
#include <sys/time.h>
#include "SharedUtil.h"
#include "PacketHeaders.h"
#include "AudioInjectionManager.h"
UDPSocket* AudioInjectionManager::_injectorSocket = NULL;
sockaddr AudioInjectionManager::_destinationSocket;
AudioInjector* AudioInjectionManager::_injectors[50] = {};
AudioInjector* AudioInjectionManager::injectorWithSamplesFromFile(const char* filename) {
for (int i = 0; i < MAX_CONCURRENT_INJECTORS; i++) {
if (!_injectors[i]) {
_injectors[i] = new AudioInjector(filename);
return _injectors[i];
}
}
return NULL;
}
AudioInjector* AudioInjectionManager::injectorWithCapacity(int capacity) {
for (int i = 0; i < MAX_CONCURRENT_INJECTORS; i++) {
if (!_injectors[i]) {
_injectors[i] = new AudioInjector(capacity);
return _injectors[i];
}
}
return NULL;
}
void* AudioInjectionManager::injectAudioViaThread(void* args) {
AudioInjector* injector = (AudioInjector*) args;
injector->injectAudio(_injectorSocket, &_destinationSocket);
// if this an injector inside the injection manager's array we're responsible for deletion
for (int i = 0; i < MAX_CONCURRENT_INJECTORS; i++) {
if (_injectors[i] == injector) {
// pointer matched - delete this injector
delete injector;
// set the pointer to NULL so we can reuse this spot
_injectors[i] = NULL;
}
}
pthread_exit(0);
}
void AudioInjectionManager::threadInjector(AudioInjector* injector) {
pthread_t audioInjectThread;
pthread_create(&audioInjectThread, NULL, injectAudioViaThread, (void*) injector);
}

View file

@ -0,0 +1,36 @@
//
// AudioInjectionManager.h
// hifi
//
// Created by Stephen Birarda on 5/16/13.
// Copyright (c) 2012 High Fidelity, Inc. All rights reserved.
//
#ifndef __hifi__AudioInjectionManager__
#define __hifi__AudioInjectionManager__
#include <iostream>
#include "UDPSocket.h"
#include "AudioInjector.h"
const int MAX_CONCURRENT_INJECTORS = 50;
class AudioInjectionManager {
public:
static AudioInjector* injectorWithCapacity(int capacity);
static AudioInjector* injectorWithSamplesFromFile(const char* filename);
static void threadInjector(AudioInjector* injector);
static void setInjectorSocket(UDPSocket* injectorSocket) { _injectorSocket = injectorSocket;}
static void setDestinationSocket(sockaddr& destinationSocket) { _destinationSocket = destinationSocket; }
private:
static void* injectAudioViaThread(void* args);
static UDPSocket* _injectorSocket;
static sockaddr _destinationSocket;
static AudioInjector* _injectors[MAX_CONCURRENT_INJECTORS];
};
#endif /* defined(__hifi__AudioInjectionManager__) */

View file

@ -3,27 +3,24 @@
// hifi
//
// Created by Stephen Birarda on 4/23/13.
//
// Copyright (c) 2012 High Fidelity, Inc. All rights reserved.
//
#include <sys/time.h>
#include <fstream>
#include <cstring>
#include "SharedUtil.h"
#include "PacketHeaders.h"
#include <SharedUtil.h>
#include <PacketHeaders.h>
#include <UDPSocket.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;
const int MAX_INJECTOR_VOLUME = 0xFF;
AudioInjector::AudioInjector(const char* filename) :
_position(),
_bearing(0),
_attenuationModifier(255),
_volume(MAX_INJECTOR_VOLUME),
_indexOfNextSlot(0),
_isInjectingAudio(false)
{
@ -50,7 +47,7 @@ AudioInjector::AudioInjector(int maxNumSamples) :
_numTotalSamples(maxNumSamples),
_position(),
_bearing(0),
_attenuationModifier(255),
_volume(MAX_INJECTOR_VOLUME),
_indexOfNextSlot(0),
_isInjectingAudio(false)
{
@ -62,10 +59,50 @@ 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) {
if (_audioSampleArray) {
_isInjectingAudio = true;
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;
memcpy(currentPacketPtr, &_position, sizeof(_position));
currentPacketPtr += sizeof(_position);
*currentPacketPtr = _volume;
currentPacketPtr++;
memcpy(currentPacketPtr, &_bearing, sizeof(_bearing));
currentPacketPtr += sizeof(_bearing);
for (int i = 0; i < _numTotalSamples; i += BUFFER_LENGTH_SAMPLES) {
gettimeofday(&startTime, NULL);
int numSamplesToCopy = BUFFER_LENGTH_SAMPLES;
if (_numTotalSamples - i < BUFFER_LENGTH_SAMPLES) {
numSamplesToCopy = _numTotalSamples - i;
memset(currentPacketPtr + numSamplesToCopy, 0, BUFFER_LENGTH_BYTES - (numSamplesToCopy * sizeof(int16_t)));
}
memcpy(currentPacketPtr, _audioSampleArray + i, numSamplesToCopy * sizeof(int16_t));
injectorSocket->send(destinationSocket, dataPacket, sizeof(dataPacket));
double usecToSleep = BUFFER_SEND_INTERVAL_USECS - (usecTimestampNow() - usecTimestamp(&startTime));
if (usecToSleep > 0) {
usleep(usecToSleep);
}
}
_isInjectingAudio = false;
}
}
void AudioInjector::addSample(const int16_t sample) {
@ -82,63 +119,3 @@ void AudioInjector::addSamples(int16_t* sampleBuffer, int numSamples) {
_indexOfNextSlot += numSamples;
}
}
void AudioInjector::injectAudio() {
if (_audioSampleArray) {
_isInjectingAudio = true;
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 < _numTotalSamples; i += BUFFER_LENGTH_SAMPLES) {
gettimeofday(&startTime, NULL);
int numSamplesToCopy = BUFFER_LENGTH_SAMPLES;
if (_numTotalSamples - i < BUFFER_LENGTH_SAMPLES) {
numSamplesToCopy = _numTotalSamples - i;
memset(currentPacketPtr + numSamplesToCopy, 0, BUFFER_LENGTH_BYTES - (numSamplesToCopy * sizeof(int16_t)));
}
memcpy(currentPacketPtr, _audioSampleArray + i, numSamplesToCopy * sizeof(int16_t));
_injectorSocket->send(&_destinationSocket, dataPacket, sizeof(dataPacket));
double usecToSleep = BUFFER_SEND_INTERVAL_USECS - (usecTimestampNow() - usecTimestamp(&startTime));
if (usecToSleep > 0) {
usleep(usecToSleep);
}
}
_isInjectingAudio = false;
}
}
void* injectAudioViaThread(void* args) {
AudioInjector* parentInjector = (AudioInjector*) args;
parentInjector->injectAudio();
pthread_exit(0);
}
void AudioInjector::threadInjectionOfAudio() {
pthread_t audioInjectThread;
pthread_create(&audioInjectThread, NULL, injectAudioViaThread, (void*) this);
}

View file

@ -0,0 +1,55 @@
//
// AudioInjector.h
// hifi
//
// Created by Stephen Birarda on 4/23/13.
// Copyright (c) 2012 High Fidelity, Inc. All rights reserved.
//
#ifndef __hifi__AudioInjector__
#define __hifi__AudioInjector__
#include <iostream>
#include <glm/glm.hpp>
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;
class AudioInjector {
friend class AudioInjectionManager;
public:
AudioInjector(const char* filename);
AudioInjector(int maxNumSamples);
~AudioInjector();
void injectAudio(UDPSocket* injectorSocket, sockaddr* destinationSocket);
bool isInjectingAudio() const { return _isInjectingAudio; }
void setIsInjectingAudio(bool isInjectingAudio) { _isInjectingAudio = isInjectingAudio; }
unsigned char getVolume() const { return _volume; }
void setVolume(unsigned char volume) { _volume = volume; }
const glm::vec3& getPosition() const { return _position; }
void setPosition(const glm::vec3& position) { _position = position; }
float getBearing() const { return _bearing; }
void setBearing(float bearing) { _bearing = bearing; }
void addSample(const int16_t sample);
void addSamples(int16_t* sampleBuffer, int numSamples);
private:
int16_t* _audioSampleArray;
int _numTotalSamples;
glm::vec3 _position;
float _bearing;
unsigned char _volume;
int _indexOfNextSlot;
bool _isInjectingAudio;
};
#endif /* defined(__hifi__AudioInjector__) */

View file

@ -1,48 +0,0 @@
//
// 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(int maxNumSamples);
~AudioInjector();
bool isInjectingAudio() const { return _isInjectingAudio; }
void setPosition(float* position);
void setBearing(float bearing) { _bearing = bearing; }
void setAttenuationModifier(unsigned char attenuationModifier) { _attenuationModifier = attenuationModifier; }
void setInjectorSocket(UDPSocket* injectorSocket) { _injectorSocket = injectorSocket; }
void setDestinationSocket(sockaddr* destinationSocket) { _destinationSocket = *destinationSocket; }
void addSample(const int16_t sample);
void addSamples(int16_t* sampleBuffer, int numSamples);
void injectAudio();
void threadInjectionOfAudio();
private:
int16_t* _audioSampleArray;
int _numTotalSamples;
float _position[3];
float _bearing;
unsigned char _attenuationModifier;
int _indexOfNextSlot;
UDPSocket* _injectorSocket;
sockaddr _destinationSocket;
bool _isInjectingAudio;
};
#endif /* defined(__hifi__AudioInjector__) */