From 91804fbc04a2d586e2f80dad4d80abf116696dfa Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 22 Oct 2015 22:02:09 -0700 Subject: [PATCH 1/2] Fix ordering of standard vs device routes --- .../src/controllers/UserInputMapper.cpp | 43 +++++++++++++------ 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/libraries/controllers/src/controllers/UserInputMapper.cpp b/libraries/controllers/src/controllers/UserInputMapper.cpp index 2ed81aecba..8cd6618bfc 100755 --- a/libraries/controllers/src/controllers/UserInputMapper.cpp +++ b/libraries/controllers/src/controllers/UserInputMapper.cpp @@ -18,6 +18,7 @@ #include #include +#include #include "StandardController.h" #include "Logging.h" @@ -653,7 +654,16 @@ Input UserInputMapper::makeStandardInput(controller::StandardPoseChannel pose) { return Input(STANDARD_DEVICE, pose, ChannelType::POSE); } +static auto lastDebugTime = usecTimestampNow(); +static auto debugRoutes = false; +static const auto DEBUG_INTERVAL = USECS_PER_SECOND; + void UserInputMapper::runMappings() { + auto now = usecTimestampNow(); + if (now - lastDebugTime > DEBUG_INTERVAL) { + lastDebugTime = now; + debugRoutes = true; + } static auto deviceNames = getDeviceNames(); for (auto endpointEntry : this->_endpointsByInput) { endpointEntry.second->reset(); @@ -673,17 +683,17 @@ void UserInputMapper::runMappings() { } applyRoute(route); } + debugRoutes = false; } - void UserInputMapper::applyRoute(const Route::Pointer& route) { - if (route->debug) { + if (debugRoutes && route->debug) { qCDebug(controllers) << "Applying route " << route->json; } if (route->conditional) { if (!route->conditional->satisfied()) { - if (route->debug) { + if (debugRoutes && route->debug) { qCDebug(controllers) << "Conditional failed"; } return; @@ -698,7 +708,7 @@ void UserInputMapper::applyRoute(const Route::Pointer& route) { // I press the button. The exception is if I'm wiring a control back to itself // in order to adjust my interface, like inverting the Y axis on an analog stick if (!source->readable()) { - if (route->debug) { + if (debugRoutes && route->debug) { qCDebug(controllers) << "Source unreadable"; } return; @@ -708,14 +718,14 @@ void UserInputMapper::applyRoute(const Route::Pointer& route) { // THis could happen if the route destination failed to create // FIXME: Maybe do not create the route if the destination failed and avoid this case ? if (!destination) { - if (route->debug) { + if (debugRoutes && route->debug) { qCDebug(controllers) << "Bad Destination"; } return; } if (!destination->writeable()) { - if (route->debug) { + if (debugRoutes && route->debug) { qCDebug(controllers) << "Destination unwritable"; } return; @@ -723,17 +733,24 @@ void UserInputMapper::applyRoute(const Route::Pointer& route) { // Fetch the value, may have been overriden by previous loopback routes if (source->isPose()) { - if (route->debug) { - qCDebug(controllers) << "Applying pose"; - } Pose value = getPose(source); + static const Pose IDENTITY_POSE { vec3(), quat() }; + if (debugRoutes && route->debug) { + if (!value.valid) { + qCDebug(controllers) << "Applying invalid pose"; + } else if (value == IDENTITY_POSE) { + qCDebug(controllers) << "Applying identity pose"; + } else { + qCDebug(controllers) << "Applying valid pose"; + } + } // no filters yet for pose destination->apply(value, Pose(), source); } else { // Fetch the value, may have been overriden by previous loopback routes float value = getValue(source); - if (route->debug) { + if (debugRoutes && route->debug) { qCDebug(controllers) << "Value was " << value; } // Apply each of the filters. @@ -741,7 +758,7 @@ void UserInputMapper::applyRoute(const Route::Pointer& route) { value = filter->apply(value); } - if (route->debug) { + if (debugRoutes && route->debug) { qCDebug(controllers) << "Filtered value was " << value; } @@ -1148,13 +1165,13 @@ void UserInputMapper::enableMapping(const Mapping::Pointer& mapping) { // because standard -> action is the first set of routes added. Route::List standardRoutes = mapping->routes; standardRoutes.remove_if([](const Route::Pointer& value) { - return (value->source->getInput().device == STANDARD_DEVICE); + return (value->source->getInput().device != STANDARD_DEVICE); }); _standardRoutes.insert(_standardRoutes.begin(), standardRoutes.begin(), standardRoutes.end()); Route::List deviceRoutes = mapping->routes; deviceRoutes.remove_if([](const Route::Pointer& value) { - return (value->source->getInput().device != STANDARD_DEVICE); + return (value->source->getInput().device == STANDARD_DEVICE); }); _deviceRoutes.insert(_deviceRoutes.begin(), deviceRoutes.begin(), deviceRoutes.end()); } From 63df9fb959b78bf1a34d5b7bb5f042acfaa5b2de Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 22 Oct 2015 22:37:18 -0700 Subject: [PATCH 2/2] Fixing raw sound playback and air guitar --- examples/controllers/hydra/airGuitar.js | 37 +++++++++++++-------- libraries/audio/src/Sound.cpp | 43 ++++++++++--------------- 2 files changed, 41 insertions(+), 39 deletions(-) diff --git a/examples/controllers/hydra/airGuitar.js b/examples/controllers/hydra/airGuitar.js index b286cc6084..f8606808c1 100644 --- a/examples/controllers/hydra/airGuitar.js +++ b/examples/controllers/hydra/airGuitar.js @@ -90,7 +90,7 @@ var audioInjector = null; var selectorPressed = false; var position; -MyAvatar.attach(guitarModel, "Hips", {x: -0.2, y: 0.0, z: 0.1}, Quat.fromPitchYawRollDegrees(90, 00, 90), 1.0); +MyAvatar.attach(guitarModel, "Hips", {x: leftHanded ? -0.2 : 0.2, y: 0.0, z: 0.1}, Quat.fromPitchYawRollDegrees(90, 00, leftHanded ? 75 : -75), 1.0); function checkHands(deltaTime) { var strumVelocity = Controller.getPoseValue(strumHand).velocity; @@ -114,27 +114,32 @@ function checkHands(deltaTime) { // Change guitars if button FWD (5) pressed if (Controller.getValue(changeGuitar)) { - print("changeGuitar:" + changeGuitar); if (!selectorPressed) { + print("changeGuitar:" + changeGuitar); guitarSelector += NUM_CHORDS; if (guitarSelector >= NUM_CHORDS * NUM_GUITARS) { guitarSelector = 0; } + print("new guitarBase: " + guitarSelector); + stopAudio(true); selectorPressed = true; } } else { selectorPressed = false; } - //print("selectorPressed:" + selectorPressed); if (Controller.getValue(chord1)) { whichChord = 1; + stopAudio(true); } else if (Controller.getValue(chord2)) { whichChord = 2; + stopAudio(true); } else if (Controller.getValue(chord3)) { whichChord = 3; + stopAudio(true); } else if (Controller.getValue(chord4)) { whichChord = 4; + stopAudio(true); } var STRUM_HEIGHT_ABOVE_PELVIS = 0.10; @@ -154,26 +159,27 @@ function checkHands(deltaTime) { lastPosition = strumHandPosition; } -function playChord(position, volume) { +function stopAudio(killInjector) { if (audioInjector && audioInjector.isPlaying) { print("stopped sound"); audioInjector.stop(); } - + if (killInjector) { + audioInjector = null; + } +} + + +function playChord(position, volume) { + stopAudio(); print("Played sound: " + whichChord + " at volume " + volume); if (!audioInjector) { - - // FIXME - we apparenlty broke RAW file playback, so we need WAV files for all these chords. In the mean - // time, we will just play the heyMan wave file for all chords - var chord = heyManWave; // chords[guitarSelector + whichChord]; - + var index = guitarSelector + whichChord; + var chord = chords[guitarSelector + whichChord]; audioInjector = Audio.playSound(chord, { position: position, volume: volume }); - print("audioInjector: " + JSON.stringify(audioInjector)); } else { - print("audioInjector: " + JSON.stringify(audioInjector)); audioInjector.restart(); } - } function keyPressEvent(event) { @@ -181,15 +187,19 @@ function keyPressEvent(event) { keyVolume = 0.4; if (event.text == "1") { whichChord = 1; + stopAudio(true); playChord(MyAvatar.position, keyVolume); } else if (event.text == "2") { whichChord = 2; + stopAudio(true); playChord(MyAvatar.position, keyVolume); } else if (event.text == "3") { whichChord = 3; + stopAudio(true); playChord(MyAvatar.position, keyVolume); } else if (event.text == "4") { whichChord = 4; + stopAudio(true); playChord(MyAvatar.position, keyVolume); } } @@ -197,6 +207,7 @@ function keyPressEvent(event) { function scriptEnding() { MyAvatar.detachOne(guitarModel); } + // Connect a call back that happens every frame Script.update.connect(checkHands); Script.scriptEnding.connect(scriptEnding); diff --git a/libraries/audio/src/Sound.cpp b/libraries/audio/src/Sound.cpp index 2457bda74a..2ce2c47fef 100644 --- a/libraries/audio/src/Sound.cpp +++ b/libraries/audio/src/Sound.cpp @@ -59,39 +59,30 @@ Sound::Sound(const QUrl& url, bool isStereo) : void Sound::downloadFinished(const QByteArray& data) { // replace our byte array with the downloaded data QByteArray rawAudioByteArray = QByteArray(data); - QString fileName = getURL().fileName(); - - const QString WAV_EXTENSION = ".wav"; + QString fileName = getURL().fileName().toLower(); + static const QString WAV_EXTENSION = ".wav"; + static const QString RAW_EXTENSION = ".raw"; if (fileName.endsWith(WAV_EXTENSION)) { - QString headerContentType = "audio/x-wav"; - //QByteArray headerContentType = reply->rawHeader("Content-Type"); + QByteArray outputAudioByteArray; - // WAV audio file encountered - if (headerContentType == "audio/x-wav" - || headerContentType == "audio/wav" - || headerContentType == "audio/wave" - || fileName.endsWith(WAV_EXTENSION)) { - - QByteArray outputAudioByteArray; - - interpretAsWav(rawAudioByteArray, outputAudioByteArray); - downSample(outputAudioByteArray); - } else { - // check if this was a stereo raw file - // since it's raw the only way for us to know that is if the file was called .stereo.raw - if (fileName.toLower().endsWith("stereo.raw")) { - _isStereo = true; - qCDebug(audio) << "Processing sound of" << rawAudioByteArray.size() << "bytes from" << getURL() << "as stereo audio file."; - } - - // Process as RAW file - downSample(rawAudioByteArray); + interpretAsWav(rawAudioByteArray, outputAudioByteArray); + downSample(outputAudioByteArray); + trimFrames(); + } else if (fileName.endsWith(RAW_EXTENSION)) { + // check if this was a stereo raw file + // since it's raw the only way for us to know that is if the file was called .stereo.raw + if (fileName.toLower().endsWith("stereo.raw")) { + _isStereo = true; + qCDebug(audio) << "Processing sound of" << rawAudioByteArray.size() << "bytes from" << getURL() << "as stereo audio file."; } + + // Process as RAW file + downSample(rawAudioByteArray); trimFrames(); } else { - qCDebug(audio) << "Network reply without 'Content-Type'."; + qCDebug(audio) << "Unknown sound file type"; } _isReady = true;