mirror of
https://github.com/lubosz/overte.git
synced 2025-04-10 04:52:17 +02:00
allow audio injection from javascript
This commit is contained in:
parent
515e2d5a23
commit
0eae0f129c
5 changed files with 45 additions and 70 deletions
|
@ -45,15 +45,6 @@ void Agent::setStaticInstance(Agent* staticInstance) {
|
|||
_staticInstance = staticInstance;
|
||||
}
|
||||
|
||||
QScriptValue Agent::AudioInjectorConstructor(QScriptContext *context, QScriptEngine *engine) {
|
||||
AudioInjector* injector = new AudioInjector(BUFFER_LENGTH_SAMPLES_PER_CHANNEL);
|
||||
|
||||
// add this injector to the vector of audio injectors so we know we have to tell it to send its audio during loop
|
||||
_staticInstance->_audioInjectors.push_back(injector);
|
||||
|
||||
return engine->newQObject(injector, QScriptEngine::ScriptOwnership);
|
||||
}
|
||||
|
||||
QScriptValue vec3toScriptValue(QScriptEngine *engine, const glm::vec3 &vec3) {
|
||||
QScriptValue obj = engine->newObject();
|
||||
obj.setProperty("x", vec3.x);
|
||||
|
@ -126,19 +117,14 @@ void Agent::run() {
|
|||
|
||||
QScriptValue treeScaleValue = engine.newVariant(QVariant(TREE_SCALE));
|
||||
engine.globalObject().setProperty("TREE_SCALE", treeScaleValue);
|
||||
|
||||
const long long VISUAL_DATA_SEND_INTERVAL_USECS = (1 / 60.0f) * 1000 * 1000;
|
||||
|
||||
// let the VoxelPacketSender know how frequently we plan to call it
|
||||
voxelScripter.getVoxelPacketSender()->setProcessCallIntervalHint(VISUAL_DATA_SEND_INTERVAL_USECS);
|
||||
|
||||
QScriptValue visualSendIntervalValue = engine.newVariant((QVariant(VISUAL_DATA_SEND_INTERVAL_USECS / 1000)));
|
||||
engine.globalObject().setProperty("VISUAL_DATA_SEND_INTERVAL_MS", visualSendIntervalValue);
|
||||
voxelScripter.getVoxelPacketSender()->setProcessCallIntervalHint(INJECT_INTERVAL_USECS);
|
||||
|
||||
// hook in a constructor for audio injectorss
|
||||
QScriptValue audioInjectorConstructor = engine.newFunction(AudioInjectorConstructor);
|
||||
QScriptValue audioMetaObject = engine.newQMetaObject(&AudioInjector::staticMetaObject, audioInjectorConstructor);
|
||||
engine.globalObject().setProperty("AudioInjector", audioMetaObject);
|
||||
AudioInjector scriptedAudioInjector(BUFFER_LENGTH_SAMPLES_PER_CHANNEL);
|
||||
QScriptValue audioInjectorValue = engine.newQObject(&scriptedAudioInjector);
|
||||
engine.globalObject().setProperty("AudioInjector", audioInjectorValue);
|
||||
|
||||
qDebug() << "Downloaded script:" << scriptContents << "\n";
|
||||
QScriptValue result = engine.evaluate(scriptContents);
|
||||
|
@ -149,19 +135,20 @@ void Agent::run() {
|
|||
qDebug() << "Uncaught exception at line" << line << ":" << result.toString() << "\n";
|
||||
}
|
||||
|
||||
timeval thisSend;
|
||||
timeval startTime;
|
||||
gettimeofday(&startTime, NULL);
|
||||
|
||||
timeval lastDomainServerCheckIn = {};
|
||||
int numMicrosecondsSleep = 0;
|
||||
|
||||
sockaddr_in senderAddress;
|
||||
unsigned char receivedData[MAX_PACKET_SIZE];
|
||||
ssize_t receivedBytes;
|
||||
|
||||
bool hasVoxelServer = false;
|
||||
int thisFrame = 0;
|
||||
|
||||
bool firstDomainCheckIn = false;
|
||||
|
||||
while (!_shouldStop) {
|
||||
// update the thisSend timeval to the current time
|
||||
gettimeofday(&thisSend, NULL);
|
||||
|
||||
// if we're not hearing from the domain-server we should stop running
|
||||
if (NodeList::getInstance()->getNumNoReplyDomainCheckIns() == MAX_SILENT_DOMAIN_SERVER_CHECK_INS) {
|
||||
|
@ -174,38 +161,44 @@ void Agent::run() {
|
|||
NodeList::getInstance()->sendDomainServerCheckIn();
|
||||
}
|
||||
|
||||
if (!hasVoxelServer) {
|
||||
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
|
||||
if (node->getType() == NODE_TYPE_VOXEL_SERVER) {
|
||||
hasVoxelServer = true;
|
||||
if (firstDomainCheckIn) {
|
||||
// find the audio-mixer in the NodeList so we can inject audio at it
|
||||
Node* audioMixer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_AUDIO_MIXER);
|
||||
|
||||
emit willSendAudioDataCallback();
|
||||
|
||||
if (audioMixer) {
|
||||
int usecToSleep = usecTimestamp(&startTime) + (thisFrame++ * INJECT_INTERVAL_USECS) - usecTimestampNow();
|
||||
if (usecToSleep > 0) {
|
||||
usleep(usecToSleep);
|
||||
}
|
||||
|
||||
scriptedAudioInjector.injectAudio(NodeList::getInstance()->getNodeSocket(), audioMixer->getPublicSocket());
|
||||
}
|
||||
}
|
||||
|
||||
if (hasVoxelServer) {
|
||||
|
||||
// allow the scripter's call back to setup visual data
|
||||
emit willSendVisualDataCallback();
|
||||
|
||||
if (engine.hasUncaughtException()) {
|
||||
int line = engine.uncaughtExceptionLineNumber();
|
||||
qDebug() << "Uncaught exception at line" << line << ":" << engine.uncaughtException().toString() << "\n";
|
||||
}
|
||||
|
||||
// release the queue of edit voxel messages.
|
||||
voxelScripter.getVoxelPacketSender()->releaseQueuedMessages();
|
||||
|
||||
|
||||
// since we're in non-threaded mode, call process so that the packets are sent
|
||||
voxelScripter.getVoxelPacketSender()->process();
|
||||
|
||||
}
|
||||
|
||||
if (engine.hasUncaughtException()) {
|
||||
int line = engine.uncaughtExceptionLineNumber();
|
||||
qDebug() << "Uncaught exception at line" << line << ":" << engine.uncaughtException().toString() << "\n";
|
||||
}
|
||||
|
||||
while (NodeList::getInstance()->getNodeSocket()->receive((sockaddr*) &senderAddress, receivedData, &receivedBytes)) {
|
||||
if (!firstDomainCheckIn && receivedData[0] == PACKET_TYPE_DOMAIN) {
|
||||
firstDomainCheckIn = true;
|
||||
}
|
||||
|
||||
NodeList::getInstance()->processNodeData((sockaddr*) &senderAddress, receivedData, receivedBytes);
|
||||
}
|
||||
|
||||
// sleep for the correct amount of time to have data send be consistently timed
|
||||
if ((numMicrosecondsSleep = VISUAL_DATA_SEND_INTERVAL_USECS - (usecTimestampNow() - usecTimestamp(&thisSend))) > 0) {
|
||||
usleep(numMicrosecondsSleep);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
|
|
@ -27,6 +27,7 @@ public:
|
|||
public slots:
|
||||
void stop();
|
||||
signals:
|
||||
void willSendAudioDataCallback();
|
||||
void willSendVisualDataCallback();
|
||||
private:
|
||||
static void setStaticInstance(Agent* staticInstance);
|
||||
|
|
|
@ -21,8 +21,7 @@ AudioInjector::AudioInjector(const char* filename) :
|
|||
_radius(0.0f),
|
||||
_volume(MAX_INJECTOR_VOLUME),
|
||||
_indexOfNextSlot(0),
|
||||
_isInjectingAudio(false),
|
||||
_lastFrameIntensity(0.0f)
|
||||
_isInjectingAudio(false)
|
||||
{
|
||||
loadRandomIdentifier(_streamIdentifier, STREAM_IDENTIFIER_NUM_BYTES);
|
||||
|
||||
|
@ -52,8 +51,7 @@ AudioInjector::AudioInjector(int maxNumSamples) :
|
|||
_radius(0.0f),
|
||||
_volume(MAX_INJECTOR_VOLUME),
|
||||
_indexOfNextSlot(0),
|
||||
_isInjectingAudio(false),
|
||||
_lastFrameIntensity(0.0f)
|
||||
_isInjectingAudio(false)
|
||||
{
|
||||
loadRandomIdentifier(_streamIdentifier, STREAM_IDENTIFIER_NUM_BYTES);
|
||||
|
||||
|
@ -103,6 +101,11 @@ void AudioInjector::injectAudio(UDPSocket* injectorSocket, sockaddr* destination
|
|||
int nextFrame = 0;
|
||||
|
||||
for (int i = 0; i < _numTotalSamples; i += BUFFER_LENGTH_SAMPLES_PER_CHANNEL) {
|
||||
int usecToSleep = usecTimestamp(&startTime) + (nextFrame++ * INJECT_INTERVAL_USECS) - usecTimestampNow();
|
||||
if (usecToSleep > 0) {
|
||||
usleep(usecToSleep);
|
||||
}
|
||||
|
||||
int numSamplesToCopy = BUFFER_LENGTH_SAMPLES_PER_CHANNEL;
|
||||
|
||||
if (_numTotalSamples - i < BUFFER_LENGTH_SAMPLES_PER_CHANNEL) {
|
||||
|
@ -115,23 +118,6 @@ void AudioInjector::injectAudio(UDPSocket* injectorSocket, sockaddr* destination
|
|||
memcpy(currentPacketPtr, _audioSampleArray + i, numSamplesToCopy * sizeof(int16_t));
|
||||
|
||||
injectorSocket->send(destinationSocket, dataPacket, sizeof(dataPacket));
|
||||
|
||||
// calculate the intensity for this frame
|
||||
float lastRMS = 0;
|
||||
|
||||
for (int j = 0; j < BUFFER_LENGTH_SAMPLES_PER_CHANNEL; j++) {
|
||||
lastRMS += _audioSampleArray[i + j] * _audioSampleArray[i + j];
|
||||
}
|
||||
|
||||
lastRMS /= BUFFER_LENGTH_SAMPLES_PER_CHANNEL;
|
||||
lastRMS = sqrtf(lastRMS);
|
||||
|
||||
_lastFrameIntensity = lastRMS / std::numeric_limits<int16_t>::max();
|
||||
|
||||
int usecToSleep = usecTimestamp(&startTime) + (++nextFrame * INJECT_INTERVAL_USECS) - usecTimestampNow();
|
||||
if (usecToSleep > 0) {
|
||||
usleep(usecToSleep);
|
||||
}
|
||||
}
|
||||
|
||||
_isInjectingAudio = false;
|
||||
|
@ -159,8 +145,8 @@ int16_t& AudioInjector::sampleAt(const int index) {
|
|||
return _audioSampleArray[index];
|
||||
}
|
||||
|
||||
void AudioInjector::insertSample(const int index, int16_t sample) {
|
||||
void AudioInjector::insertSample(const int index, int sample) {
|
||||
assert (index >= 0 && index < _numTotalSamples);
|
||||
|
||||
_audioSampleArray[index] = sample;
|
||||
_audioSampleArray[index] = (int16_t) sample;
|
||||
}
|
||||
|
|
|
@ -42,8 +42,6 @@ public:
|
|||
unsigned char getVolume() const { return _volume; }
|
||||
void setVolume(unsigned char volume) { _volume = volume; }
|
||||
|
||||
float getLastFrameIntensity() const { return _lastFrameIntensity; }
|
||||
|
||||
const glm::vec3& getPosition() const { return _position; }
|
||||
void setPosition(const glm::vec3& position) { _position = position; }
|
||||
|
||||
|
@ -57,7 +55,7 @@ public:
|
|||
void addSamples(int16_t* sampleBuffer, int numSamples);
|
||||
public slots:
|
||||
int16_t& sampleAt(const int index);
|
||||
void insertSample(const int index, int16_t sample);
|
||||
void insertSample(const int index, int sample);
|
||||
private:
|
||||
unsigned char _streamIdentifier[STREAM_IDENTIFIER_NUM_BYTES];
|
||||
int16_t* _audioSampleArray;
|
||||
|
@ -68,7 +66,6 @@ private:
|
|||
unsigned char _volume;
|
||||
int _indexOfNextSlot;
|
||||
bool _isInjectingAudio;
|
||||
float _lastFrameIntensity;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__AudioInjector__) */
|
||||
|
|
|
@ -441,10 +441,8 @@ Node* NodeList::addOrUpdateNode(sockaddr* publicSocket, sockaddr* localSocket, c
|
|||
|
||||
if (publicSocket) {
|
||||
for (node = begin(); node != end(); node++) {
|
||||
qDebug() << "comparing to node with ID " << node->getNodeID() << "\n";
|
||||
if (node->matches(publicSocket, localSocket, nodeType)) {
|
||||
// we already have this node, stop checking
|
||||
qDebug() << "Matched node to existing\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue