From 3123b83d0bfdfe5c66dffc1abf6e8ad6254971b3 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 2 Jan 2014 11:53:33 -0800 Subject: [PATCH 1/4] audio API changes to allow multiple injections of single sound --- libraries/audio/src/AudioInjector.cpp | 58 +++++++++------------------ libraries/audio/src/AudioInjector.h | 25 +++--------- libraries/audio/src/Sound.cpp | 29 ++++++++++++++ libraries/audio/src/Sound.h | 27 +++++++++++++ 4 files changed, 81 insertions(+), 58 deletions(-) create mode 100644 libraries/audio/src/Sound.cpp create mode 100644 libraries/audio/src/Sound.h diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 00c1fa2b21..315c384e8b 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -2,16 +2,10 @@ // AudioInjector.cpp // hifi // -// Created by Stephen Birarda on 12/19/2013. +// Created by Stephen Birarda on 1/2/2014. // Copyright (c) 2013 HighFidelity, Inc. All rights reserved. // -#include - -#include -#include -#include - #include #include #include @@ -24,13 +18,12 @@ int abstractAudioPointerMeta = qRegisterMetaType("AbstractAudioInterface*"); -AudioInjector::AudioInjector(const QUrl& sampleURL) : - _currentSendPosition(0), - _sourceURL(sampleURL), - _position(0,0,0), - _orientation(), +AudioInjector::AudioInjector(Sound* sound) : + _sound(sound), _volume(1.0f), - _shouldLoopback(true) + _shouldLoopback(true), + _position(0.0f, 0.0f, 0.0f), + _orientation() { // we want to live on our own thread moveToThread(&_thread); @@ -38,45 +31,30 @@ AudioInjector::AudioInjector(const QUrl& sampleURL) : _thread.start(); } -void AudioInjector::startDownload() { - // assume we have a QApplication or QCoreApplication instance and use the - // QNetworkAccess manager to grab the raw audio file at the given URL - - QNetworkAccessManager *manager = new QNetworkAccessManager(this); - connect(manager, SIGNAL(finished(QNetworkReply*)), - this, SLOT(replyFinished(QNetworkReply*))); - - manager->get(QNetworkRequest(_sourceURL)); -} - -void AudioInjector::replyFinished(QNetworkReply* reply) { - // replace our samples array with the downloaded data - _sampleByteArray = reply->readAll(); -} - void AudioInjector::injectViaThread(AbstractAudioInterface* localAudioInterface) { // use Qt::AutoConnection so that this is called on our thread, if appropriate QMetaObject::invokeMethod(this, "injectAudio", Qt::AutoConnection, Q_ARG(AbstractAudioInterface*, localAudioInterface)); } +const uchar MAX_INJECTOR_VOLUME = 0xFF; + void AudioInjector::injectAudio(AbstractAudioInterface* localAudioInterface) { + QByteArray soundByteArray = _sound->getByteArray(); + // make sure we actually have samples downloaded to inject - if (_sampleByteArray.size()) { + if (soundByteArray.size()) { // give our sample byte array to the local audio interface, if we have it, so it can be handled locally if (localAudioInterface) { // assume that localAudioInterface could be on a separate thread, use Qt::AutoConnection to handle properly QMetaObject::invokeMethod(localAudioInterface, "handleAudioByteArray", Qt::AutoConnection, - Q_ARG(QByteArray, _sampleByteArray)); + Q_ARG(QByteArray, soundByteArray)); } NodeList* nodeList = NodeList::getInstance(); - // reset the current send position to the beginning - _currentSendPosition = 0; - // setup the packet for injected audio unsigned char injectedAudioPacket[MAX_PACKET_SIZE]; unsigned char* currentPacketPosition = injectedAudioPacket; @@ -121,14 +99,16 @@ void AudioInjector::injectAudio(AbstractAudioInterface* localAudioInterface) { gettimeofday(&startTime, NULL); int nextFrame = 0; + int currentSendPosition = 0; + // loop to send off our audio in NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL byte chunks - while (_currentSendPosition < _sampleByteArray.size()) { + while (currentSendPosition < soundByteArray.size()) { int bytesToCopy = std::min(NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL, - _sampleByteArray.size() - _currentSendPosition); + soundByteArray.size() - currentSendPosition); // copy the next NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL bytes to the packet - memcpy(currentPacketPosition, _sampleByteArray.data() + _currentSendPosition, + memcpy(currentPacketPosition, soundByteArray.data() + currentSendPosition, bytesToCopy); @@ -143,11 +123,11 @@ void AudioInjector::injectAudio(AbstractAudioInterface* localAudioInterface) { audioMixer->getActiveSocket()->getPort()); } - _currentSendPosition += bytesToCopy; + currentSendPosition += bytesToCopy; // send two packets before the first sleep so the mixer can start playback right away - if (_currentSendPosition != bytesToCopy && _currentSendPosition < _sampleByteArray.size()) { + if (currentSendPosition != bytesToCopy && currentSendPosition < soundByteArray.size()) { // not the first packet and not done // sleep for the appropriate time int usecToSleep = usecTimestamp(&startTime) + (++nextFrame * BUFFER_SEND_INTERVAL_USECS) - usecTimestampNow(); diff --git a/libraries/audio/src/AudioInjector.h b/libraries/audio/src/AudioInjector.h index 425ae7477f..38e280d623 100644 --- a/libraries/audio/src/AudioInjector.h +++ b/libraries/audio/src/AudioInjector.h @@ -2,7 +2,7 @@ // AudioInjector.h // hifi // -// Created by Stephen Birarda on 12/19/2013. +// Created by Stephen Birarda on 1/2/2014. // Copyright (c) 2013 HighFidelity, Inc. All rights reserved. // @@ -11,22 +11,15 @@ #include #include -#include #include #include -class AbstractAudioInterface; -class QNetworkReply; - -const uchar MAX_INJECTOR_VOLUME = 0xFF; +#include "Sound.h" class AudioInjector : public QObject { - Q_OBJECT public: - AudioInjector(const QUrl& sampleURL); - - int size() const { return _sampleByteArray.size(); } + AudioInjector(Sound* sound); void setPosition(const glm::vec3& position) { _position = position; } void setOrientation(const glm::quat& orientation) { _orientation = orientation; } @@ -34,20 +27,14 @@ public: void setShouldLoopback(bool shouldLoopback) { _shouldLoopback = shouldLoopback; } public slots: void injectViaThread(AbstractAudioInterface* localAudioInterface = NULL); - private: - QByteArray _sampleByteArray; - int _currentSendPosition; QThread _thread; - QUrl _sourceURL; - glm::vec3 _position; - glm::quat _orientation; + Sound* _sound; float _volume; uchar _shouldLoopback; - + glm::vec3 _position; + glm::quat _orientation; private slots: - void startDownload(); - void replyFinished(QNetworkReply* reply); void injectAudio(AbstractAudioInterface* localAudioInterface); }; diff --git a/libraries/audio/src/Sound.cpp b/libraries/audio/src/Sound.cpp new file mode 100644 index 0000000000..147df5c10f --- /dev/null +++ b/libraries/audio/src/Sound.cpp @@ -0,0 +1,29 @@ +// +// Sound.cpp +// hifi +// +// Created by Stephen Birarda on 1/2/2014. +// Copyright (c) 2013 HighFidelity, Inc. All rights reserved. +// + +#include +#include +#include + +#include "Sound.h" + +Sound::Sound(const QUrl& sampleURL) { + // assume we have a QApplication or QCoreApplication instance and use the + // QNetworkAccess manager to grab the raw audio file at the given URL + + QNetworkAccessManager *manager = new QNetworkAccessManager(this); + connect(manager, SIGNAL(finished(QNetworkReply*)), + this, SLOT(replyFinished(QNetworkReply*))); + + manager->get(QNetworkRequest(sampleURL)); +} + +void Sound::replyFinished(QNetworkReply* reply) { + // replace our samples array with the downloaded data + _sampleByteArray = reply->readAll(); +} \ No newline at end of file diff --git a/libraries/audio/src/Sound.h b/libraries/audio/src/Sound.h new file mode 100644 index 0000000000..c5ca9f9c3f --- /dev/null +++ b/libraries/audio/src/Sound.h @@ -0,0 +1,27 @@ +// +// Sound.h +// hifi +// +// Created by Stephen Birarda on 1/2/2014. +// Copyright (c) 2013 HighFidelity, Inc. All rights reserved. +// + +#ifndef __hifi__Sound__ +#define __hifi__Sound__ + +#include + +class QNetworkReply; + +class Sound : public QObject { +public: + Sound(const QUrl& sampleURL); + + const QByteArray& getByteArray() { return _byteArray; } +private: + QByteArray _byteArray; +private slots: + void replyFinished(QNetworkReply* reply); +}; + +#endif /* defined(__hifi__Sound__) */ From 674c19a570e144073ed948d5295344076dd1d879 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 2 Jan 2014 12:17:18 -0800 Subject: [PATCH 2/4] leverage new AudioInjector API for throw and catch sounds --- interface/src/avatar/Hand.cpp | 22 +++++---------- interface/src/avatar/Hand.h | 4 +-- libraries/audio/src/AudioInjector.cpp | 39 +++++++++++++++++---------- libraries/audio/src/AudioInjector.h | 24 ++++++++++------- libraries/audio/src/Sound.cpp | 4 +-- 5 files changed, 50 insertions(+), 43 deletions(-) diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 5f712d947b..b85fa94ef0 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -54,8 +54,8 @@ Hand::Hand(Avatar* owningAvatar) : _grabDeltaVelocity(0, 0, 0), _grabStartRotation(0, 0, 0, 1), _grabCurrentRotation(0, 0, 0, 1), - _throwInjector(QUrl("https://dl.dropboxusercontent.com/u/1864924/hifi-sounds/throw.raw")), - _catchInjector(QUrl("https://dl.dropboxusercontent.com/u/1864924/hifi-sounds/catch.raw")) + _throwSound(QUrl("https://dl.dropboxusercontent.com/u/1864924/hifi-sounds/throw.raw")), + _catchSound(QUrl("https://dl.dropboxusercontent.com/u/1864924/hifi-sounds/catch.raw")) { for (int i = 0; i < MAX_HANDS; i++) { _toyBallInHand[i] = false; @@ -63,10 +63,6 @@ Hand::Hand(Avatar* owningAvatar) : _whichBallColor[i] = 0; } _lastControllerButtons = 0; - - // the throw and catch sounds should not loopback, we'll play them locally - _throwInjector.setShouldLoopback(false); - _catchInjector.setShouldLoopback(false); } void Hand::init() { @@ -128,11 +124,8 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f _ballParticleEditHandles[handID] = caughtParticle; caughtParticle = NULL; - // set the position of the catch sound to the new position of the ball - _catchInjector.setPosition(targetPosition); - - // inject the catch sound to the mixer and play it locally - _catchInjector.injectViaThread(app->getAudio()); + // use the threadSound static method to inject the catch sound + AudioInjector::threadSound(&_catchSound, targetPosition); } } @@ -214,11 +207,8 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f delete _ballParticleEditHandles[handID]; _ballParticleEditHandles[handID] = NULL; - // move the throw injector to inject from the position of the ball - _throwInjector.setPosition(ballPosition); - - // inject the throw sound and play it locally - _throwInjector.injectViaThread(app->getAudio()); + // use the threadSound static method to inject the throw sound + AudioInjector::threadSound(&_throwSound, targetPosition); } } diff --git a/interface/src/avatar/Hand.h b/interface/src/avatar/Hand.h index e938135a29..88ca4a61e7 100755 --- a/interface/src/avatar/Hand.h +++ b/interface/src/avatar/Hand.h @@ -114,8 +114,8 @@ private: glm::quat _grabStartRotation; glm::quat _grabCurrentRotation; - AudioInjector _throwInjector; - AudioInjector _catchInjector; + Sound _throwSound; + Sound _catchSound; }; #endif diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 315c384e8b..87a0b2c833 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -18,36 +18,46 @@ int abstractAudioPointerMeta = qRegisterMetaType("AbstractAudioInterface*"); -AudioInjector::AudioInjector(Sound* sound) : +AudioInjector::AudioInjector(Sound* sound, const glm::vec3 position, float volume, + const glm::quat orientation, bool shouldLoopback, + AbstractAudioInterface* loopbackAudioInterface) : _sound(sound), - _volume(1.0f), - _shouldLoopback(true), - _position(0.0f, 0.0f, 0.0f), - _orientation() + _volume(volume), + _shouldLoopback(shouldLoopback), + _position(position), + _orientation(orientation), + _loopbackAudioInterface(loopbackAudioInterface) { // we want to live on our own thread moveToThread(&_thread); - connect(&_thread, SIGNAL(started()), this, SLOT(startDownload())); - _thread.start(); } -void AudioInjector::injectViaThread(AbstractAudioInterface* localAudioInterface) { - // use Qt::AutoConnection so that this is called on our thread, if appropriate - QMetaObject::invokeMethod(this, "injectAudio", Qt::AutoConnection, Q_ARG(AbstractAudioInterface*, localAudioInterface)); +void AudioInjector::threadSound(Sound* sound, const glm::vec3 position, float volume, + const glm::quat orientation, bool shouldLoopback, AbstractAudioInterface* audioInterface) { + AudioInjector injector(sound, position, volume, orientation, shouldLoopback, audioInterface); + + // start injecting when the injector thread starts + connect(&injector._thread, SIGNAL(started()), &injector, SLOT(injectAudio())); + + // connect the right slots and signals so that the AudioInjector is killed once the injection is complete + connect(&injector, SIGNAL(finished()), &injector._thread, SLOT(quit())); + connect(&injector, SIGNAL(finished()), &injector, SLOT(deleteLater())); + + injector._thread.start(); } const uchar MAX_INJECTOR_VOLUME = 0xFF; -void AudioInjector::injectAudio(AbstractAudioInterface* localAudioInterface) { +void AudioInjector::injectAudio() { QByteArray soundByteArray = _sound->getByteArray(); // make sure we actually have samples downloaded to inject if (soundByteArray.size()) { // give our sample byte array to the local audio interface, if we have it, so it can be handled locally - if (localAudioInterface) { + if (_loopbackAudioInterface) { // assume that localAudioInterface could be on a separate thread, use Qt::AutoConnection to handle properly - QMetaObject::invokeMethod(localAudioInterface, "handleAudioByteArray", + QMetaObject::invokeMethod(_loopbackAudioInterface, "handleAudioByteArray", Qt::AutoConnection, Q_ARG(QByteArray, soundByteArray)); @@ -137,6 +147,7 @@ void AudioInjector::injectAudio(AbstractAudioInterface* localAudioInterface) { } } } - } + + emit finished(); } \ No newline at end of file diff --git a/libraries/audio/src/AudioInjector.h b/libraries/audio/src/AudioInjector.h index 38e280d623..9bfd486807 100644 --- a/libraries/audio/src/AudioInjector.h +++ b/libraries/audio/src/AudioInjector.h @@ -17,25 +17,31 @@ #include "Sound.h" +class AbstractAudioInterface; + class AudioInjector : public QObject { public: - AudioInjector(Sound* sound); - - void setPosition(const glm::vec3& position) { _position = position; } - void setOrientation(const glm::quat& orientation) { _orientation = orientation; } - void setVolume(float volume) { _volume = std::max(fabsf(volume), 1.0f); } - void setShouldLoopback(bool shouldLoopback) { _shouldLoopback = shouldLoopback; } -public slots: - void injectViaThread(AbstractAudioInterface* localAudioInterface = NULL); + static void threadSound(Sound* sound, + const glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f), + float volume = 1.0f, + const glm::quat orientation = glm::quat(), + bool shouldLoopback = true, + AbstractAudioInterface* loopbackAudioInterface = NULL); private: + AudioInjector(Sound* sound, const glm::vec3 position, float volume, + const glm::quat orientation, bool shouldLoopback, AbstractAudioInterface* loopbackAudioInterface); + QThread _thread; Sound* _sound; float _volume; uchar _shouldLoopback; glm::vec3 _position; glm::quat _orientation; + AbstractAudioInterface* _loopbackAudioInterface; private slots: - void injectAudio(AbstractAudioInterface* localAudioInterface); + void injectAudio(); +signals: + void finished(); }; #endif /* defined(__hifi__AudioInjector__) */ diff --git a/libraries/audio/src/Sound.cpp b/libraries/audio/src/Sound.cpp index 147df5c10f..0362561fff 100644 --- a/libraries/audio/src/Sound.cpp +++ b/libraries/audio/src/Sound.cpp @@ -24,6 +24,6 @@ Sound::Sound(const QUrl& sampleURL) { } void Sound::replyFinished(QNetworkReply* reply) { - // replace our samples array with the downloaded data - _sampleByteArray = reply->readAll(); + // replace our byte array with the downloaded data + _byteArray = reply->readAll(); } \ No newline at end of file From 3a45fb8533b9f8063938c6ca6012f952ff47d47a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 2 Jan 2014 12:31:01 -0800 Subject: [PATCH 3/4] cleanup new API for sound injection --- interface/src/avatar/Hand.cpp | 16 ++++++++++++++-- libraries/audio/src/AudioInjector.cpp | 19 ++++++++----------- libraries/audio/src/AudioInjector.h | 25 +++++++++++++++++-------- libraries/audio/src/Sound.h | 1 + 4 files changed, 40 insertions(+), 21 deletions(-) diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index b85fa94ef0..6b776f5cfa 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -125,7 +125,13 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f caughtParticle = NULL; // use the threadSound static method to inject the catch sound - AudioInjector::threadSound(&_catchSound, targetPosition); + // pass an AudioInjectorOptions struct to set position and disable loopback + AudioInjectorOptions injectorOptions; + injectorOptions.position = targetPosition; + injectorOptions.shouldLoopback = false; + injectorOptions.loopbackAudioInterface = app->getAudio(); + + AudioInjector::threadSound(&_catchSound, injectorOptions); } } @@ -208,7 +214,13 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f _ballParticleEditHandles[handID] = NULL; // use the threadSound static method to inject the throw sound - AudioInjector::threadSound(&_throwSound, targetPosition); + // pass an AudioInjectorOptions struct to set position and disable loopback + AudioInjectorOptions injectorOptions; + injectorOptions.position = targetPosition; + injectorOptions.shouldLoopback = false; + injectorOptions.loopbackAudioInterface = app->getAudio(); + + AudioInjector::threadSound(&_throwSound, injectorOptions); } } diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 87a0b2c833..78bc157afe 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -18,23 +18,20 @@ int abstractAudioPointerMeta = qRegisterMetaType("AbstractAudioInterface*"); -AudioInjector::AudioInjector(Sound* sound, const glm::vec3 position, float volume, - const glm::quat orientation, bool shouldLoopback, - AbstractAudioInterface* loopbackAudioInterface) : +AudioInjector::AudioInjector(Sound* sound, AudioInjectorOptions injectorOptions) : _sound(sound), - _volume(volume), - _shouldLoopback(shouldLoopback), - _position(position), - _orientation(orientation), - _loopbackAudioInterface(loopbackAudioInterface) + _volume(injectorOptions.volume), + _shouldLoopback(injectorOptions.shouldLoopback), + _position(injectorOptions.position), + _orientation(injectorOptions.orientation), + _loopbackAudioInterface(injectorOptions.loopbackAudioInterface) { // we want to live on our own thread moveToThread(&_thread); } -void AudioInjector::threadSound(Sound* sound, const glm::vec3 position, float volume, - const glm::quat orientation, bool shouldLoopback, AbstractAudioInterface* audioInterface) { - AudioInjector injector(sound, position, volume, orientation, shouldLoopback, audioInterface); +void AudioInjector::threadSound(Sound* sound, AudioInjectorOptions injectorOptions) { + AudioInjector injector(sound, injectorOptions); // start injecting when the injector thread starts connect(&injector._thread, SIGNAL(started()), &injector, SLOT(injectAudio())); diff --git a/libraries/audio/src/AudioInjector.h b/libraries/audio/src/AudioInjector.h index 9bfd486807..10a1335fe8 100644 --- a/libraries/audio/src/AudioInjector.h +++ b/libraries/audio/src/AudioInjector.h @@ -19,17 +19,26 @@ class AbstractAudioInterface; +struct AudioInjectorOptions { + AudioInjectorOptions() : position(glm::vec3(0.0f, 0.0f, 0.0f)), + volume(1.0f), + orientation(glm::quat()), + shouldLoopback(true), + loopbackAudioInterface(NULL) {}; + + glm::vec3 position; + float volume; + const glm::quat orientation; + bool shouldLoopback; + AbstractAudioInterface* loopbackAudioInterface; +}; + class AudioInjector : public QObject { + Q_OBJECT public: - static void threadSound(Sound* sound, - const glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f), - float volume = 1.0f, - const glm::quat orientation = glm::quat(), - bool shouldLoopback = true, - AbstractAudioInterface* loopbackAudioInterface = NULL); + static void threadSound(Sound* sound, AudioInjectorOptions injectorOptions = AudioInjectorOptions()); private: - AudioInjector(Sound* sound, const glm::vec3 position, float volume, - const glm::quat orientation, bool shouldLoopback, AbstractAudioInterface* loopbackAudioInterface); + AudioInjector(Sound* sound, AudioInjectorOptions injectorOptions); QThread _thread; Sound* _sound; diff --git a/libraries/audio/src/Sound.h b/libraries/audio/src/Sound.h index c5ca9f9c3f..e9a6e856ba 100644 --- a/libraries/audio/src/Sound.h +++ b/libraries/audio/src/Sound.h @@ -14,6 +14,7 @@ class QNetworkReply; class Sound : public QObject { + Q_OBJECT public: Sound(const QUrl& sampleURL); From 8cc4a33ad3af30377c1de3585ba6316ead4ce150 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 2 Jan 2014 13:35:56 -0800 Subject: [PATCH 4/4] repair AudioInjector threading --- libraries/audio/src/AudioInjector.cpp | 16 ++++++++++------ libraries/audio/src/AudioInjector.h | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 78bc157afe..5ad4dc6f4d 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -19,6 +19,7 @@ int abstractAudioPointerMeta = qRegisterMetaType("AbstractAudioInterface*"); AudioInjector::AudioInjector(Sound* sound, AudioInjectorOptions injectorOptions) : + _thread(NULL), _sound(sound), _volume(injectorOptions.volume), _shouldLoopback(injectorOptions.shouldLoopback), @@ -26,21 +27,24 @@ AudioInjector::AudioInjector(Sound* sound, AudioInjectorOptions injectorOptions) _orientation(injectorOptions.orientation), _loopbackAudioInterface(injectorOptions.loopbackAudioInterface) { + _thread = new QThread(); + // we want to live on our own thread - moveToThread(&_thread); + moveToThread(_thread); } void AudioInjector::threadSound(Sound* sound, AudioInjectorOptions injectorOptions) { - AudioInjector injector(sound, injectorOptions); + AudioInjector* injector = new AudioInjector(sound, injectorOptions); // start injecting when the injector thread starts - connect(&injector._thread, SIGNAL(started()), &injector, SLOT(injectAudio())); + connect(injector->_thread, SIGNAL(started()), injector, SLOT(injectAudio())); // connect the right slots and signals so that the AudioInjector is killed once the injection is complete - connect(&injector, SIGNAL(finished()), &injector._thread, SLOT(quit())); - connect(&injector, SIGNAL(finished()), &injector, SLOT(deleteLater())); + connect(injector, SIGNAL(finished()), injector, SLOT(deleteLater())); + connect(injector, SIGNAL(finished()), injector->_thread, SLOT(quit())); + connect(injector->_thread, SIGNAL(finished()), injector->_thread, SLOT(deleteLater())); - injector._thread.start(); + injector->_thread->start(); } const uchar MAX_INJECTOR_VOLUME = 0xFF; diff --git a/libraries/audio/src/AudioInjector.h b/libraries/audio/src/AudioInjector.h index 10a1335fe8..f2e7b3b498 100644 --- a/libraries/audio/src/AudioInjector.h +++ b/libraries/audio/src/AudioInjector.h @@ -40,7 +40,7 @@ public: private: AudioInjector(Sound* sound, AudioInjectorOptions injectorOptions); - QThread _thread; + QThread* _thread; Sound* _sound; float _volume; uchar _shouldLoopback;