Skip to content

Commit

Permalink
add option to trigger in proportion sound when jumping over in propor…
Browse files Browse the repository at this point in the history
…tion, #162
  • Loading branch information
zepumph committed Sep 2, 2020
1 parent eb3cc99 commit 865b233
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 23 deletions.
40 changes: 21 additions & 19 deletions js/common/view/RatioAndProportionScreenView.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,16 @@ class RatioAndProportionScreenView extends ScreenView {
// @protected
this.tickMarkViewProperty = tickMarkViewProperty;

// @private - SoundGenerators that sonify different aspects of the model
this.inProportionSoundGenerator = new InProportionSoundGenerator( model );
this.movingInProportionSoundGenerator = new MovingInProportionSoundGenerator( model );
this.staccatoFrequencySoundGenerator = new StaccatoFrequencySoundGenerator( model.ratioFitnessProperty, model.fitnessRange,
model.inProportion.bind( model ) );

soundManager.addSoundGenerator( this.staccatoFrequencySoundGenerator );
soundManager.addSoundGenerator( this.inProportionSoundGenerator );
soundManager.addSoundGenerator( this.movingInProportionSoundGenerator );

// by default, the keyboard step size should be half of one default tick mark width. See https://github.com/phetsims/ratio-and-proportion/issues/85
const keyboardStep = 1 / 2 / options.tickMarkRangeProperty.value;

Expand All @@ -114,7 +124,7 @@ class RatioAndProportionScreenView extends ScreenView {
tickMarksAndLabelsColorProperty,
keyboardStep,
model.lockRatioProperty,
playUISoundsProperty, {
playUISoundsProperty, this.inProportionSoundGenerator, {
accessibleName: ratioAndProportionStrings.a11y.leftHand,
a11yDependencies: a11yDependencies,
isRight: false // this way we get a left hand
Expand All @@ -135,7 +145,7 @@ class RatioAndProportionScreenView extends ScreenView {
tickMarksAndLabelsColorProperty,
keyboardStep,
model.lockRatioProperty,
playUISoundsProperty, {
playUISoundsProperty, this.inProportionSoundGenerator, {
accessibleName: ratioAndProportionStrings.a11y.rightHand,
a11yDependencies: a11yDependencies,
helpText: ratioAndProportionStrings.a11y.rightHandHelpText
Expand Down Expand Up @@ -188,24 +198,16 @@ class RatioAndProportionScreenView extends ScreenView {
// @private TODO: add support for mechamarker input again https://github.com/phetsims/ratio-and-proportion/issues/89
// this.markerInput = new ProportionMarkerInput( model );

const soundGeneratorOptions = {
enableControlProperties: [ DerivedProperty.or( [
this.leftRatioHalf.isBeingInteractedWithProperty,
this.rightRatioHalf.isBeingInteractedWithProperty,
// this.markerInput.isBeingInteractedWithProperty, // TODO: add support for mechamarker input again https://github.com/phetsims/ratio-and-proportion/issues/89
ratioInteractionListener.isBeingInteractedWithProperty
] ) ]
};

// @private - SoundGenerators that sonify different aspects of the model
this.inProportionSoundGenerator = new InProportionSoundGenerator( model, soundGeneratorOptions );
this.movingInProportionSoundGenerator = new MovingInProportionSoundGenerator( model, soundGeneratorOptions );
this.staccatoFrequencySoundGenerator = new StaccatoFrequencySoundGenerator( model.ratioFitnessProperty, model.fitnessRange,
model.inProportion.bind( model ), soundGeneratorOptions );
const soundGeneratorEnabledProperty = DerivedProperty.or( [
this.leftRatioHalf.isBeingInteractedWithProperty,
this.rightRatioHalf.isBeingInteractedWithProperty,
// this.markerInput.isBeingInteractedWithProperty, // TODO: add support for mechamarker input again https://github.com/phetsims/ratio-and-proportion/issues/89
ratioInteractionListener.isBeingInteractedWithProperty
] );

soundManager.addSoundGenerator( this.staccatoFrequencySoundGenerator );
soundManager.addSoundGenerator( this.inProportionSoundGenerator );
soundManager.addSoundGenerator( this.movingInProportionSoundGenerator );
this.inProportionSoundGenerator.addEnableControlProperty( soundGeneratorEnabledProperty );
this.movingInProportionSoundGenerator.addEnableControlProperty( soundGeneratorEnabledProperty );
this.staccatoFrequencySoundGenerator.addEnableControlProperty( soundGeneratorEnabledProperty );

// these dimensions are just temporary, and will be recomputed below in the layout function
const labelsNode = new RAPTickMarkLabelsNode( tickMarkViewProperty, options.tickMarkRangeProperty, 1000, tickMarksAndLabelsColorProperty );
Expand Down
8 changes: 7 additions & 1 deletion js/common/view/RatioHalf.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,13 @@ class RatioHalf extends Rectangle {
* @param {number} keyboardStep
* @param {BooleanProperty} horizontalMovementAllowedProperty
* @param {BooleanProperty} playUISoundsProperty
* @param {InProportionSoundGenerator} inProportionSoundGenerator
* @param {Object} [options]
*/
constructor( valueProperty, valueRange, enabledValueRangeProperty, firstInteractionProperty, bounds, tickMarkViewProperty,
tickMarkRangeProperty, ratioDescriber, handPositionsDescriber, colorProperty, keyboardStep, horizontalMovementAllowedProperty, playUISoundsProperty, options ) {
tickMarkRangeProperty, ratioDescriber, handPositionsDescriber, colorProperty, keyboardStep,
horizontalMovementAllowedProperty, playUISoundsProperty, inProportionSoundGenerator,
options ) {

options = merge( {
isRight: true, // right ratio or the left ratio
Expand Down Expand Up @@ -211,6 +214,8 @@ class RatioHalf extends Rectangle {
}
commonGrabSoundClip.play();
firstInteractionProperty.value = false;

inProportionSoundGenerator.setJumpingOverProportionShouldTriggerSound( true );
},
drag: () => {
this.isBeingInteractedWithProperty.value = true;
Expand Down Expand Up @@ -252,6 +257,7 @@ class RatioHalf extends Rectangle {
commonReleaseSoundClip.play();
this.isBeingInteractedWithProperty.value = false;
this.alertManager.alertRatioChange();
inProportionSoundGenerator.setJumpingOverProportionShouldTriggerSound( false );
}
} );

Expand Down
31 changes: 28 additions & 3 deletions js/common/view/sound/InProportionSoundGenerator.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ class InProportionSoundGenerator extends SoundClip {
// @private - True when, in the previous step, the current ratio (calculated from leftValue/rightValue) is larger than
// the target ratio.
this.currentRatioWasLargerThanTarget = this.calculateCurrentRatioLargerThanTarget();

// @private - in certain cases ratio hand positions can move so quickly "through" the in-proportion range that an
// actual "in proportion" value is never set. When this boolean is true, then this SoundGenerator will note when
// this "jump over in proportion" occurs, and still play the sound. This is useful for mouse interaction, but not
// so much for keyboard interaction. See https://github.com/phetsims/ratio-and-proportion/issues/162
this.jumpingOverShouldSound = false;
}

/**
Expand All @@ -51,6 +57,25 @@ class InProportionSoundGenerator extends SoundClip {
return this.currentRatioProperty.value > this.model.targetRatioProperty.value;
}

/**
* When true, the InProportionSoundGenerator will play when the ratio "jumps" over in proportion in two consecutive
* values of the current ratio.
* @public
* @param {boolean} jumpingOverShouldSound
*/
setJumpingOverProportionShouldTriggerSound( jumpingOverShouldSound ) {
this.jumpingOverShouldSound = jumpingOverShouldSound;
}

/**
* True when the ratio jumped over being in proportion, but it should still sound that it was in proportion
* @private
* @returns {boolean}
*/
jumpedOverInProportionAndShouldSound() {
return this.jumpingOverShouldSound && this.calculateCurrentRatioLargerThanTarget() !== this.currentRatioWasLargerThanTarget;
}

/**
* Step this sound generator, used for fading out the sound in the absence change.
* @param {number} dt
Expand All @@ -61,12 +86,11 @@ class InProportionSoundGenerator extends SoundClip {

const isInRatio = this.model.inProportion();

const currentRatioIsLargerThanTarget = this.calculateCurrentRatioLargerThanTarget();

// Only use hysteresis when both hands are moving.
const hysteresisThreshold = this.model.movingInDirection() ? RatioAndProportionQueryParameters.hysteresisThreshold : 0;

if ( !this.playedSuccessYet && ( isInRatio || currentRatioIsLargerThanTarget !== this.currentRatioWasLargerThanTarget ) ) {
if ( !this.playedSuccessYet && ( isInRatio || this.jumpedOverInProportionAndShouldSound() ) ) {
this.setOutputLevel( SUCCESS_OUTPUT_LEVEL, 0 );
this.play();
this.playedSuccessYet = true;
Expand All @@ -82,7 +106,8 @@ class InProportionSoundGenerator extends SoundClip {
this.setOutputLevel( SILENT_LEVEL, .1 );
}

this.currentRatioWasLargerThanTarget = currentRatioIsLargerThanTarget;
// for testing during next step()
this.currentRatioWasLargerThanTarget = this.calculateCurrentRatioLargerThanTarget();
}

/**
Expand Down

0 comments on commit 865b233

Please sign in to comment.