mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 07:58:59 +02:00
Rolling my own 100hz timer
Starting with the simplest possible thing - just sleep for 10000 microseconds. Can make it adaptive if need be.
This commit is contained in:
parent
b4c064a538
commit
b58c36cb12
2 changed files with 54 additions and 15 deletions
|
@ -15,6 +15,7 @@
|
||||||
#include <QtNetwork/QNetworkDiskCache>
|
#include <QtNetwork/QNetworkDiskCache>
|
||||||
#include <QtNetwork/QNetworkRequest>
|
#include <QtNetwork/QNetworkRequest>
|
||||||
#include <QtNetwork/QNetworkReply>
|
#include <QtNetwork/QNetworkReply>
|
||||||
|
#include <QThread>
|
||||||
|
|
||||||
#include <AssetClient.h>
|
#include <AssetClient.h>
|
||||||
#include <AvatarHashMap.h>
|
#include <AvatarHashMap.h>
|
||||||
|
@ -48,6 +49,18 @@
|
||||||
|
|
||||||
static const int RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES = 10;
|
static const int RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES = 10;
|
||||||
|
|
||||||
|
// this should send a signal every 10ms, with pretty good precision
|
||||||
|
void AvatarAudioTimer::start() {
|
||||||
|
qDebug() << "AvatarAudioTimer::start called";
|
||||||
|
const int TARGET_INTERVAL_USEC = 10000; // 10ms
|
||||||
|
while (!_quit) {
|
||||||
|
// simplest possible timer
|
||||||
|
usleep(TARGET_INTERVAL_USEC);
|
||||||
|
emit avatarTick();
|
||||||
|
}
|
||||||
|
qDebug() << "AvatarAudioTimer is finished";
|
||||||
|
}
|
||||||
|
|
||||||
Agent::Agent(ReceivedMessage& message) :
|
Agent::Agent(ReceivedMessage& message) :
|
||||||
ThreadedAssignment(message),
|
ThreadedAssignment(message),
|
||||||
_entityEditSender(),
|
_entityEditSender(),
|
||||||
|
@ -121,7 +134,6 @@ void Agent::handleAudioPacket(QSharedPointer<ReceivedMessage> message) {
|
||||||
_receivedAudioStream.parseData(*message);
|
_receivedAudioStream.parseData(*message);
|
||||||
|
|
||||||
_lastReceivedAudioLoudness = _receivedAudioStream.getNextOutputFrameLoudness();
|
_lastReceivedAudioLoudness = _receivedAudioStream.getNextOutputFrameLoudness();
|
||||||
|
|
||||||
_receivedAudioStream.clearBuffer();
|
_receivedAudioStream.clearBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,11 +384,15 @@ void Agent::executeScript() {
|
||||||
entityScriptingInterface->setEntityTree(_entityViewer.getTree());
|
entityScriptingInterface->setEntityTree(_entityViewer.getTree());
|
||||||
|
|
||||||
DependencyManager::set<AssignmentParentFinder>(_entityViewer.getTree());
|
DependencyManager::set<AssignmentParentFinder>(_entityViewer.getTree());
|
||||||
|
|
||||||
_avatarAudioTimer = new QTimer(this);
|
qDebug() << "Connecting avatarAudioTimer and starting...";
|
||||||
_avatarAudioTimer->setTimerType(Qt::PreciseTimer);
|
AvatarAudioTimer* audioTimerWorker = new AvatarAudioTimer();
|
||||||
connect(_avatarAudioTimer, SIGNAL(timeout()), this, SLOT(processAgentAvatarAndAudio()));
|
audioTimerWorker->moveToThread(&_avatarAudioTimerThread);
|
||||||
_avatarAudioTimer->start(10);
|
connect(audioTimerWorker, &AvatarAudioTimer::avatarTick, this, &Agent::processAgentAvatarAndAudio);
|
||||||
|
connect(this, &Agent::startAvatarAudioTimer, audioTimerWorker, &AvatarAudioTimer::start);
|
||||||
|
connect(this, &Agent::stopAvatarAudioTimer, audioTimerWorker, &AvatarAudioTimer::stop);
|
||||||
|
connect(&_avatarAudioTimerThread, &QThread::finished, audioTimerWorker, &QObject::deleteLater);
|
||||||
|
_avatarAudioTimerThread.start();
|
||||||
|
|
||||||
// wire up our additional agent related processing to the update signal
|
// wire up our additional agent related processing to the update signal
|
||||||
//QObject::connect(_scriptEngine.get(), &ScriptEngine::update, this, &Agent::processAgentAvatarAndAudio);
|
//QObject::connect(_scriptEngine.get(), &ScriptEngine::update, this, &Agent::processAgentAvatarAndAudio);
|
||||||
|
@ -406,6 +422,10 @@ void Agent::setIsAvatar(bool isAvatar) {
|
||||||
|
|
||||||
// start the timers
|
// start the timers
|
||||||
_avatarIdentityTimer->start(AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS);
|
_avatarIdentityTimer->start(AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS);
|
||||||
|
|
||||||
|
// tell the audiotimer worker to start working
|
||||||
|
emit startAvatarAudioTimer();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_isAvatar) {
|
if (!_isAvatar) {
|
||||||
|
@ -428,7 +448,7 @@ void Agent::sendAvatarIdentityPacket() {
|
||||||
void Agent::processAgentAvatarAndAudio() {
|
void Agent::processAgentAvatarAndAudio() {
|
||||||
if (!_scriptEngine->isFinished() && _isAvatar) {
|
if (!_scriptEngine->isFinished() && _isAvatar) {
|
||||||
auto scriptedAvatar = DependencyManager::get<ScriptableAvatar>();
|
auto scriptedAvatar = DependencyManager::get<ScriptableAvatar>();
|
||||||
const int SCRIPT_AUDIO_BUFFER_SAMPLES = AudioConstants::SAMPLE_RATE / 100;//SCRIPT_FPS + 0.5;
|
const int SCRIPT_AUDIO_BUFFER_SAMPLES = AudioConstants::SAMPLE_RATE / 100 + 0.5;
|
||||||
const int SCRIPT_AUDIO_BUFFER_BYTES = SCRIPT_AUDIO_BUFFER_SAMPLES * sizeof(int16_t);
|
const int SCRIPT_AUDIO_BUFFER_BYTES = SCRIPT_AUDIO_BUFFER_SAMPLES * sizeof(int16_t);
|
||||||
|
|
||||||
QByteArray avatarByteArray = scriptedAvatar->toByteArray(true, randFloat() < AVATAR_SEND_FULL_UPDATE_RATIO);
|
QByteArray avatarByteArray = scriptedAvatar->toByteArray(true, randFloat() < AVATAR_SEND_FULL_UPDATE_RATIO);
|
||||||
|
@ -513,16 +533,15 @@ void Agent::processAgentAvatarAndAudio() {
|
||||||
audioPacket->writePrimitive(headOrientation);
|
audioPacket->writePrimitive(headOrientation);
|
||||||
|
|
||||||
// encode it
|
// encode it
|
||||||
QByteArray decodedBuffer(reinterpret_cast<const char*>(nextSoundOutput), numAvailableSamples*sizeof(int16_t));
|
if(_encoder) {
|
||||||
QByteArray encodedBuffer;
|
QByteArray decodedBuffer(reinterpret_cast<const char*>(nextSoundOutput), numAvailableSamples*sizeof(int16_t));
|
||||||
if (_encoder) {
|
QByteArray encodedBuffer;
|
||||||
_encoder->encode(decodedBuffer, encodedBuffer);
|
_encoder->encode(decodedBuffer, encodedBuffer);
|
||||||
|
audioPacket->write(encodedBuffer.data(), encodedBuffer.size());
|
||||||
} else {
|
} else {
|
||||||
audioPacket->write(decodedBuffer.data(), decodedBuffer.size());
|
audioPacket->write(reinterpret_cast<const char*>(nextSoundOutput), numAvailableSamples*sizeof(int16_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
// write the raw audio data
|
|
||||||
audioPacket->write(encodedBuffer.data(), encodedBuffer.size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// write audio packet to AudioMixer nodes
|
// write audio packet to AudioMixer nodes
|
||||||
|
@ -558,6 +577,9 @@ void Agent::aboutToFinish() {
|
||||||
// cleanup the AudioInjectorManager (and any still running injectors)
|
// cleanup the AudioInjectorManager (and any still running injectors)
|
||||||
DependencyManager::destroy<AudioInjectorManager>();
|
DependencyManager::destroy<AudioInjectorManager>();
|
||||||
|
|
||||||
|
emit stopAvatarAudioTimer();
|
||||||
|
_avatarAudioTimerThread.quit();
|
||||||
|
|
||||||
// cleanup codec & encoder
|
// cleanup codec & encoder
|
||||||
if (_codec && _encoder) {
|
if (_codec && _encoder) {
|
||||||
_codec->releaseEncoder(_encoder);
|
_codec->releaseEncoder(_encoder);
|
||||||
|
|
|
@ -32,6 +32,20 @@
|
||||||
#include "MixedAudioStream.h"
|
#include "MixedAudioStream.h"
|
||||||
|
|
||||||
|
|
||||||
|
class AvatarAudioTimer : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void avatarTick();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void start();
|
||||||
|
void stop() { _quit = true; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool _quit { false };
|
||||||
|
};
|
||||||
|
|
||||||
class Agent : public ThreadedAssignment {
|
class Agent : public ThreadedAssignment {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -60,6 +74,7 @@ public:
|
||||||
public slots:
|
public slots:
|
||||||
void run() override;
|
void run() override;
|
||||||
void playAvatarSound(SharedSoundPointer avatarSound) { setAvatarSound(avatarSound); }
|
void playAvatarSound(SharedSoundPointer avatarSound) { setAvatarSound(avatarSound); }
|
||||||
|
void processAgentAvatarAndAudio();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void requestScript();
|
void requestScript();
|
||||||
|
@ -71,9 +86,11 @@ private slots:
|
||||||
void handleJurisdictionPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
void handleJurisdictionPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
||||||
void handleSelectedAudioFormat(QSharedPointer<ReceivedMessage> message);
|
void handleSelectedAudioFormat(QSharedPointer<ReceivedMessage> message);
|
||||||
|
|
||||||
void processAgentAvatarAndAudio();
|
|
||||||
void nodeActivated(SharedNodePointer activatedNode);
|
void nodeActivated(SharedNodePointer activatedNode);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void startAvatarAudioTimer();
|
||||||
|
void stopAvatarAudioTimer();
|
||||||
private:
|
private:
|
||||||
void negotiateAudioFormat();
|
void negotiateAudioFormat();
|
||||||
void selectAudioFormat(const QString& selectedCodecName);
|
void selectAudioFormat(const QString& selectedCodecName);
|
||||||
|
@ -102,7 +119,7 @@ private:
|
||||||
CodecPluginPointer _codec;
|
CodecPluginPointer _codec;
|
||||||
QString _selectedCodecName;
|
QString _selectedCodecName;
|
||||||
Encoder* _encoder { nullptr };
|
Encoder* _encoder { nullptr };
|
||||||
QTimer* _avatarAudioTimer;
|
QThread _avatarAudioTimerThread;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_Agent_h
|
#endif // hifi_Agent_h
|
||||||
|
|
Loading…
Reference in a new issue