Merge pull request #25185 from bdach/minimum-sample-volume

This commit is contained in:
Dean Herbert 2023-10-24 22:04:43 +09:00 committed by GitHub
commit 34505b3933
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 49 additions and 6 deletions

View File

@ -108,7 +108,11 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
RelativeSizeAxes = Axes.X
},
tailContainer = new Container<DrawableHoldNoteTail> { RelativeSizeAxes = Axes.Both },
slidingSample = new PausableSkinnableSound { Looping = true }
slidingSample = new PausableSkinnableSound
{
Looping = true,
MinimumSampleVolume = MINIMUM_SAMPLE_VOLUME,
}
});
maskedContents.AddRange(new[]

View File

@ -107,7 +107,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
headContainer = new Container<DrawableSliderHead> { RelativeSizeAxes = Axes.Both },
OverlayElementContainer = new Container { RelativeSizeAxes = Axes.Both, },
Ball,
slidingSample = new PausableSkinnableSound { Looping = true }
slidingSample = new PausableSkinnableSound
{
Looping = true,
MinimumSampleVolume = MINIMUM_SAMPLE_VOLUME,
}
});
PositionBindable.BindValueChanged(_ => Position = HitObject.StackedPosition);

View File

@ -106,6 +106,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
spinningSample = new PausableSkinnableSound
{
Volume = { Value = 0 },
MinimumSampleVolume = MINIMUM_SAMPLE_VOLUME,
Looping = true,
Frequency = { Value = spinning_sample_initial_frequency }
}

View File

@ -159,6 +159,26 @@ namespace osu.Game.Rulesets.Objects.Drawables
/// </summary>
internal bool IsInitialized;
/// <summary>
/// The minimum allowable volume for sample playback.
/// <see cref="Samples"/> quieter than that will be forcibly played at this volume instead.
/// </summary>
/// <remarks>
/// <para>
/// Drawable hitobjects adding their own custom samples, or other sample playback sources
/// (i.e. <see cref="GameplaySampleTriggerSource"/>) must enforce this themselves.
/// </para>
/// <para>
/// This sample volume floor is present in stable, although it is set at 8% rather than 5%.
/// See: https://github.com/peppy/osu-stable-reference/blob/3ea48705eb67172c430371dcfc8a16a002ed0d3d/osu!/Audio/AudioEngine.cs#L1070,
/// https://github.com/peppy/osu-stable-reference/blob/3ea48705eb67172c430371dcfc8a16a002ed0d3d/osu!/Audio/AudioEngine.cs#L1404-L1405.
/// The reason why it is 5% here is that the 8% cap was enforced in a silent manner
/// (i.e. the minimum selectable volume in the editor was 5%, but it would be played at 8% anyways),
/// which is confusing and arbitrary, so we're just doing 5% here at the cost of sacrificing strict parity.
/// </para>
/// </remarks>
public const int MINIMUM_SAMPLE_VOLUME = 5;
/// <summary>
/// Creates a new <see cref="DrawableHitObject"/>.
/// </summary>
@ -181,7 +201,10 @@ namespace osu.Game.Rulesets.Objects.Drawables
comboColourBrightness.BindTo(gameplaySettings.ComboColourNormalisationAmount);
// Explicit non-virtual function call in case a DrawableHitObject overrides AddInternal.
base.AddInternal(Samples = new PausableSkinnableSound());
base.AddInternal(Samples = new PausableSkinnableSound
{
MinimumSampleVolume = MINIMUM_SAMPLE_VOLUME
});
CurrentSkin = skinSource;
CurrentSkin.SourceChanged += skinSourceChanged;

View File

@ -7,6 +7,7 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics.Containers;
using osu.Game.Audio;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Scoring;
using osu.Game.Screens.Play;
using osu.Game.Skinning;
@ -45,7 +46,10 @@ namespace osu.Game.Rulesets.UI
Child = hitSounds = new Container<SkinnableSound>
{
Name = "concurrent sample pool",
ChildrenEnumerable = Enumerable.Range(0, max_concurrent_hitsounds).Select(_ => new PausableSkinnableSound())
ChildrenEnumerable = Enumerable.Range(0, max_concurrent_hitsounds).Select(_ => new PausableSkinnableSound
{
MinimumSampleVolume = DrawableHitObject.MINIMUM_SAMPLE_VOLUME
})
}
};
}

View File

@ -16,6 +16,7 @@ using osu.Game.Audio;
using osu.Game.Graphics;
using osu.Game.Graphics.UserInterfaceV2;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Screens.Edit.Timing;
using osuTK;
using osuTK.Graphics;
@ -101,7 +102,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
},
volume = new IndeterminateSliderWithTextBoxInput<int>("Volume", new BindableInt(100)
{
MinValue = 0,
MinValue = DrawableHitObject.MINIMUM_SAMPLE_VOLUME,
MaxValue = 100,
})
}

View File

@ -20,6 +20,12 @@ namespace osu.Game.Skinning
/// </summary>
public partial class SkinnableSound : SkinReloadableDrawable, IAdjustableAudioComponent
{
/// <summary>
/// The minimum allowable volume for <see cref="Samples"/>.
/// <see cref="Samples"/> that specify a lower <see cref="ISampleInfo.Volume"/> will be forcibly pulled up to this volume.
/// </summary>
public int MinimumSampleVolume { get; set; }
public override bool RemoveWhenNotAlive => false;
public override bool RemoveCompletedTransforms => false;
@ -156,7 +162,7 @@ namespace osu.Game.Skinning
{
var sample = samplePool?.GetPooledSample(s) ?? new PoolableSkinnableSample(s);
sample.Looping = Looping;
sample.Volume.Value = s.Volume / 100.0;
sample.Volume.Value = Math.Max(s.Volume, MinimumSampleVolume) / 100.0;
samplesContainer.Add(sample);
}