mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 13:37:25 +08:00
Avoid using bindable for AudioFilter
cutoff
It doesn't play nicely with screen exiting, as it is automatically unbound during the exit process. Easiest to just avoid using this for now.
This commit is contained in:
parent
6f79d29ba4
commit
b37096f440
@ -34,6 +34,9 @@ namespace osu.Game.Tests.Visual.Audio
|
|||||||
beatmap = new WaveformTestBeatmap(audio);
|
beatmap = new WaveformTestBeatmap(audio);
|
||||||
track = beatmap.LoadTrack();
|
track = beatmap.LoadTrack();
|
||||||
|
|
||||||
|
OsuSliderBar<int> lowPassCutoff;
|
||||||
|
OsuSliderBar<int> highPassCutoff;
|
||||||
|
|
||||||
Add(new FillFlowContainer
|
Add(new FillFlowContainer
|
||||||
{
|
{
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
@ -43,33 +46,41 @@ namespace osu.Game.Tests.Visual.Audio
|
|||||||
lowpassText = new OsuSpriteText
|
lowpassText = new OsuSpriteText
|
||||||
{
|
{
|
||||||
Padding = new MarginPadding(20),
|
Padding = new MarginPadding(20),
|
||||||
Text = $"Low Pass: {lowpassFilter.Cutoff.Value}hz",
|
Text = $"Low Pass: {lowpassFilter.Cutoff}hz",
|
||||||
Font = new FontUsage(size: 40)
|
Font = new FontUsage(size: 40)
|
||||||
},
|
},
|
||||||
new OsuSliderBar<int>
|
lowPassCutoff = new OsuSliderBar<int>
|
||||||
{
|
{
|
||||||
Width = 500,
|
Width = 500,
|
||||||
Height = 50,
|
Height = 50,
|
||||||
Padding = new MarginPadding(20),
|
Padding = new MarginPadding(20),
|
||||||
Current = { BindTarget = lowpassFilter.Cutoff }
|
|
||||||
},
|
},
|
||||||
highpassText = new OsuSpriteText
|
highpassText = new OsuSpriteText
|
||||||
{
|
{
|
||||||
Padding = new MarginPadding(20),
|
Padding = new MarginPadding(20),
|
||||||
Text = $"High Pass: {highpassFilter.Cutoff.Value}hz",
|
Text = $"High Pass: {highpassFilter.Cutoff}hz",
|
||||||
Font = new FontUsage(size: 40)
|
Font = new FontUsage(size: 40)
|
||||||
},
|
},
|
||||||
new OsuSliderBar<int>
|
highPassCutoff = new OsuSliderBar<int>
|
||||||
{
|
{
|
||||||
Width = 500,
|
Width = 500,
|
||||||
Height = 50,
|
Height = 50,
|
||||||
Padding = new MarginPadding(20),
|
Padding = new MarginPadding(20),
|
||||||
Current = { BindTarget = highpassFilter.Cutoff }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
lowpassFilter.Cutoff.ValueChanged += e => lowpassText.Text = $"Low Pass: {e.NewValue}hz";
|
|
||||||
highpassFilter.Cutoff.ValueChanged += e => highpassText.Text = $"High Pass: {e.NewValue}hz";
|
lowPassCutoff.Current.ValueChanged += e =>
|
||||||
|
{
|
||||||
|
lowpassText.Text = $"Low Pass: {e.NewValue}hz";
|
||||||
|
lowpassFilter.Cutoff = e.NewValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
highPassCutoff.Current.ValueChanged += e =>
|
||||||
|
{
|
||||||
|
highpassText.Text = $"High Pass: {e.NewValue}hz";
|
||||||
|
highpassFilter.Cutoff = e.NewValue;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
[SetUpSteps]
|
[SetUpSteps]
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using ManagedBass.Fx;
|
using ManagedBass.Fx;
|
||||||
using osu.Framework.Audio.Mixing;
|
using osu.Framework.Audio.Mixing;
|
||||||
using osu.Framework.Bindables;
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Audio.Effects
|
namespace osu.Game.Audio.Effects
|
||||||
@ -21,10 +20,25 @@ namespace osu.Game.Audio.Effects
|
|||||||
private readonly BQFParameters filter;
|
private readonly BQFParameters filter;
|
||||||
private readonly BQFType type;
|
private readonly BQFType type;
|
||||||
|
|
||||||
|
private int cutoff;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The current cutoff of this filter.
|
/// The cutoff frequency of this filter.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public BindableNumber<int> Cutoff { get; }
|
public int Cutoff
|
||||||
|
{
|
||||||
|
get => cutoff;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == cutoff)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int oldValue = cutoff;
|
||||||
|
cutoff = value;
|
||||||
|
|
||||||
|
updateFilter(oldValue, cutoff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A Component that implements a BASS FX BiQuad Filter Effect.
|
/// A Component that implements a BASS FX BiQuad Filter Effect.
|
||||||
@ -36,33 +50,25 @@ namespace osu.Game.Audio.Effects
|
|||||||
this.mixer = mixer;
|
this.mixer = mixer;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
|
||||||
int initialCutoff;
|
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case BQFType.HighPass:
|
case BQFType.HighPass:
|
||||||
initialCutoff = 1;
|
cutoff = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BQFType.LowPass:
|
case BQFType.LowPass:
|
||||||
initialCutoff = MAX_LOWPASS_CUTOFF;
|
cutoff = MAX_LOWPASS_CUTOFF;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
initialCutoff = 500; // A default that should ensure audio remains audible for other filters.
|
cutoff = 500; // A default that should ensure audio remains audible for other filters.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Cutoff = new BindableNumber<int>(initialCutoff)
|
|
||||||
{
|
|
||||||
MinValue = 1,
|
|
||||||
MaxValue = MAX_LOWPASS_CUTOFF
|
|
||||||
};
|
|
||||||
|
|
||||||
filter = new BQFParameters
|
filter = new BQFParameters
|
||||||
{
|
{
|
||||||
lFilter = type,
|
lFilter = type,
|
||||||
fCenter = initialCutoff,
|
fCenter = cutoff,
|
||||||
fBandwidth = 0,
|
fBandwidth = 0,
|
||||||
fQ = 0.7f // This allows fCenter to go up to 22049hz (nyquist - 1hz) without overflowing and causing weird filter behaviour (see: https://www.un4seen.com/forum/?topic=19542.0)
|
fQ = 0.7f // This allows fCenter to go up to 22049hz (nyquist - 1hz) without overflowing and causing weird filter behaviour (see: https://www.un4seen.com/forum/?topic=19542.0)
|
||||||
};
|
};
|
||||||
@ -70,8 +76,6 @@ namespace osu.Game.Audio.Effects
|
|||||||
// Don't start attached if this is low-pass or high-pass filter (as they have special auto-attach/detach logic)
|
// Don't start attached if this is low-pass or high-pass filter (as they have special auto-attach/detach logic)
|
||||||
if (type != BQFType.LowPass && type != BQFType.HighPass)
|
if (type != BQFType.LowPass && type != BQFType.HighPass)
|
||||||
attachFilter();
|
attachFilter();
|
||||||
|
|
||||||
Cutoff.ValueChanged += updateFilter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void attachFilter()
|
private void attachFilter()
|
||||||
@ -86,40 +90,41 @@ namespace osu.Game.Audio.Effects
|
|||||||
mixer.Effects.Remove(filter);
|
mixer.Effects.Remove(filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateFilter(ValueChangedEvent<int> cutoff)
|
private void updateFilter(int oldValue, int newValue)
|
||||||
{
|
{
|
||||||
// Workaround for weird behaviour when rapidly setting fCenter of a low-pass filter to nyquist - 1hz.
|
// Workaround for weird behaviour when rapidly setting fCenter of a low-pass filter to nyquist - 1hz.
|
||||||
if (type == BQFType.LowPass)
|
if (type == BQFType.LowPass)
|
||||||
{
|
{
|
||||||
if (cutoff.NewValue >= MAX_LOWPASS_CUTOFF)
|
if (newValue >= MAX_LOWPASS_CUTOFF)
|
||||||
{
|
{
|
||||||
detachFilter();
|
detachFilter();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cutoff.OldValue >= MAX_LOWPASS_CUTOFF && cutoff.NewValue < MAX_LOWPASS_CUTOFF)
|
if (oldValue >= MAX_LOWPASS_CUTOFF)
|
||||||
attachFilter();
|
attachFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Workaround for weird behaviour when rapidly setting fCenter of a high-pass filter to 1hz.
|
// Workaround for weird behaviour when rapidly setting fCenter of a high-pass filter to 1hz.
|
||||||
if (type == BQFType.HighPass)
|
if (type == BQFType.HighPass)
|
||||||
{
|
{
|
||||||
if (cutoff.NewValue <= 1)
|
if (newValue <= 1)
|
||||||
{
|
{
|
||||||
detachFilter();
|
detachFilter();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cutoff.OldValue <= 1 && cutoff.NewValue > 1)
|
if (oldValue <= 1)
|
||||||
attachFilter();
|
attachFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
var filterIndex = mixer.Effects.IndexOf(filter);
|
var filterIndex = mixer.Effects.IndexOf(filter);
|
||||||
|
|
||||||
if (filterIndex < 0) return;
|
if (filterIndex < 0) return;
|
||||||
|
|
||||||
if (mixer.Effects[filterIndex] is BQFParameters existingFilter)
|
if (mixer.Effects[filterIndex] is BQFParameters existingFilter)
|
||||||
{
|
{
|
||||||
existingFilter.fCenter = cutoff.NewValue;
|
existingFilter.fCenter = newValue;
|
||||||
|
|
||||||
// required to update effect with new parameters.
|
// required to update effect with new parameters.
|
||||||
mixer.Effects[filterIndex] = existingFilter;
|
mixer.Effects[filterIndex] = existingFilter;
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using osu.Framework.Bindables;
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Transforms;
|
using osu.Framework.Graphics.Transforms;
|
||||||
|
|
||||||
@ -12,7 +11,7 @@ namespace osu.Game.Audio.Effects
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The filter cutoff.
|
/// The filter cutoff.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
BindableNumber<int> Cutoff { get; }
|
int Cutoff { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class FilterableAudioComponentExtensions
|
public static class FilterableAudioComponentExtensions
|
||||||
@ -40,7 +39,7 @@ namespace osu.Game.Audio.Effects
|
|||||||
public static TransformSequence<T> CutoffTo<T, TEasing>(this T component, int newCutoff, double duration, TEasing easing)
|
public static TransformSequence<T> CutoffTo<T, TEasing>(this T component, int newCutoff, double duration, TEasing easing)
|
||||||
where T : class, ITransformableFilter, IDrawable
|
where T : class, ITransformableFilter, IDrawable
|
||||||
where TEasing : IEasingFunction
|
where TEasing : IEasingFunction
|
||||||
=> component.TransformBindableTo(component.Cutoff, newCutoff, duration, easing);
|
=> component.TransformTo(nameof(component.Cutoff), newCutoff, duration, easing);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Smoothly adjusts filter cutoff over time.
|
/// Smoothly adjusts filter cutoff over time.
|
||||||
@ -49,6 +48,6 @@ namespace osu.Game.Audio.Effects
|
|||||||
public static TransformSequence<T> CutoffTo<T, TEasing>(this TransformSequence<T> sequence, int newCutoff, double duration, TEasing easing)
|
public static TransformSequence<T> CutoffTo<T, TEasing>(this TransformSequence<T> sequence, int newCutoff, double duration, TEasing easing)
|
||||||
where T : class, ITransformableFilter, IDrawable
|
where T : class, ITransformableFilter, IDrawable
|
||||||
where TEasing : IEasingFunction
|
where TEasing : IEasingFunction
|
||||||
=> sequence.Append(o => o.TransformBindableTo(o.Cutoff, newCutoff, duration, easing));
|
=> sequence.Append(o => o.TransformTo(nameof(o.Cutoff), newCutoff, duration, easing));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user