handle cleanup of local injection, volume

This commit is contained in:
Stephen Birarda 2014-11-11 15:12:11 -08:00
parent 83529c1fed
commit 0e30c65e60
7 changed files with 60 additions and 25 deletions

View file

@ -39,6 +39,7 @@ var ORB_SHIFT = { x: 0, y: -1.4, z: -0.8};
var HELMET_ATTACHMENT_URL = HIFI_PUBLIC_BUCKET + "models/attachments/IronManMaskOnly.fbx" var HELMET_ATTACHMENT_URL = HIFI_PUBLIC_BUCKET + "models/attachments/IronManMaskOnly.fbx"
var droneSound = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Lobby/drone.raw") var droneSound = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Lobby/drone.raw")
var currentDrone;
function reticlePosition() { function reticlePosition() {
var RETICLE_DISTANCE = 1; var RETICLE_DISTANCE = 1;
@ -90,7 +91,7 @@ function drawLobby() {
MyAvatar.attach(HELMET_ATTACHMENT_URL, "Neck", {x: 0, y: 0, z: 0}, Quat.fromPitchYawRollDegrees(0, 0, 0), 1.15); MyAvatar.attach(HELMET_ATTACHMENT_URL, "Neck", {x: 0, y: 0, z: 0}, Quat.fromPitchYawRollDegrees(0, 0, 0), 1.15);
// start the drone sound // start the drone sound
Audio.playSound(droneSound, { stereo: true, localOnly: true }); currentDrone = Audio.playSound(droneSound, { stereo: true, localOnly: true });
} }
} }
@ -121,6 +122,9 @@ function cleanupLobby() {
Overlays.deleteOverlay(orbShell); Overlays.deleteOverlay(orbShell);
Overlays.deleteOverlay(reticle); Overlays.deleteOverlay(reticle);
currentDrone.stop();
currentDrone = null;
panelWall = false; panelWall = false;
orbShell = false; orbShell = false;
reticle = false; reticle = false;

View file

@ -453,23 +453,22 @@ Application::~Application() {
// ask the datagram processing thread to quit and wait until it is done // ask the datagram processing thread to quit and wait until it is done
_nodeThread->quit(); _nodeThread->quit();
_nodeThread->wait(); _nodeThread->wait();
// kill any audio injectors that are still around
AudioScriptingInterface::getInstance().stopAllInjectors();
// stop the audio process // stop the audio process
QMetaObject::invokeMethod(&_audio, "stop"); QMetaObject::invokeMethod(&_audio, "stop");
// ask the audio thread to quit and wait until it is done // ask the audio thread to quit and wait until it is done
_audio.thread()->quit(); _audio.thread()->quit();
_audio.thread()->wait(); _audio.thread()->wait();
// kill any audio injectors that are still around
AudioScriptingInterface::getInstance().stopAllInjectors();
_octreeProcessor.terminate(); _octreeProcessor.terminate();
_voxelHideShowThread.terminate(); _voxelHideShowThread.terminate();
_voxelEditSender.terminate(); _voxelEditSender.terminate();
_entityEditSender.terminate(); _entityEditSender.terminate();
VoxelTreeElement::removeDeleteHook(&_voxels); // we don't need to do this processing on shutdown VoxelTreeElement::removeDeleteHook(&_voxels); // we don't need to do this processing on shutdown
Menu::getInstance()->deleteLater(); Menu::getInstance()->deleteLater();

View file

@ -32,19 +32,21 @@
#include <QtMultimedia/QAudioOutput> #include <QtMultimedia/QAudioOutput>
#include <QSvgRenderer> #include <QSvgRenderer>
#include <glm/glm.hpp>
#include <AudioInjector.h>
#include <NodeList.h> #include <NodeList.h>
#include <PacketHeaders.h> #include <PacketHeaders.h>
#include <SharedUtil.h> #include <SharedUtil.h>
#include <StDev.h> #include <StDev.h>
#include <UUID.h> #include <UUID.h>
#include <glm/glm.hpp>
#include "Audio.h"
#include "Menu.h" #include "Menu.h"
#include "Util.h" #include "Util.h"
#include "PositionalAudioStream.h" #include "PositionalAudioStream.h"
#include "Audio.h"
static const float AUDIO_CALLBACK_MSECS = (float) NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL / (float)SAMPLE_RATE * 1000.0; static const float AUDIO_CALLBACK_MSECS = (float) NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL / (float)SAMPLE_RATE * 1000.0;
static const int NUMBER_OF_NOISE_SAMPLE_FRAMES = 300; static const int NUMBER_OF_NOISE_SAMPLE_FRAMES = 300;
@ -1334,17 +1336,33 @@ void Audio::startDrumSound(float volume, float frequency, float duration, float
_drumSoundSample = 0; _drumSoundSample = 0;
} }
QIODevice* Audio::newLocalOutputDevice(bool isStereo, int numBytes, QObject* injector) { QIODevice* Audio::newLocalOutputDevice(bool isStereo, qreal volume, int numBytes, AudioInjector* injector) {
QAudioFormat localFormat = _desiredOutputFormat; QAudioFormat localFormat = _desiredOutputFormat;
localFormat.setChannelCount(isStereo ? 2 : 1); localFormat.setChannelCount(isStereo ? 2 : 1);
QAudioOutput* localOutput = new QAudioOutput(getNamedAudioDeviceForMode(QAudio::AudioOutput, _outputAudioDeviceName), QAudioOutput* localOutput = new QAudioOutput(getNamedAudioDeviceForMode(QAudio::AudioOutput, _outputAudioDeviceName),
localFormat, this); localFormat, this);
localOutput->setBufferSize(numBytes); localOutput->setBufferSize(numBytes);
localOutput->setVolume(volume);
// add this to our list of local injected outputs, we will need to clean it up when the injector says it is done
_injectedOutputInterfaces.insert(injector, localOutput);
connect(injector, &AudioInjector::finished, this, &Audio::cleanupLocalOutputInterface);
return localOutput->start(); return localOutput->start();
} }
void Audio::cleanupLocalOutputInterface() {
QAudioOutput* outputInterface = _injectedOutputInterfaces.value(sender());
if (outputInterface) {
qDebug() << "Stopping a QAudioOutput interface since injector" << sender() << "is finished";
outputInterface->stop();
outputInterface->deleteLater();
}
}
void Audio::renderToolBox(int x, int y, bool boxed) { void Audio::renderToolBox(int x, int y, bool boxed) {
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);

View file

@ -155,7 +155,7 @@ public slots:
void selectAudioFilterBassCut(); void selectAudioFilterBassCut();
void selectAudioFilterSmiley(); void selectAudioFilterSmiley();
virtual QIODevice* newLocalOutputDevice(bool isStereo, int numBytes, QObject* injector); virtual QIODevice* newLocalOutputDevice(bool isStereo, qreal volume, int numBytes, AudioInjector* injector);
void sendDownstreamAudioStatsPacket(); void sendDownstreamAudioStatsPacket();
@ -180,11 +180,11 @@ signals:
void processInboundAudio(unsigned int sampleTime, const QByteArray& samples, const QAudioFormat& format); void processInboundAudio(unsigned int sampleTime, const QByteArray& samples, const QAudioFormat& format);
void processLocalAudio(unsigned int sampleTime, const QByteArray& samples, const QAudioFormat& format); void processLocalAudio(unsigned int sampleTime, const QByteArray& samples, const QAudioFormat& format);
private slots:
void cleanupLocalOutputInterface();
private: private:
void outputFormatChanged(); void outputFormatChanged();
private:
QByteArray firstInputFrame; QByteArray firstInputFrame;
QAudioInput* _audioInput; QAudioInput* _audioInput;
QAudioFormat _desiredInputFormat; QAudioFormat _desiredInputFormat;
@ -365,6 +365,8 @@ private:
AudioOutputIODevice _audioOutputIODevice; AudioOutputIODevice _audioOutputIODevice;
WeakRecorderPointer _recorder; WeakRecorderPointer _recorder;
QHash<QObject*, QAudioOutput*> _injectedOutputInterfaces;
}; };

