mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 08:04:01 +02:00
Merge pull request #3754 from birarda/local-audio
add option for local only loopback of audio from js
This commit is contained in:
commit
f29a418e25
9 changed files with 55 additions and 28 deletions
|
@ -416,6 +416,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
|||
|
||||
_trayIcon->show();
|
||||
|
||||
// set the local loopback interface for local sounds from audio scripts
|
||||
AudioScriptingInterface::getInstance().setLocalLoopbackInterface(&_audio);
|
||||
|
||||
#ifdef HAVE_RTMIDI
|
||||
// setup the MIDIManager
|
||||
MIDIManager& midiManagerInstance = MIDIManager::getInstance();
|
||||
|
|
|
@ -184,9 +184,9 @@ QAudioDeviceInfo getNamedAudioDeviceForMode(QAudio::Mode mode, const QString& de
|
|||
QAudioDeviceInfo::defaultOutputDevice();
|
||||
#else
|
||||
foreach(QAudioDeviceInfo audioDevice, QAudioDeviceInfo::availableDevices(mode)) {
|
||||
qDebug() << audioDevice.deviceName() << " " << deviceName;
|
||||
if (audioDevice.deviceName().trimmed() == deviceName.trimmed()) {
|
||||
result = audioDevice;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -1331,9 +1331,22 @@ void Audio::startDrumSound(float volume, float frequency, float duration, float
|
|||
_drumSoundSample = 0;
|
||||
}
|
||||
|
||||
void Audio::handleAudioByteArray(const QByteArray& audioByteArray) {
|
||||
// TODO: either create a new audio device (up to the limit of the sound card or a hard limit)
|
||||
// or send to the mixer and use delayed loopback
|
||||
void Audio::handleAudioByteArray(const QByteArray& audioByteArray, const AudioInjectorOptions& injectorOptions) {
|
||||
if (audioByteArray.size() > 0) {
|
||||
QAudioFormat localFormat = _outputFormat;
|
||||
|
||||
if (!injectorOptions.isStereo()) {
|
||||
localFormat.setChannelCount(1);
|
||||
}
|
||||
|
||||
QAudioOutput* localSoundOutput = new QAudioOutput(getNamedAudioDeviceForMode(QAudio::AudioOutput, _outputAudioDeviceName), localFormat, this);
|
||||
|
||||
QIODevice* localIODevice = localSoundOutput->start();
|
||||
qDebug() << "Writing" << audioByteArray.size() << "to" << localIODevice;
|
||||
localIODevice->write(audioByteArray);
|
||||
} else {
|
||||
qDebug() << "Audio::handleAudioByteArray called with an empty byte array. Sound is likely still downloading.";
|
||||
}
|
||||
}
|
||||
|
||||
void Audio::renderToolBox(int x, int y, bool boxed) {
|
||||
|
@ -1903,6 +1916,7 @@ bool Audio::switchInputToAudioDevice(const QAudioDeviceInfo& inputDeviceInfo) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return supportedFormat;
|
||||
}
|
||||
|
||||
|
@ -1961,6 +1975,7 @@ bool Audio::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDeviceInfo)
|
|||
supportedFormat = true;
|
||||
}
|
||||
}
|
||||
|
||||
return supportedFormat;
|
||||
}
|
||||
|
||||
|
|
|
@ -155,7 +155,7 @@ public slots:
|
|||
void selectAudioFilterBassCut();
|
||||
void selectAudioFilterSmiley();
|
||||
|
||||
virtual void handleAudioByteArray(const QByteArray& audioByteArray);
|
||||
virtual void handleAudioByteArray(const QByteArray& audioByteArray, const AudioInjectorOptions& options);
|
||||
|
||||
void sendDownstreamAudioStatsPacket();
|
||||
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include "AudioInjectorOptions.h"
|
||||
|
||||
class AbstractAudioInterface : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
@ -22,7 +24,7 @@ public:
|
|||
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;
|
||||
public slots:
|
||||
virtual void handleAudioByteArray(const QByteArray& audioByteArray) = 0;
|
||||
virtual void handleAudioByteArray(const QByteArray& audioByteArray, const AudioInjectorOptions& options) = 0;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(AbstractAudioInterface*)
|
||||
|
|
|
@ -62,14 +62,6 @@ void AudioInjector::injectAudio() {
|
|||
|
||||
// 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 (_options.getLoopbackAudioInterface()) {
|
||||
// assume that localAudioInterface could be on a separate thread, use Qt::AutoConnection to handle properly
|
||||
QMetaObject::invokeMethod(_options.getLoopbackAudioInterface(), "handleAudioByteArray",
|
||||
Qt::AutoConnection,
|
||||
Q_ARG(QByteArray, soundByteArray));
|
||||
|
||||
}
|
||||
|
||||
// setup the packet for injected audio
|
||||
QByteArray injectAudioPacket = byteArrayWithPopulatedHeader(PacketTypeInjectAudio);
|
||||
|
@ -86,7 +78,7 @@ void AudioInjector::injectAudio() {
|
|||
packetStream << _options.isStereo();
|
||||
|
||||
// pack the flag for loopback
|
||||
uchar loopbackFlag = (uchar) (!_options.getLoopbackAudioInterface());
|
||||
uchar loopbackFlag = (uchar) true;
|
||||
packetStream << loopbackFlag;
|
||||
|
||||
// pack the position for injected audio
|
||||
|
|
|
@ -18,8 +18,7 @@ AudioInjectorOptions::AudioInjectorOptions(QObject* parent) :
|
|||
_loop(false),
|
||||
_orientation(glm::vec3(0.0f, 0.0f, 0.0f)),
|
||||
_isStereo(false),
|
||||
_ignorePenumbra(false),
|
||||
_loopbackAudioInterface(NULL)
|
||||
_ignorePenumbra(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -30,7 +29,6 @@ AudioInjectorOptions::AudioInjectorOptions(const AudioInjectorOptions& other) {
|
|||
_orientation = other._orientation;
|
||||
_isStereo = other._isStereo;
|
||||
_ignorePenumbra = other._ignorePenumbra;
|
||||
_loopbackAudioInterface = other._loopbackAudioInterface;
|
||||
}
|
||||
|
||||
void AudioInjectorOptions::operator=(const AudioInjectorOptions& other) {
|
||||
|
@ -40,5 +38,4 @@ void AudioInjectorOptions::operator=(const AudioInjectorOptions& other) {
|
|||
_orientation = other._orientation;
|
||||
_isStereo = other._isStereo;
|
||||
_ignorePenumbra = other._ignorePenumbra;
|
||||
_loopbackAudioInterface = other._loopbackAudioInterface;
|
||||
}
|
|
@ -19,8 +19,6 @@
|
|||
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
||||
#include "AbstractAudioInterface.h"
|
||||
|
||||
class AudioInjectorOptions : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -53,9 +51,6 @@ public:
|
|||
const bool ignorePenumbra() const {return _ignorePenumbra; }
|
||||
void setIgnorePenumbra(bool ignorePenumbra) { _ignorePenumbra = ignorePenumbra; }
|
||||
|
||||
AbstractAudioInterface* getLoopbackAudioInterface() const { return _loopbackAudioInterface; }
|
||||
void setLoopbackAudioInterface(AbstractAudioInterface* loopbackAudioInterface)
|
||||
{ _loopbackAudioInterface = loopbackAudioInterface; }
|
||||
private:
|
||||
glm::vec3 _position;
|
||||
float _volume;
|
||||
|
@ -63,7 +58,8 @@ private:
|
|||
glm::quat _orientation;
|
||||
bool _isStereo;
|
||||
bool _ignorePenumbra;
|
||||
AbstractAudioInterface* _loopbackAudioInterface;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(AudioInjectorOptions)
|
||||
|
||||
#endif // hifi_AudioInjectorOptions_h
|
||||
|
|
|
@ -16,6 +16,12 @@ AudioScriptingInterface& AudioScriptingInterface::getInstance() {
|
|||
return staticInstance;
|
||||
}
|
||||
|
||||
AudioScriptingInterface::AudioScriptingInterface() :
|
||||
_localLoopbackInterface(NULL)
|
||||
{
|
||||
qRegisterMetaType<AudioInjectorOptions>("AudioInjectorOptions");
|
||||
}
|
||||
|
||||
void AudioScriptingInterface::stopAllInjectors() {
|
||||
QList<QPointer<AudioInjector> >::iterator injector = _activeInjectors.begin();
|
||||
while (injector != _activeInjectors.end()) {
|
||||
|
@ -31,6 +37,18 @@ void AudioScriptingInterface::stopAllInjectors() {
|
|||
}
|
||||
}
|
||||
|
||||
void AudioScriptingInterface::playLocalSound(Sound* sound, const AudioInjectorOptions* injectorOptions) {
|
||||
if (sound->isStereo()) {
|
||||
const_cast<AudioInjectorOptions*>(injectorOptions)->setIsStereo(true);
|
||||
}
|
||||
|
||||
// assume that localAudioInterface could be on a separate thread, use Qt::AutoConnection to handle properly
|
||||
QMetaObject::invokeMethod(_localLoopbackInterface, "handleAudioByteArray",
|
||||
Qt::AutoConnection,
|
||||
Q_ARG(QByteArray, sound->getByteArray()),
|
||||
Q_ARG(const AudioInjectorOptions&, *injectorOptions));
|
||||
}
|
||||
|
||||
AudioInjector* AudioScriptingInterface::playSound(Sound* sound, const AudioInjectorOptions* injectorOptions) {
|
||||
|
||||
if (sound->isStereo()) {
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include <qpointer.h>
|
||||
|
||||
#include "AbstractAudioInterface.h"
|
||||
#include "AudioInjector.h"
|
||||
#include "Sound.h"
|
||||
|
||||
|
@ -25,20 +26,23 @@ public:
|
|||
static AudioScriptingInterface& getInstance();
|
||||
|
||||
void stopAllInjectors();
|
||||
|
||||
void setLocalLoopbackInterface(AbstractAudioInterface* audioInterface) { _localLoopbackInterface = audioInterface; }
|
||||
public slots:
|
||||
|
||||
static float getLoudness(AudioInjector* injector);
|
||||
|
||||
void playLocalSound(Sound *sound, const AudioInjectorOptions* injectorOptions = NULL);
|
||||
AudioInjector* playSound(Sound* sound, const AudioInjectorOptions* injectorOptions = NULL);
|
||||
|
||||
void stopInjector(AudioInjector* injector);
|
||||
bool isInjectorPlaying(AudioInjector* injector);
|
||||
|
||||
void injectorStopped();
|
||||
|
||||
private:
|
||||
AudioScriptingInterface() {};
|
||||
AudioScriptingInterface();
|
||||
QList< QPointer<AudioInjector> > _activeInjectors;
|
||||
|
||||
|
||||
AbstractAudioInterface* _localLoopbackInterface;
|
||||
};
|
||||
#endif // hifi_AudioScriptingInterface_h
|
||||
|
|
Loading…
Reference in a new issue