mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 01:36:56 +02:00
Merge pull request #10986 from Atlante45/fix/avatar-audio-timer
Use timer instead of dedicated thread to tick AC scripted avatar audio
This commit is contained in:
commit
6e59e451c4
4 changed files with 15 additions and 86 deletions
|
@ -51,14 +51,14 @@
|
||||||
#include "RecordingScriptingInterface.h"
|
#include "RecordingScriptingInterface.h"
|
||||||
#include "AbstractAudioInterface.h"
|
#include "AbstractAudioInterface.h"
|
||||||
|
|
||||||
#include "AvatarAudioTimer.h"
|
|
||||||
|
|
||||||
static const int RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES = 10;
|
static const int RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES = 10;
|
||||||
|
|
||||||
Agent::Agent(ReceivedMessage& message) :
|
Agent::Agent(ReceivedMessage& message) :
|
||||||
ThreadedAssignment(message),
|
ThreadedAssignment(message),
|
||||||
_receivedAudioStream(RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES, RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES),
|
_receivedAudioStream(RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES, RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES),
|
||||||
_audioGate(AudioConstants::SAMPLE_RATE, AudioConstants::MONO)
|
_audioGate(AudioConstants::SAMPLE_RATE, AudioConstants::MONO),
|
||||||
|
_avatarAudioTimer(this)
|
||||||
{
|
{
|
||||||
_entityEditSender.setPacketsPerSecond(DEFAULT_ENTITY_PPS_PER_SCRIPT);
|
_entityEditSender.setPacketsPerSecond(DEFAULT_ENTITY_PPS_PER_SCRIPT);
|
||||||
DependencyManager::get<EntityScriptingInterface>()->setPacketSender(&_entityEditSender);
|
DependencyManager::get<EntityScriptingInterface>()->setPacketSender(&_entityEditSender);
|
||||||
|
@ -96,6 +96,14 @@ Agent::Agent(ReceivedMessage& message) :
|
||||||
this, "handleOctreePacket");
|
this, "handleOctreePacket");
|
||||||
packetReceiver.registerListener(PacketType::Jurisdiction, this, "handleJurisdictionPacket");
|
packetReceiver.registerListener(PacketType::Jurisdiction, this, "handleJurisdictionPacket");
|
||||||
packetReceiver.registerListener(PacketType::SelectedAudioFormat, this, "handleSelectedAudioFormat");
|
packetReceiver.registerListener(PacketType::SelectedAudioFormat, this, "handleSelectedAudioFormat");
|
||||||
|
|
||||||
|
|
||||||
|
// 100Hz timer for audio
|
||||||
|
const int TARGET_INTERVAL_MSEC = 10; // 10ms
|
||||||
|
connect(&_avatarAudioTimer, &QTimer::timeout, this, &Agent::processAgentAvatarAudio);
|
||||||
|
_avatarAudioTimer.setSingleShot(false);
|
||||||
|
_avatarAudioTimer.setInterval(TARGET_INTERVAL_MSEC);
|
||||||
|
_avatarAudioTimer.setTimerType(Qt::PreciseTimer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Agent::playAvatarSound(SharedSoundPointer sound) {
|
void Agent::playAvatarSound(SharedSoundPointer sound) {
|
||||||
|
@ -475,14 +483,7 @@ void Agent::executeScript() {
|
||||||
|
|
||||||
DependencyManager::set<AssignmentParentFinder>(_entityViewer.getTree());
|
DependencyManager::set<AssignmentParentFinder>(_entityViewer.getTree());
|
||||||
|
|
||||||
// 100Hz timer for audio
|
QMetaObject::invokeMethod(&_avatarAudioTimer, "start");
|
||||||
AvatarAudioTimer* audioTimerWorker = new AvatarAudioTimer();
|
|
||||||
audioTimerWorker->moveToThread(&_avatarAudioTimerThread);
|
|
||||||
connect(audioTimerWorker, &AvatarAudioTimer::avatarTick, this, &Agent::processAgentAvatarAudio);
|
|
||||||
connect(this, &Agent::startAvatarAudioTimer, audioTimerWorker, &AvatarAudioTimer::start);
|
|
||||||
connect(this, &Agent::stopAvatarAudioTimer, audioTimerWorker, &AvatarAudioTimer::stop);
|
|
||||||
connect(&_avatarAudioTimerThread, &QThread::finished, audioTimerWorker, &QObject::deleteLater);
|
|
||||||
_avatarAudioTimerThread.start();
|
|
||||||
|
|
||||||
// Agents should run at 45hz
|
// Agents should run at 45hz
|
||||||
static const int AVATAR_DATA_HZ = 45;
|
static const int AVATAR_DATA_HZ = 45;
|
||||||
|
@ -561,7 +562,7 @@ void Agent::setIsAvatar(bool isAvatar) {
|
||||||
_avatarIdentityTimer->start(AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS); // FIXME - we shouldn't really need to constantly send identity packets
|
_avatarIdentityTimer->start(AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS); // FIXME - we shouldn't really need to constantly send identity packets
|
||||||
|
|
||||||
// tell the avatarAudioTimer to start ticking
|
// tell the avatarAudioTimer to start ticking
|
||||||
emit startAvatarAudioTimer();
|
QMetaObject::invokeMethod(&_avatarAudioTimer, "start");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -590,7 +591,7 @@ void Agent::setIsAvatar(bool isAvatar) {
|
||||||
nodeList->sendPacket(std::move(packet), *node);
|
nodeList->sendPacket(std::move(packet), *node);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
emit stopAvatarAudioTimer();
|
QMetaObject::invokeMethod(&_avatarAudioTimer, "stop");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -818,9 +819,7 @@ void Agent::aboutToFinish() {
|
||||||
DependencyManager::destroy<recording::Recorder>();
|
DependencyManager::destroy<recording::Recorder>();
|
||||||
DependencyManager::destroy<recording::ClipCache>();
|
DependencyManager::destroy<recording::ClipCache>();
|
||||||
|
|
||||||
emit stopAvatarAudioTimer();
|
QMetaObject::invokeMethod(&_avatarAudioTimer, "stop");
|
||||||
_avatarAudioTimerThread.quit();
|
|
||||||
_avatarAudioTimerThread.wait();
|
|
||||||
|
|
||||||
// cleanup codec & encoder
|
// cleanup codec & encoder
|
||||||
if (_codec && _encoder) {
|
if (_codec && _encoder) {
|
||||||
|
|
|
@ -81,9 +81,6 @@ private slots:
|
||||||
void processAgentAvatar();
|
void processAgentAvatar();
|
||||||
void processAgentAvatarAudio();
|
void processAgentAvatarAudio();
|
||||||
|
|
||||||
signals:
|
|
||||||
void startAvatarAudioTimer();
|
|
||||||
void stopAvatarAudioTimer();
|
|
||||||
private:
|
private:
|
||||||
void negotiateAudioFormat();
|
void negotiateAudioFormat();
|
||||||
void selectAudioFormat(const QString& selectedCodecName);
|
void selectAudioFormat(const QString& selectedCodecName);
|
||||||
|
@ -118,7 +115,7 @@ private:
|
||||||
CodecPluginPointer _codec;
|
CodecPluginPointer _codec;
|
||||||
QString _selectedCodecName;
|
QString _selectedCodecName;
|
||||||
Encoder* _encoder { nullptr };
|
Encoder* _encoder { nullptr };
|
||||||
QThread _avatarAudioTimerThread;
|
QTimer _avatarAudioTimer;
|
||||||
bool _flushEncoder { false };
|
bool _flushEncoder { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
//
|
|
||||||
// AvatarAudioTimer.cpp
|
|
||||||
// assignment-client/src
|
|
||||||
//
|
|
||||||
// Created by David Kelly on 10/12/13.
|
|
||||||
// Copyright 2016 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
#include <QDebug>
|
|
||||||
#include <SharedUtil.h>
|
|
||||||
#include "AvatarAudioTimer.h"
|
|
||||||
|
|
||||||
// this should send a signal every 10ms, with pretty good precision. Hardcoding
|
|
||||||
// to 10ms since that's what you'd want for audio.
|
|
||||||
void AvatarAudioTimer::start() {
|
|
||||||
auto startTime = usecTimestampNow();
|
|
||||||
quint64 frameCounter = 0;
|
|
||||||
const int TARGET_INTERVAL_USEC = 10000; // 10ms
|
|
||||||
while (!_quit) {
|
|
||||||
++frameCounter;
|
|
||||||
|
|
||||||
// tick every 10ms from startTime
|
|
||||||
quint64 targetTime = startTime + frameCounter * TARGET_INTERVAL_USEC;
|
|
||||||
quint64 now = usecTimestampNow();
|
|
||||||
|
|
||||||
// avoid quint64 underflow
|
|
||||||
if (now < targetTime) {
|
|
||||||
usleep(targetTime - now);
|
|
||||||
}
|
|
||||||
|
|
||||||
emit avatarTick();
|
|
||||||
}
|
|
||||||
qDebug() << "AvatarAudioTimer is finished";
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
//
|
|
||||||
// AvatarAudioTimer.h
|
|
||||||
// assignment-client/src
|
|
||||||
//
|
|
||||||
// Created by David Kelly on 10/12/13.
|
|
||||||
// Copyright 2016 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef hifi_AvatarAudioTimer_h
|
|
||||||
#define hifi_AvatarAudioTimer_h
|
|
||||||
|
|
||||||
#include <QtCore/QObject>
|
|
||||||
|
|
||||||
class AvatarAudioTimer : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void avatarTick();
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void start();
|
|
||||||
void stop() { _quit = true; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool _quit { false };
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //hifi_AvatarAudioTimer_h
|
|
Loading…
Reference in a new issue