mirror of
https://github.com/lubosz/overte.git
synced 2025-04-24 00:13:53 +02:00
Merge pull request #2292 from birarda/agent-audio
add sendAvatarAudioStream option to Agent
This commit is contained in:
commit
e9b622361a
4 changed files with 64 additions and 13 deletions
|
@ -13,6 +13,7 @@
|
|||
#include <QtNetwork/QNetworkRequest>
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
|
||||
#include <AudioRingBuffer.h>
|
||||
#include <AvatarData.h>
|
||||
#include <NodeList.h>
|
||||
#include <PacketHeaders.h>
|
||||
|
@ -25,7 +26,8 @@
|
|||
Agent::Agent(const QByteArray& packet) :
|
||||
ThreadedAssignment(packet),
|
||||
_voxelEditSender(),
|
||||
_particleEditSender()
|
||||
_particleEditSender(),
|
||||
_avatarAudioStream(NULL)
|
||||
{
|
||||
// be the parent of the script engine so it gets moved when we do
|
||||
_scriptEngine.setParent(this);
|
||||
|
@ -34,6 +36,30 @@ Agent::Agent(const QByteArray& packet) :
|
|||
_scriptEngine.getParticlesScriptingInterface()->setPacketSender(&_particleEditSender);
|
||||
}
|
||||
|
||||
Agent::~Agent() {
|
||||
delete _avatarAudioStream;
|
||||
}
|
||||
|
||||
const int SCRIPT_AUDIO_BUFFER_SAMPLES = floor(((SCRIPT_DATA_CALLBACK_USECS * SAMPLE_RATE) / (1000 * 1000)) + 0.5);
|
||||
|
||||
void Agent::setSendAvatarAudioStream(bool sendAvatarAudioStream) {
|
||||
if (sendAvatarAudioStream) {
|
||||
// the agentAudioStream number of samples is related to the ScriptEngine callback rate
|
||||
_avatarAudioStream = new int16_t[SCRIPT_AUDIO_BUFFER_SAMPLES];
|
||||
|
||||
// fill the _audioStream with zeroes to start
|
||||
memset(_avatarAudioStream, 0, SCRIPT_AUDIO_BUFFER_SAMPLES * sizeof(int16_t));
|
||||
|
||||
_scriptEngine.setNumAvatarAudioBufferSamples(SCRIPT_AUDIO_BUFFER_SAMPLES);
|
||||
_scriptEngine.setAvatarAudioBuffer(_avatarAudioStream);
|
||||
} else {
|
||||
delete _avatarAudioStream;
|
||||
_avatarAudioStream = NULL;
|
||||
|
||||
_scriptEngine.setAvatarAudioBuffer(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void Agent::readPendingDatagrams() {
|
||||
QByteArray receivedPacket;
|
||||
HifiSockAddr senderSockAddr;
|
||||
|
|
|
@ -28,12 +28,17 @@ class Agent : public ThreadedAssignment {
|
|||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(bool isAvatar READ isAvatar WRITE setIsAvatar)
|
||||
Q_PROPERTY(bool sendAvatarAudioStream READ isSendingAvatarAudioStream WRITE setSendAvatarAudioStream)
|
||||
public:
|
||||
Agent(const QByteArray& packet);
|
||||
~Agent();
|
||||
|
||||
void setIsAvatar(bool isAvatar) { QMetaObject::invokeMethod(&_scriptEngine, "setIsAvatar", Q_ARG(bool, isAvatar)); }
|
||||
bool isAvatar() const { return _scriptEngine.isAvatar(); }
|
||||
|
||||
void setSendAvatarAudioStream(bool sendAvatarAudioStream);
|
||||
bool isSendingAvatarAudioStream() const { return (bool) _scriptEngine.sendsAvatarAudioStream(); }
|
||||
|
||||
public slots:
|
||||
void run();
|
||||
void readPendingDatagrams();
|
||||
|
@ -45,6 +50,8 @@ private:
|
|||
|
||||
ParticleTreeHeadlessViewer _particleViewer;
|
||||
VoxelTreeHeadlessViewer _voxelViewer;
|
||||
|
||||
int16_t* _avatarAudioStream;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__Agent__) */
|
||||
|
|
|
@ -28,8 +28,6 @@
|
|||
#include "LocalVoxels.h"
|
||||
#include "ScriptEngine.h"
|
||||
|
||||
const unsigned int VISUAL_DATA_CALLBACK_USECS = (1.0 / 60.0) * 1000 * 1000;
|
||||
|
||||
int ScriptEngine::_scriptNumber = 1;
|
||||
VoxelsScriptingInterface ScriptEngine::_voxelsScriptingInterface;
|
||||
ParticlesScriptingInterface ScriptEngine::_particlesScriptingInterface;
|
||||
|
@ -54,6 +52,7 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, bool wantMenuItems, co
|
|||
_avatarIdentityTimer(NULL),
|
||||
_avatarBillboardTimer(NULL),
|
||||
_timerFunctionMap(),
|
||||
_avatarAudioBuffer(NULL),
|
||||
_controllerScriptingInterface(controllerScriptingInterface),
|
||||
_avatarData(NULL),
|
||||
_wantMenuItems(wantMenuItems),
|
||||
|
@ -77,9 +76,6 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, bool wantMenuItems, co
|
|||
_scriptNumber++;
|
||||
}
|
||||
|
||||
ScriptEngine::~ScriptEngine() {
|
||||
}
|
||||
|
||||
void ScriptEngine::setIsAvatar(bool isAvatar) {
|
||||
_isAvatar = isAvatar;
|
||||
|
||||
|
@ -169,8 +165,8 @@ void ScriptEngine::init() {
|
|||
_engine.globalObject().setProperty("TREE_SCALE", treeScaleValue);
|
||||
|
||||
// let the VoxelPacketSender know how frequently we plan to call it
|
||||
_voxelsScriptingInterface.getVoxelPacketSender()->setProcessCallIntervalHint(VISUAL_DATA_CALLBACK_USECS);
|
||||
_particlesScriptingInterface.getParticlePacketSender()->setProcessCallIntervalHint(VISUAL_DATA_CALLBACK_USECS);
|
||||
_voxelsScriptingInterface.getVoxelPacketSender()->setProcessCallIntervalHint(SCRIPT_DATA_CALLBACK_USECS);
|
||||
_particlesScriptingInterface.getParticlePacketSender()->setProcessCallIntervalHint(SCRIPT_DATA_CALLBACK_USECS);
|
||||
|
||||
}
|
||||
|
||||
|
@ -228,7 +224,7 @@ void ScriptEngine::run() {
|
|||
qint64 lastUpdate = usecTimestampNow();
|
||||
|
||||
while (!_isFinished) {
|
||||
int usecToSleep = usecTimestamp(&startTime) + (thisFrame++ * VISUAL_DATA_CALLBACK_USECS) - usecTimestampNow();
|
||||
int usecToSleep = usecTimestamp(&startTime) + (thisFrame++ * SCRIPT_DATA_CALLBACK_USECS) - usecTimestampNow();
|
||||
if (usecToSleep > 0) {
|
||||
usleep(usecToSleep);
|
||||
}
|
||||
|
@ -268,6 +264,21 @@ void ScriptEngine::run() {
|
|||
avatarPacket.append(_avatarData->toByteArray());
|
||||
|
||||
nodeList->broadcastToNodes(avatarPacket, NodeSet() << NodeType::AvatarMixer);
|
||||
|
||||
if (_avatarAudioBuffer && _numAvatarAudioBufferSamples > 0) {
|
||||
// if have an avatar audio stream then send it out to our audio-mixer
|
||||
QByteArray audioPacket = byteArrayWithPopulatedHeader(PacketTypeMicrophoneAudioNoEcho);
|
||||
QDataStream packetStream(&audioPacket, QIODevice::Append);
|
||||
|
||||
// use the orientation and position of this avatar for the source of this audio
|
||||
packetStream.writeRawData(reinterpret_cast<const char*>(&_avatarData->getPosition()), sizeof(glm::vec3));
|
||||
glm::quat headOrientation = _avatarData->getHeadOrientation();
|
||||
packetStream.writeRawData(reinterpret_cast<const char*>(&headOrientation), sizeof(glm::quat));
|
||||
packetStream.writeRawData(reinterpret_cast<const char*>(_avatarAudioBuffer),
|
||||
_numAvatarAudioBufferSamples * sizeof(int16_t));
|
||||
|
||||
nodeList->broadcastToNodes(audioPacket, NodeSet() << NodeType::AudioMixer);
|
||||
}
|
||||
}
|
||||
|
||||
qint64 now = usecTimestampNow();
|
||||
|
|
|
@ -20,14 +20,16 @@
|
|||
|
||||
#include <AvatarData.h>
|
||||
|
||||
class ParticlesScriptingInterface;
|
||||
|
||||
#include "AbstractControllerScriptingInterface.h"
|
||||
#include "Quat.h"
|
||||
#include "Vec3.h"
|
||||
|
||||
class ParticlesScriptingInterface;
|
||||
|
||||
const QString NO_SCRIPT("");
|
||||
|
||||
const unsigned int SCRIPT_DATA_CALLBACK_USECS = floor(((1.0 / 60.0f) * 1000 * 1000) + 0.5);
|
||||
|
||||
class ScriptEngine : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
@ -35,8 +37,6 @@ public:
|
|||
const QString& scriptMenuName = QString(""),
|
||||
AbstractControllerScriptingInterface* controllerScriptingInterface = NULL);
|
||||
|
||||
~ScriptEngine();
|
||||
|
||||
/// Access the VoxelsScriptingInterface in order to initialize it with a custom packet sender and jurisdiction listener
|
||||
static VoxelsScriptingInterface* getVoxelsScriptingInterface() { return &_voxelsScriptingInterface; }
|
||||
|
||||
|
@ -56,6 +56,11 @@ public:
|
|||
|
||||
void setAvatarData(AvatarData* avatarData, const QString& objectName);
|
||||
|
||||
void setAvatarAudioBuffer(int16_t* avatarAudioBuffer) { _avatarAudioBuffer = avatarAudioBuffer; }
|
||||
bool sendsAvatarAudioStream() const { return (bool) _avatarAudioBuffer; }
|
||||
void setNumAvatarAudioBufferSamples(int numAvatarAudioBufferSamples)
|
||||
{ _numAvatarAudioBufferSamples = numAvatarAudioBufferSamples; }
|
||||
|
||||
void init();
|
||||
void run(); /// runs continuously until Agent.stop() is called
|
||||
void evaluate(); /// initializes the engine, and evaluates the script, but then returns control to caller
|
||||
|
@ -86,6 +91,8 @@ protected:
|
|||
QTimer* _avatarIdentityTimer;
|
||||
QTimer* _avatarBillboardTimer;
|
||||
QHash<QTimer*, QScriptValue> _timerFunctionMap;
|
||||
int16_t* _avatarAudioBuffer;
|
||||
int _numAvatarAudioBufferSamples;
|
||||
|
||||
private:
|
||||
void sendAvatarIdentityPacket();
|
||||
|
|
Loading…
Reference in a new issue