Skip to content

Commit

Permalink
Apply volume changes in a much nicer way
Browse files Browse the repository at this point in the history
  • Loading branch information
peppy committed Jul 5, 2024
1 parent f87ba15 commit 11d5a51
Show file tree
Hide file tree
Showing 5 changed files with 14 additions and 28 deletions.
6 changes: 3 additions & 3 deletions osu.Framework/Audio/AudioManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,10 @@ public AudioManager(AudioThread audioThread, ResourceStore<byte[]> trackStore, R
usingGlobalMixer.Value = handle.NewValue.HasValue;
};

TrackMixer = createAudioMixer(null, nameof(TrackMixer));
SampleMixer = createAudioMixer(null, nameof(SampleMixer));

AddItem(TrackMixer = createAudioMixer(null, nameof(TrackMixer)));
TrackMixer.Volume.BindTo(VolumeTrack);

AddItem(SampleMixer = createAudioMixer(null, nameof(SampleMixer)));
SampleMixer.Volume.BindTo(VolumeSample);

globalTrackStore = new Lazy<TrackStore>(() =>
Expand Down
12 changes: 7 additions & 5 deletions osu.Framework/Audio/Mixing/AudioMixer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,17 @@
// See the LICENCE file in the repository root for full licence text.

using ManagedBass;

using osu.Framework.Bindables;
using osu.Framework.Extensions.ObjectExtensions;

namespace osu.Framework.Audio.Mixing
{
/// <summary>
/// Mixes together multiple <see cref="IAudioChannel"/>s into one output.
/// </summary>
public abstract class AudioMixer : AudioComponent, IAudioMixer
public abstract class AudioMixer : AdjustableAudioComponent, IAudioMixer
{
public readonly string Identifier;

public readonly Bindable<double> Volume = new BindableDouble(1);

private readonly AudioMixer? fallbackMixer;

/// <summary>
Expand All @@ -33,6 +29,9 @@ protected AudioMixer(AudioMixer? fallbackMixer, string identifier)

public void Add(IAudioChannel channel)
{
if (channel is IAdjustableAudioComponent adj)
adj.BindAdjustments(this);

channel.EnqueueAction(() =>
{
if (channel.Mixer == this)
Expand Down Expand Up @@ -74,6 +73,9 @@ protected void Remove(IAudioChannel channel, bool returnToDefault)
RemoveInternal(channel);
channel.Mixer = null;

if (channel is IAdjustableAudioComponent adj)
adj.UnbindAdjustments(this);

// Add the channel back to the default mixer so audio can always be played.
if (returnToDefault)
fallbackMixer.AsNonNull().Add(channel);
Expand Down
13 changes: 1 addition & 12 deletions osu.Framework/Audio/Sample/SampleChannel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,20 +55,9 @@ protected override void UpdateState()
AudioMixer? IAudioChannel.Mixer
{
get => Mixer;
set
{
if (Mixer != null)
Mixer.Volume.ValueChanged -= mixerVolumeChanged;

Mixer = value;

if (Mixer != null)
Mixer.Volume.ValueChanged += mixerVolumeChanged;
}
set => Mixer = value;
}

private void mixerVolumeChanged(Bindables.ValueChangedEvent<double> obj) => OnStateChanged();

Task IAudioChannel.EnqueueAction(Action action) => EnqueueAction(action);

#endregion
Expand Down
2 changes: 1 addition & 1 deletion osu.Framework/Audio/Sample/SampleChannelBass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ internal override void OnStateChanged()
if (!hasChannel)
return;

Bass.ChannelSetAttribute(channel, ChannelAttribute.Volume, AggregateVolume.Value * bassMixer.Volume.Value);
Bass.ChannelSetAttribute(channel, ChannelAttribute.Volume, AggregateVolume.Value);
Bass.ChannelSetAttribute(channel, ChannelAttribute.Pan, AggregateBalance.Value);
relativeFrequencyHandler.SetFrequency(AggregateFrequency.Value);
}
Expand Down
9 changes: 2 additions & 7 deletions osu.Framework/Audio/Track/TrackBass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,8 @@ internal override void OnStateChanged()
return;

setDirection(AggregateFrequency.Value < 0);
Bass.ChannelSetAttribute(activeStream, ChannelAttribute.Volume, AggregateVolume.Value * bassMixer.Volume.Value);

Bass.ChannelSetAttribute(activeStream, ChannelAttribute.Volume, AggregateVolume.Value);
Bass.ChannelSetAttribute(activeStream, ChannelAttribute.Pan, AggregateBalance.Value);
relativeFrequencyHandler.SetFrequency(AggregateFrequency.Value);

Expand Down Expand Up @@ -422,10 +423,7 @@ protected override AudioMixer? Mixer
{
// While BASS cleans up syncs automatically on mixer change, ManagedBass internally tracks the sync procedures via ChannelReferences, so clean up eagerly for safety.
if (Mixer != null)
{
Mixer.Volume.ValueChanged -= mixerVolumeChanged;
cleanUpSyncs();
}

base.Mixer = value;

Expand All @@ -434,16 +432,13 @@ protected override AudioMixer? Mixer
{
// Tracks are always active until they're disposed, so they need to be added to the mix prematurely for operations like Seek() to work immediately.
bassMixer.AddChannelToBassMix(this);
Mixer.Volume.ValueChanged += mixerVolumeChanged;

// Syncs are not automatically moved on mixer change, so restore them on the new mixer manually.
initializeSyncs();
}
}
}

private void mixerVolumeChanged(Bindables.ValueChangedEvent<double> obj) => OnStateChanged();

private BassAudioMixer bassMixer => (BassAudioMixer)Mixer.AsNonNull();

bool IBassAudioChannel.IsActive => !IsDisposed;
Expand Down

0 comments on commit 11d5a51

Please sign in to comment.