From 4dc929eddbaa68c6cdebdeeab715d80aa4f78a06 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Mon, 15 Sep 2014 19:50:38 -0700 Subject: [PATCH 1/5] Simpler script with sphere to indicate emission point --- examples/playSoundLoop.js | 51 +++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/examples/playSoundLoop.js b/examples/playSoundLoop.js index 86226468bc..2c684a73a1 100644 --- a/examples/playSoundLoop.js +++ b/examples/playSoundLoop.js @@ -5,39 +5,54 @@ // Created by David Rowe on 5/29/14. // Copyright 2014 High Fidelity, Inc. // -// This example script plays a sound in a continuous loop. +// This example script plays a sound in a continuous loop, and creates a red sphere in front of you at the origin of the sound. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -var sound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Guitars/Guitar+-+Nylon+A.raw"); + +// A few sample files you may want to try: + +//var sound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Guitars/Guitar+-+Nylon+A.raw"); +//var sound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/220Sine.wav"); +var sound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Bandcamp.wav"); var soundPlaying = false; +var options = new AudioInjectionOptions(); +options.position = Vec3.sum(Camera.getPosition(), Quat.getFront(MyAvatar.orientation)); +options.volume = 0.5; +options.loop = true; +var playing = false; +var ball = false; -function keyPressEvent(event) { - if (event.text === "1") { - if (!Audio.isInjectorPlaying(soundPlaying)) { - var options = new AudioInjectionOptions(); - options.position = MyAvatar.position; - options.volume = 0.5; - options.loop = true; - soundPlaying = Audio.playSound(sound, options); - print("Started sound loop"); - } else { - Audio.stopInjector(soundPlaying); - print("Stopped sound loop"); - } +function maybePlaySound(deltaTime) { + if (sound.downloaded) { + var properties = { + type: "Sphere", + position: options.position, + velocity: { x: 0, y: 0, z: 0}, + gravity: { x: 0, y: 0, z: 0}, + radius: 0.10, + damping: 0.999, + color: { red: 200, green: 0, blue: 0 } + }; + ball = Entities.addEntity(properties); + soundPlaying = Audio.playSound(sound, options); + print("Started sound looping."); + Script.update.disconnect(maybePlaySound); } } - + function scriptEnding() { if (Audio.isInjectorPlaying(soundPlaying)) { Audio.stopInjector(soundPlaying); - print("Stopped sound loop"); + Entities.deleteEntity(ball); + print("Stopped sound."); } } // Connect a call back that happens every frame Script.scriptEnding.connect(scriptEnding); -Controller.keyPressEvent.connect(keyPressEvent); +Script.update.connect(maybePlaySound); + From af638a9963a2da6a48c2f5c436db36f3065edf3d Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Mon, 15 Sep 2014 20:55:25 -0700 Subject: [PATCH 2/5] Use dimensions, not radius --- examples/playSoundLoop.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/playSoundLoop.js b/examples/playSoundLoop.js index 2c684a73a1..9139494bbf 100644 --- a/examples/playSoundLoop.js +++ b/examples/playSoundLoop.js @@ -33,7 +33,7 @@ function maybePlaySound(deltaTime) { position: options.position, velocity: { x: 0, y: 0, z: 0}, gravity: { x: 0, y: 0, z: 0}, - radius: 0.10, + dimensions: { x: 0.2, y: 0.2, z: 0.2 }, damping: 0.999, color: { red: 200, green: 0, blue: 0 } }; From 62b21f52af68266d14f744742930c2cbc623b17b Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 16 Sep 2014 01:18:42 -0700 Subject: [PATCH 3/5] fix for sharp change in attenuation when too near a source --- assignment-client/src/audio/AudioMixer.cpp | 243 ++++++++++----------- examples/playSoundLoop.js | 9 +- 2 files changed, 119 insertions(+), 133 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 714cd0e3f3..ca3a241f6c 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -102,7 +102,7 @@ AudioMixer::~AudioMixer() { const float ATTENUATION_BEGINS_AT_DISTANCE = 1.0f; const float ATTENUATION_AMOUNT_PER_DOUBLING_IN_DISTANCE = 0.18f; -const float ATTENUATION_EPSILON_DISTANCE = 0.1f; +const float RADIUS_OF_HEAD = 0.076f; int AudioMixer::addStreamToMixForListeningNodeWithStream(PositionalAudioStream* streamToAdd, AvatarAudioStream* listeningNodeStream) { @@ -112,6 +112,8 @@ int AudioMixer::addStreamToMixForListeningNodeWithStream(PositionalAudioStream* // Basically, we'll repeat that last frame until it has a frame to mix. Depending on how many times // we've repeated that frame in a row, we'll gradually fade that repeated frame into silence. // This improves the perceived quality of the audio slightly. + + bool showDebug = false; // (randFloat() < 0.05f); float repeatedFrameFadeFactor = 1.0f; @@ -140,112 +142,109 @@ int AudioMixer::addStreamToMixForListeningNodeWithStream(PositionalAudioStream* int numSamplesDelay = 0; float weakChannelAmplitudeRatio = 1.0f; - bool shouldAttenuate = (streamToAdd != listeningNodeStream); + bool shouldDistanceAttenuate = true; - if (shouldAttenuate) { + // if the two stream pointers do not match then these are different streams + glm::vec3 relativePosition = streamToAdd->getPosition() - listeningNodeStream->getPosition(); + + float distanceBetween = glm::length(relativePosition); + + if (distanceBetween < EPSILON) { + distanceBetween = EPSILON; + } + + if (streamToAdd->getLastPopOutputTrailingLoudness() / distanceBetween <= _minAudibilityThreshold) { + // according to mixer performance we have decided this does not get to be mixed in + // bail out + return 0; + } + + ++_sumMixes; + + if (streamToAdd->getListenerUnattenuatedZone()) { + shouldDistanceAttenuate = !streamToAdd->getListenerUnattenuatedZone()->contains(listeningNodeStream->getPosition()); + } + + if (streamToAdd->getType() == PositionalAudioStream::Injector) { + attenuationCoefficient *= reinterpret_cast(streamToAdd)->getAttenuationRatio(); + if (showDebug) qDebug() << "AttenuationRatio: " << reinterpret_cast(streamToAdd)->getAttenuationRatio(); + } + + if (showDebug) { + qDebug() << "distance: " << distanceBetween; + } + + glm::quat inverseOrientation = glm::inverse(listeningNodeStream->getOrientation()); + + if (streamToAdd->getType() != PositionalAudioStream::Injector) { + // source is another avatar, apply fixed off-axis attenuation to make them quieter as they turn away from listener + glm::vec3 rotatedListenerPosition = glm::inverse(streamToAdd->getOrientation()) * relativePosition; - // if the two stream pointers do not match then these are different streams - glm::vec3 relativePosition = streamToAdd->getPosition() - listeningNodeStream->getPosition(); + float angleOfDelivery = glm::angle(glm::vec3(0.0f, 0.0f, -1.0f), + glm::normalize(rotatedListenerPosition)); - float distanceBetween = glm::length(relativePosition); + const float MAX_OFF_AXIS_ATTENUATION = 0.2f; + const float OFF_AXIS_ATTENUATION_FORMULA_STEP = (1 - MAX_OFF_AXIS_ATTENUATION) / 2.0f; - if (distanceBetween < EPSILON) { - distanceBetween = EPSILON; - } + float offAxisCoefficient = MAX_OFF_AXIS_ATTENUATION + + (OFF_AXIS_ATTENUATION_FORMULA_STEP * (angleOfDelivery / PI_OVER_TWO)); - if (streamToAdd->getLastPopOutputTrailingLoudness() / distanceBetween <= _minAudibilityThreshold) { - // according to mixer performance we have decided this does not get to be mixed in - // bail out - return 0; - } - - ++_sumMixes; - - if (streamToAdd->getListenerUnattenuatedZone()) { - shouldAttenuate = !streamToAdd->getListenerUnattenuatedZone()->contains(listeningNodeStream->getPosition()); - } - - if (streamToAdd->getType() == PositionalAudioStream::Injector) { - attenuationCoefficient *= reinterpret_cast(streamToAdd)->getAttenuationRatio(); - } - - shouldAttenuate = shouldAttenuate && distanceBetween > ATTENUATION_EPSILON_DISTANCE; - - if (shouldAttenuate) { - glm::quat inverseOrientation = glm::inverse(listeningNodeStream->getOrientation()); + if (showDebug) { + qDebug() << "angleOfDelivery" << angleOfDelivery << "offAxisCoefficient: " << offAxisCoefficient; - float distanceSquareToSource = glm::dot(relativePosition, relativePosition); - float radius = 0.0f; - - if (streamToAdd->getType() == PositionalAudioStream::Injector) { - radius = reinterpret_cast(streamToAdd)->getRadius(); - } - - if (radius == 0 || (distanceSquareToSource > radius * radius)) { - // this is either not a spherical source, or the listener is outside the sphere - - if (radius > 0) { - // this is a spherical source - the distance used for the coefficient - // needs to be the closest point on the boundary to the source - - // ovveride the distance to the node with the distance to the point on the - // boundary of the sphere - distanceSquareToSource -= (radius * radius); - - } else { - // calculate the angle delivery for off-axis attenuation - glm::vec3 rotatedListenerPosition = glm::inverse(streamToAdd->getOrientation()) * relativePosition; - - float angleOfDelivery = glm::angle(glm::vec3(0.0f, 0.0f, -1.0f), - glm::normalize(rotatedListenerPosition)); - - const float MAX_OFF_AXIS_ATTENUATION = 0.2f; - const float OFF_AXIS_ATTENUATION_FORMULA_STEP = (1 - MAX_OFF_AXIS_ATTENUATION) / 2.0f; - - float offAxisCoefficient = MAX_OFF_AXIS_ATTENUATION + - (OFF_AXIS_ATTENUATION_FORMULA_STEP * (angleOfDelivery / PI_OVER_TWO)); - - // multiply the current attenuation coefficient by the calculated off axis coefficient - attenuationCoefficient *= offAxisCoefficient; - } - - glm::vec3 rotatedSourcePosition = inverseOrientation * relativePosition; - - if (distanceBetween >= ATTENUATION_BEGINS_AT_DISTANCE) { - // calculate the distance coefficient using the distance to this node - float distanceCoefficient = 1 - (logf(distanceBetween / ATTENUATION_BEGINS_AT_DISTANCE) / logf(2.0f) - * ATTENUATION_AMOUNT_PER_DOUBLING_IN_DISTANCE); - - if (distanceCoefficient < 0) { - distanceCoefficient = 0; - } - - // multiply the current attenuation coefficient by the distance coefficient - attenuationCoefficient *= distanceCoefficient; - } - - // project the rotated source position vector onto the XZ plane - rotatedSourcePosition.y = 0.0f; - - // produce an oriented angle about the y-axis - bearingRelativeAngleToSource = glm::orientedAngle(glm::vec3(0.0f, 0.0f, -1.0f), - glm::normalize(rotatedSourcePosition), - glm::vec3(0.0f, 1.0f, 0.0f)); - - const float PHASE_AMPLITUDE_RATIO_AT_90 = 0.5; - - // figure out the number of samples of delay and the ratio of the amplitude - // in the weak channel for audio spatialization - float sinRatio = fabsf(sinf(bearingRelativeAngleToSource)); - numSamplesDelay = SAMPLE_PHASE_DELAY_AT_90 * sinRatio; - weakChannelAmplitudeRatio = 1 - (PHASE_AMPLITUDE_RATIO_AT_90 * sinRatio); - } } + // multiply the current attenuation coefficient by the calculated off axis coefficient + + attenuationCoefficient *= offAxisCoefficient; + } + + if (shouldDistanceAttenuate && (distanceBetween >= ATTENUATION_BEGINS_AT_DISTANCE)) { + // calculate the distance coefficient using the distance to this node + float distanceCoefficient = 1 - (logf(distanceBetween / ATTENUATION_BEGINS_AT_DISTANCE) / logf(2.0f) + * ATTENUATION_AMOUNT_PER_DOUBLING_IN_DISTANCE); + + if (distanceCoefficient < 0) { + distanceCoefficient = 0; + } + + // multiply the current attenuation coefficient by the distance coefficient + attenuationCoefficient *= distanceCoefficient; + if (showDebug) qDebug() << "distanceCoefficient: " << distanceCoefficient; + } + + // Compute sample delay for the two ears to create phase panning + glm::vec3 rotatedSourcePosition = inverseOrientation * relativePosition; + + // project the rotated source position vector onto the XZ plane + rotatedSourcePosition.y = 0.0f; + + // produce an oriented angle about the y-axis + bearingRelativeAngleToSource = glm::orientedAngle(glm::vec3(0.0f, 0.0f, -1.0f), + glm::normalize(rotatedSourcePosition), + glm::vec3(0.0f, 1.0f, 0.0f)); + + const float PHASE_AMPLITUDE_RATIO_AT_90 = 0.5; + + // figure out the number of samples of delay and the ratio of the amplitude + // in the weak channel for audio spatialization + float sinRatio = fabsf(sinf(bearingRelativeAngleToSource)); + numSamplesDelay = SAMPLE_PHASE_DELAY_AT_90 * sinRatio; + weakChannelAmplitudeRatio = 1 - (PHASE_AMPLITUDE_RATIO_AT_90 * sinRatio); + + if (distanceBetween < RADIUS_OF_HEAD) { + // Diminish phase panning if source would be inside head + numSamplesDelay *= distanceBetween / RADIUS_OF_HEAD; + weakChannelAmplitudeRatio += (PHASE_AMPLITUDE_RATIO_AT_90 * sinRatio) * distanceBetween / RADIUS_OF_HEAD; + } + + if (showDebug) { + qDebug() << "attenuation: " << attenuationCoefficient; + qDebug() << "bearingRelativeAngleToSource: " << bearingRelativeAngleToSource << " numSamplesDelay: " << numSamplesDelay; } AudioRingBuffer::ConstIterator streamPopOutput = streamToAdd->getLastPopOutput(); - if (!streamToAdd->isStereo() && shouldAttenuate) { + if (!streamToAdd->isStereo()) { // this is a mono stream, which means it gets full attenuation and spatialization // if the bearing relative angle to source is > 0 then the delayed channel is the right one @@ -293,11 +292,7 @@ int AudioMixer::addStreamToMixForListeningNodeWithStream(PositionalAudioStream* } else { int stereoDivider = streamToAdd->isStereo() ? 1 : 2; - if (!shouldAttenuate) { - attenuationCoefficient = 1.0f; - } - - float attenuationAndFade = attenuationCoefficient * repeatedFrameFadeFactor; + float attenuationAndFade = attenuationCoefficient * repeatedFrameFadeFactor; for (int s = 0; s < NETWORK_BUFFER_LENGTH_SAMPLES_STEREO; s++) { _clientSamples[s] = glm::clamp(_clientSamples[s] + (int)(streamPopOutput[s / stereoDivider] * attenuationAndFade), @@ -305,19 +300,8 @@ int AudioMixer::addStreamToMixForListeningNodeWithStream(PositionalAudioStream* } } - if (_enableFilter && shouldAttenuate) { + if (_enableFilter) { - glm::vec3 relativePosition = streamToAdd->getPosition() - listeningNodeStream->getPosition(); - glm::quat inverseOrientation = glm::inverse(listeningNodeStream->getOrientation()); - glm::vec3 rotatedSourcePosition = inverseOrientation * relativePosition; - - // project the rotated source position vector onto the XZ plane - rotatedSourcePosition.y = 0.0f; - - // produce an oriented angle about the y-axis - float bearingAngleToSource = glm::orientedAngle(glm::vec3(0.0f, 0.0f, -1.0f), - glm::normalize(rotatedSourcePosition), - glm::vec3(0.0f, -1.0f, 0.0f)); const float TWO_OVER_PI = 2.0f / PI; const float ZERO_DB = 1.0f; @@ -337,36 +321,41 @@ int AudioMixer::addStreamToMixForListeningNodeWithStream(PositionalAudioStream* float penumbraFilterGainL; float penumbraFilterGainR; - // variable gain calculation broken down by quadrent - if (bearingAngleToSource < -PI_OVER_TWO && bearingAngleToSource > -PI) { + // variable gain calculation broken down by quadrant + if (-bearingRelativeAngleToSource < -PI_OVER_TWO && -bearingRelativeAngleToSource > -PI) { penumbraFilterGainL = TWO_OVER_PI * - (FILTER_GAIN_AT_0 - FILTER_GAIN_AT_180) * (bearingAngleToSource + PI_OVER_TWO) + FILTER_GAIN_AT_0; + (FILTER_GAIN_AT_0 - FILTER_GAIN_AT_180) * (-bearingRelativeAngleToSource + PI_OVER_TWO) + FILTER_GAIN_AT_0; penumbraFilterGainR = TWO_OVER_PI * - (FILTER_GAIN_AT_90 - FILTER_GAIN_AT_180) * (bearingAngleToSource + PI_OVER_TWO) + FILTER_GAIN_AT_90; - } else if (bearingAngleToSource <= PI && bearingAngleToSource > PI_OVER_TWO) { + (FILTER_GAIN_AT_90 - FILTER_GAIN_AT_180) * (-bearingRelativeAngleToSource + PI_OVER_TWO) + FILTER_GAIN_AT_90; + } else if (-bearingRelativeAngleToSource <= PI && -bearingRelativeAngleToSource > PI_OVER_TWO) { penumbraFilterGainL = TWO_OVER_PI * - (FILTER_GAIN_AT_180 - FILTER_GAIN_AT_90) * (bearingAngleToSource - PI) + FILTER_GAIN_AT_180; + (FILTER_GAIN_AT_180 - FILTER_GAIN_AT_90) * (-bearingRelativeAngleToSource - PI) + FILTER_GAIN_AT_180; penumbraFilterGainR = TWO_OVER_PI * - (FILTER_GAIN_AT_180 - FILTER_GAIN_AT_0) * (bearingAngleToSource - PI) + FILTER_GAIN_AT_180; - } else if (bearingAngleToSource <= PI_OVER_TWO && bearingAngleToSource > 0) { + (FILTER_GAIN_AT_180 - FILTER_GAIN_AT_0) * (-bearingRelativeAngleToSource - PI) + FILTER_GAIN_AT_180; + } else if (-bearingRelativeAngleToSource <= PI_OVER_TWO && -bearingRelativeAngleToSource > 0) { penumbraFilterGainL = TWO_OVER_PI * - (FILTER_GAIN_AT_90 - FILTER_GAIN_AT_0) * (bearingAngleToSource - PI_OVER_TWO) + FILTER_GAIN_AT_90; + (FILTER_GAIN_AT_90 - FILTER_GAIN_AT_0) * (-bearingRelativeAngleToSource - PI_OVER_TWO) + FILTER_GAIN_AT_90; penumbraFilterGainR = FILTER_GAIN_AT_0; } else { penumbraFilterGainL = FILTER_GAIN_AT_0; penumbraFilterGainR = TWO_OVER_PI * - (FILTER_GAIN_AT_0 - FILTER_GAIN_AT_90) * (bearingAngleToSource) + FILTER_GAIN_AT_0; + (FILTER_GAIN_AT_0 - FILTER_GAIN_AT_90) * (-bearingRelativeAngleToSource) + FILTER_GAIN_AT_0; + } + + if (distanceBetween < RADIUS_OF_HEAD) { + // Diminish effect if source would be inside head + penumbraFilterGainL += (1.f - penumbraFilterGainL) * (1.f - distanceBetween / RADIUS_OF_HEAD); + penumbraFilterGainR += (1.f - penumbraFilterGainR) * (1.f - distanceBetween / RADIUS_OF_HEAD); } + #if 0 - qDebug() << "avatar=" - << listeningNodeStream - << "gainL=" + qDebug() << "gainL=" << penumbraFilterGainL << "gainR=" << penumbraFilterGainR << "angle=" - << bearingAngleToSource; + << -bearingRelativeAngleToSource; #endif // set the gain on both filter channels diff --git a/examples/playSoundLoop.js b/examples/playSoundLoop.js index 9139494bbf..30f8762248 100644 --- a/examples/playSoundLoop.js +++ b/examples/playSoundLoop.js @@ -14,9 +14,9 @@ // A few sample files you may want to try: -//var sound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Guitars/Guitar+-+Nylon+A.raw"); +var sound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Guitars/Guitar+-+Nylon+A.raw"); //var sound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/220Sine.wav"); -var sound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Bandcamp.wav"); +//var sound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Bandcamp.wav"); var soundPlaying = false; var options = new AudioInjectionOptions(); @@ -31,10 +31,7 @@ function maybePlaySound(deltaTime) { var properties = { type: "Sphere", position: options.position, - velocity: { x: 0, y: 0, z: 0}, - gravity: { x: 0, y: 0, z: 0}, - dimensions: { x: 0.2, y: 0.2, z: 0.2 }, - damping: 0.999, + dimensions: { x: 0.2, y: 0.2, z: 0.2 }, color: { red: 200, green: 0, blue: 0 } }; ball = Entities.addEntity(properties); From 1514b58700dccdb4d0fd9ba83003e0516eeb7632 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 16 Sep 2014 01:30:25 -0700 Subject: [PATCH 4/5] add detect if source is self --- assignment-client/src/audio/AudioMixer.cpp | 52 ++++++++++++---------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index ca3a241f6c..bc4cb7e245 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -144,6 +144,8 @@ int AudioMixer::addStreamToMixForListeningNodeWithStream(PositionalAudioStream* bool shouldDistanceAttenuate = true; + bool sourceIsSelf = (streamToAdd == listeningNodeStream); + // if the two stream pointers do not match then these are different streams glm::vec3 relativePosition = streamToAdd->getPosition() - listeningNodeStream->getPosition(); @@ -176,7 +178,7 @@ int AudioMixer::addStreamToMixForListeningNodeWithStream(PositionalAudioStream* glm::quat inverseOrientation = glm::inverse(listeningNodeStream->getOrientation()); - if (streamToAdd->getType() != PositionalAudioStream::Injector) { + if (!sourceIsSelf && (streamToAdd->getType() != PositionalAudioStream::Injector)) { // source is another avatar, apply fixed off-axis attenuation to make them quieter as they turn away from listener glm::vec3 rotatedListenerPosition = glm::inverse(streamToAdd->getOrientation()) * relativePosition; @@ -212,29 +214,31 @@ int AudioMixer::addStreamToMixForListeningNodeWithStream(PositionalAudioStream* if (showDebug) qDebug() << "distanceCoefficient: " << distanceCoefficient; } - // Compute sample delay for the two ears to create phase panning - glm::vec3 rotatedSourcePosition = inverseOrientation * relativePosition; + if (!sourceIsSelf) { + // Compute sample delay for the two ears to create phase panning + glm::vec3 rotatedSourcePosition = inverseOrientation * relativePosition; - // project the rotated source position vector onto the XZ plane - rotatedSourcePosition.y = 0.0f; - - // produce an oriented angle about the y-axis - bearingRelativeAngleToSource = glm::orientedAngle(glm::vec3(0.0f, 0.0f, -1.0f), - glm::normalize(rotatedSourcePosition), - glm::vec3(0.0f, 1.0f, 0.0f)); - - const float PHASE_AMPLITUDE_RATIO_AT_90 = 0.5; - - // figure out the number of samples of delay and the ratio of the amplitude - // in the weak channel for audio spatialization - float sinRatio = fabsf(sinf(bearingRelativeAngleToSource)); - numSamplesDelay = SAMPLE_PHASE_DELAY_AT_90 * sinRatio; - weakChannelAmplitudeRatio = 1 - (PHASE_AMPLITUDE_RATIO_AT_90 * sinRatio); - - if (distanceBetween < RADIUS_OF_HEAD) { - // Diminish phase panning if source would be inside head - numSamplesDelay *= distanceBetween / RADIUS_OF_HEAD; - weakChannelAmplitudeRatio += (PHASE_AMPLITUDE_RATIO_AT_90 * sinRatio) * distanceBetween / RADIUS_OF_HEAD; + // project the rotated source position vector onto the XZ plane + rotatedSourcePosition.y = 0.0f; + + // produce an oriented angle about the y-axis + bearingRelativeAngleToSource = glm::orientedAngle(glm::vec3(0.0f, 0.0f, -1.0f), + glm::normalize(rotatedSourcePosition), + glm::vec3(0.0f, 1.0f, 0.0f)); + + const float PHASE_AMPLITUDE_RATIO_AT_90 = 0.5; + + // figure out the number of samples of delay and the ratio of the amplitude + // in the weak channel for audio spatialization + float sinRatio = fabsf(sinf(bearingRelativeAngleToSource)); + numSamplesDelay = SAMPLE_PHASE_DELAY_AT_90 * sinRatio; + weakChannelAmplitudeRatio = 1 - (PHASE_AMPLITUDE_RATIO_AT_90 * sinRatio); + + if (distanceBetween < RADIUS_OF_HEAD) { + // Diminish phase panning if source would be inside head + numSamplesDelay *= distanceBetween / RADIUS_OF_HEAD; + weakChannelAmplitudeRatio += (PHASE_AMPLITUDE_RATIO_AT_90 * sinRatio) * distanceBetween / RADIUS_OF_HEAD; + } } if (showDebug) { @@ -300,7 +304,7 @@ int AudioMixer::addStreamToMixForListeningNodeWithStream(PositionalAudioStream* } } - if (_enableFilter) { + if (!sourceIsSelf && _enableFilter) { const float TWO_OVER_PI = 2.0f / PI; From 35b772bc4da7dc997fb6544f929c54c90a1e20ef Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 16 Sep 2014 09:24:23 -0700 Subject: [PATCH 5/5] fixes from review --- assignment-client/src/audio/AudioMixer.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index bc4cb7e245..0443331dc2 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -144,9 +144,9 @@ int AudioMixer::addStreamToMixForListeningNodeWithStream(PositionalAudioStream* bool shouldDistanceAttenuate = true; + // Is the source that I am mixing my own? bool sourceIsSelf = (streamToAdd == listeningNodeStream); - // if the two stream pointers do not match then these are different streams glm::vec3 relativePosition = streamToAdd->getPosition() - listeningNodeStream->getPosition(); float distanceBetween = glm::length(relativePosition); @@ -169,7 +169,9 @@ int AudioMixer::addStreamToMixForListeningNodeWithStream(PositionalAudioStream* if (streamToAdd->getType() == PositionalAudioStream::Injector) { attenuationCoefficient *= reinterpret_cast(streamToAdd)->getAttenuationRatio(); - if (showDebug) qDebug() << "AttenuationRatio: " << reinterpret_cast(streamToAdd)->getAttenuationRatio(); + if (showDebug) { + qDebug() << "AttenuationRatio: " << reinterpret_cast(streamToAdd)->getAttenuationRatio(); + } } if (showDebug) { @@ -178,7 +180,7 @@ int AudioMixer::addStreamToMixForListeningNodeWithStream(PositionalAudioStream* glm::quat inverseOrientation = glm::inverse(listeningNodeStream->getOrientation()); - if (!sourceIsSelf && (streamToAdd->getType() != PositionalAudioStream::Injector)) { + if (!sourceIsSelf && (streamToAdd->getType() == PositionalAudioStream::Microphone)) { // source is another avatar, apply fixed off-axis attenuation to make them quieter as they turn away from listener glm::vec3 rotatedListenerPosition = glm::inverse(streamToAdd->getOrientation()) * relativePosition; @@ -189,7 +191,7 @@ int AudioMixer::addStreamToMixForListeningNodeWithStream(PositionalAudioStream* const float OFF_AXIS_ATTENUATION_FORMULA_STEP = (1 - MAX_OFF_AXIS_ATTENUATION) / 2.0f; float offAxisCoefficient = MAX_OFF_AXIS_ATTENUATION + - (OFF_AXIS_ATTENUATION_FORMULA_STEP * (angleOfDelivery / PI_OVER_TWO)); + (OFF_AXIS_ATTENUATION_FORMULA_STEP * (angleOfDelivery / PI_OVER_TWO)); if (showDebug) { qDebug() << "angleOfDelivery" << angleOfDelivery << "offAxisCoefficient: " << offAxisCoefficient; @@ -211,7 +213,9 @@ int AudioMixer::addStreamToMixForListeningNodeWithStream(PositionalAudioStream* // multiply the current attenuation coefficient by the distance coefficient attenuationCoefficient *= distanceCoefficient; - if (showDebug) qDebug() << "distanceCoefficient: " << distanceCoefficient; + if (showDebug) { + qDebug() << "distanceCoefficient: " << distanceCoefficient; + } } if (!sourceIsSelf) {