From cd3877b5847301e213fb0dbe3a81a436666c097e Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 11 Nov 2014 14:14:43 -0800 Subject: [PATCH] handle local audio output via AudioInjector directly for control --- examples/lobby.js | 6 +++- interface/src/Audio.cpp | 9 ++++-- interface/src/Audio.h | 2 +- libraries/audio/src/AbstractAudioInterface.h | 2 +- libraries/audio/src/AudioInjector.cpp | 30 +++++++++++++++++++- libraries/audio/src/AudioInjector.h | 3 ++ libraries/audio/src/AudioInjectorOptions.cpp | 8 +++++- libraries/audio/src/AudioInjectorOptions.h | 1 + 8 files changed, 53 insertions(+), 8 deletions(-) diff --git a/examples/lobby.js b/examples/lobby.js index 63ea1654a9..e6db57bdd5 100644 --- a/examples/lobby.js +++ b/examples/lobby.js @@ -37,7 +37,8 @@ var panelsCenterShift = Vec3.subtract(panelsCenter, orbCenter); var ORB_SHIFT = { x: 0, y: -1.4, z: -0.8}; -var HELMET_ATTACHMENT_URL = "https://hifi-public.s3.amazonaws.com/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") function reticlePosition() { var RETICLE_DISTANCE = 1; @@ -87,6 +88,9 @@ function drawLobby() { // add an attachment on this avatar so other people see them in the lobby MyAvatar.attach(HELMET_ATTACHMENT_URL, "Neck", {x: 0, y: 0, z: 0}, Quat.fromPitchYawRollDegrees(0, 0, 0), 1.15); + + // start the drone sound + Audio.playSound(droneSound, { stereo: true, localOnly: true }); } } diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 3289e64ed4..58c3972bcb 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -1334,10 +1334,13 @@ void Audio::startDrumSound(float volume, float frequency, float duration, float _drumSoundSample = 0; } -QAudioOutput* Audio::newLocalOutputInterface(bool isStereo) { - QAudioFormat localFormat = _outputFormat; +QIODevice* Audio::newLocalOutputDevice(bool isStereo) { + QAudioFormat localFormat = _desiredOutputFormat; localFormat.setChannelCount(isStereo ? 2 : 1); - return new QAudioOutput(getNamedAudioDeviceForMode(QAudio::AudioOutput, _outputAudioDeviceName), localFormat); + QAudioOutput* localOutput = new QAudioOutput(getNamedAudioDeviceForMode(QAudio::AudioOutput, _outputAudioDeviceName), + localFormat); + + return localOutput->start(); } void Audio::renderToolBox(int x, int y, bool boxed) { diff --git a/interface/src/Audio.h b/interface/src/Audio.h index 02ea6db498..83688cf84a 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -155,7 +155,7 @@ public slots: void selectAudioFilterBassCut(); void selectAudioFilterSmiley(); - virtual QAudioOutput* newLocalOutputInterface(bool isStereo); + virtual QIODevice* newLocalOutputDevice(bool isStereo); void sendDownstreamAudioStatsPacket(); diff --git a/libraries/audio/src/AbstractAudioInterface.h b/libraries/audio/src/AbstractAudioInterface.h index 82710277b3..e413bfc8f1 100644 --- a/libraries/audio/src/AbstractAudioInterface.h +++ b/libraries/audio/src/AbstractAudioInterface.h @@ -25,7 +25,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 QAudioOutput* newLocalOutputInterface(bool isStereo) = 0; + virtual QIODevice* newLocalOutputDevice(bool isStereo) = 0; }; Q_DECLARE_METATYPE(AbstractAudioInterface*) diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 239d9eb596..9b2720b90c 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -58,9 +58,37 @@ float AudioInjector::getLoudness() { return _loudness; } +void AudioInjector::injectAudio() { + if (_options.localOnly) { + injectLocally(); + } else { + injectToMixer(); + } +} + +void AudioInjector::injectLocally() { + if (_localAudioInterface) { + + QIODevice* localBuffer = NULL; + + QMetaObject::invokeMethod(_localAudioInterface, "newLocalOutputDevice", Qt::BlockingQueuedConnection, + Q_RETURN_ARG(QIODevice*, localBuffer), + Q_ARG(bool, _options.stereo)); + + if (localBuffer) { + // immediately write the byte array to the local device + localBuffer->write(_sound->getByteArray()); + } else { + qDebug() << "AudioInject::injectLocally did not get a valid QIODevice from _localAudioInterface"; + } + } else { + qDebug() << "AudioInject::injectLocally cannot inject locally with no local audio interface present."; + } +} + const uchar MAX_INJECTOR_VOLUME = 0xFF; -void AudioInjector::injectAudio() { +void AudioInjector::injectToMixer() { QByteArray soundByteArray = _sound->getByteArray(); if (_currentSendPosition < 0 || diff --git a/libraries/audio/src/AudioInjector.h b/libraries/audio/src/AudioInjector.h index 12e4c62d5d..5a0a35d599 100644 --- a/libraries/audio/src/AudioInjector.h +++ b/libraries/audio/src/AudioInjector.h @@ -43,6 +43,9 @@ public slots: signals: void finished(); private: + void injectToMixer(); + void injectLocally(); + Sound* _sound; AudioInjectorOptions _options; bool _shouldStop; diff --git a/libraries/audio/src/AudioInjectorOptions.cpp b/libraries/audio/src/AudioInjectorOptions.cpp index 2a532b92b7..df435cf2cc 100644 --- a/libraries/audio/src/AudioInjectorOptions.cpp +++ b/libraries/audio/src/AudioInjectorOptions.cpp @@ -19,7 +19,8 @@ AudioInjectorOptions::AudioInjectorOptions() : loop(false), orientation(glm::vec3(0.0f, 0.0f, 0.0f)), stereo(false), - ignorePenumbra(false) + ignorePenumbra(false), + localOnly(false) { } @@ -32,6 +33,7 @@ QScriptValue injectorOptionsToScriptValue(QScriptEngine* engine, const AudioInje obj.setProperty("orientation", quatToScriptValue(engine, injectorOptions.orientation)); obj.setProperty("stereo", injectorOptions.stereo); obj.setProperty("ignorePenumbra", injectorOptions.ignorePenumbra); + obj.setProperty("localOnly", injectorOptions.localOnly); return obj; } @@ -59,4 +61,8 @@ void injectorOptionsFromScriptValue(const QScriptValue& object, AudioInjectorOpt if (object.property("ignorePenumbra").isValid()) { injectorOptions.ignorePenumbra = object.property("ignorePenumbra").toBool(); } + + if (object.property("localOnly").isValid()) { + injectorOptions.localOnly = object.property("localOnly").toBool(); + } } \ No newline at end of file diff --git a/libraries/audio/src/AudioInjectorOptions.h b/libraries/audio/src/AudioInjectorOptions.h index c3e2da991a..4fd3a0b7ae 100644 --- a/libraries/audio/src/AudioInjectorOptions.h +++ b/libraries/audio/src/AudioInjectorOptions.h @@ -26,6 +26,7 @@ public: glm::quat orientation; bool stereo; bool ignorePenumbra; + bool localOnly; }; Q_DECLARE_METATYPE(AudioInjectorOptions);