View file

@ -17,6 +17,8 @@
#include "AudioInjectorOptions.h" #include "AudioInjectorOptions.h"
class AudioInjector;
class AbstractAudioInterface : public QObject { class AbstractAudioInterface : public QObject {
Q_OBJECT Q_OBJECT
public: public:
@ -25,7 +27,7 @@ public:
virtual void startCollisionSound(float magnitude, float frequency, float noise, float duration, bool flashScreen) = 0; virtual void startCollisionSound(float magnitude, float frequency, float noise, float duration, bool flashScreen) = 0;
virtual void startDrumSound(float volume, float frequency, float duration, float decay) = 0; virtual void startDrumSound(float volume, float frequency, float duration, float decay) = 0;
public slots: public slots:
virtual QIODevice* newLocalOutputDevice(bool isStereo, int numBytes, QObject* injector) = 0; virtual QIODevice* newLocalOutputDevice(bool isStereo, qreal volume, int numBytes, AudioInjector* injector) = 0;
}; };
Q_DECLARE_METATYPE(AbstractAudioInterface*) Q_DECLARE_METATYPE(AbstractAudioInterface*)

View file

@ -36,7 +36,8 @@ AudioInjector::AudioInjector(QObject* parent) :
_shouldStop(false), _shouldStop(false),
_loudness(0.0f), _loudness(0.0f),
_isFinished(false), _isFinished(false),
_currentSendPosition(0) _currentSendPosition(0),
_localDevice(NULL)
{ {
} }
@ -67,22 +68,21 @@ void AudioInjector::injectAudio() {
} }
void AudioInjector::injectLocally() { void AudioInjector::injectLocally() {
if (_localAudioInterface) { if (_localAudioInterface) {
QIODevice* localBuffer = NULL;
const QByteArray& soundByteArray = _sound->getByteArray(); const QByteArray& soundByteArray = _sound->getByteArray();
if (soundByteArray.size() > 0) { if (soundByteArray.size() > 0) {
QMetaObject::invokeMethod(_localAudioInterface, "newLocalOutputDevice", Qt::BlockingQueuedConnection, QMetaObject::invokeMethod(_localAudioInterface, "newLocalOutputDevice", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(QIODevice*, localBuffer), Q_RETURN_ARG(QIODevice*, _localDevice),
Q_ARG(bool, _options.stereo), Q_ARG(bool, _options.stereo),
Q_ARG(qreal, _options.volume),
Q_ARG(int, soundByteArray.size()), Q_ARG(int, soundByteArray.size()),
Q_ARG(QObject*, this)); Q_ARG(AudioInjector*, this));
if (localBuffer) { if (_localDevice) {
// immediately write the byte array to the local device // immediately write the byte array to the local device
qDebug() << "Writing" << localBuffer->write(soundByteArray) << "bytes to local audio device"; qDebug() << "Writing" << soundByteArray.size() << "bytes to local audio device";
_localDevice->write(soundByteArray);
} else { } else {
qDebug() << "AudioInjector::injectLocally did not get a valid QIODevice from _localAudioInterface"; qDebug() << "AudioInjector::injectLocally did not get a valid QIODevice from _localAudioInterface";
} }
@ -220,3 +220,13 @@ void AudioInjector::injectToMixer() {
_isFinished = true; _isFinished = true;
emit finished(); emit finished();
} }
void AudioInjector::stop() {
_shouldStop = true;
if (_localDevice) {
// we're only a local injector, so we can say we are finished and the AbstractAudioInterface should clean us up
_isFinished = true;
emit finished();
}
}

View file

@ -35,7 +35,7 @@ public:
void setLocalAudioInterface(AbstractAudioInterface* localAudioInterface) { _localAudioInterface = localAudioInterface; } void setLocalAudioInterface(AbstractAudioInterface* localAudioInterface) { _localAudioInterface = localAudioInterface; }
public slots: public slots:
void injectAudio(); void injectAudio();
void stop() { _shouldStop = true; } void stop();
void setOptions(AudioInjectorOptions& options); void setOptions(AudioInjectorOptions& options);
void setCurrentSendPosition(int currentSendPosition) { _currentSendPosition = currentSendPosition; } void setCurrentSendPosition(int currentSendPosition) { _currentSendPosition = currentSendPosition; }
float getLoudness(); float getLoudness();
@ -53,7 +53,7 @@ private:
bool _isFinished; bool _isFinished;
int _currentSendPosition; int _currentSendPosition;
AbstractAudioInterface* _localAudioInterface; AbstractAudioInterface* _localAudioInterface;
QIODevice* _localDevice;
}; };
Q_DECLARE_METATYPE(AudioInjector*) Q_DECLARE_METATYPE(AudioInjector*)