Skip to content

Commit

Permalink
Refactor and cleanup SDL2 Audio
Browse files Browse the repository at this point in the history
  • Loading branch information
hwsmm committed Oct 2, 2023
1 parent 1c4968f commit 711035d
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 173 deletions.
8 changes: 4 additions & 4 deletions osu.Framework/Audio/AudioDecoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,6 @@ public AudioDecoder(SDL.SDL_AudioSpec spec)

private readonly CancellationTokenSource tokenSource = new CancellationTokenSource();

private bool disposedValue;

/// <summary>
/// Start decoding in the decoding thread.
/// </summary>
Expand Down Expand Up @@ -369,6 +367,8 @@ private int loadFromStream(AudioDecoderData job)
return 0;
}

private bool disposedValue;

protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
Expand All @@ -395,12 +395,12 @@ protected virtual void Dispose(bool disposing)

~AudioDecoder()
{
Dispose(disposing: false);
Dispose(false);
}

public void Dispose()
{
Dispose(disposing: true);
Dispose(true);
GC.SuppressFinalize(this);
}
}
Expand Down
40 changes: 17 additions & 23 deletions osu.Framework/Audio/Mixing/SDL2/SDL2AudioMixer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,13 @@ public void MixChannelsInto(float[] data)
{
lock (syncRoot)
{
int sampleCount = data.Length;
if (ret == null || sampleCount != ret.Length)
ret = new float[sampleCount];
int sampleCount = data.Length;
if (ret == null || sampleCount != ret.Length)
ret = new float[sampleCount];

bool useFilters = AudioFilters.Count > 0;
float[] put = useFilters ? new float[sampleCount] : data;
bool useFilters = audioFilters.Count > 0;
float[] put = useFilters ? new float[sampleCount] : data;

lock (activeChannels)
{
var node = activeChannels.First;

while (node != null)
Expand Down Expand Up @@ -123,26 +121,22 @@ public void MixChannelsInto(float[] data)
}

channelCount = activeChannels.Count;
}

if (useFilters)
{
lock (AudioFilters)
if (useFilters)
{
for (int i = 0; i < sampleCount; i++)
{
foreach (var filter in AudioFilters)
foreach (var filter in audioFilters)
{
if (filter.BiQuadFilter != null)
put[i] = filter.BiQuadFilter.Transform(put[i]);
}
}
}

mixAudio(data, put, sampleCount, SDL.SDL_MIX_MAXVOLUME);
mixAudio(data, put, sampleCount, SDL.SDL_MIX_MAXVOLUME);
}
}
}
}

private void adjustBalance(double balance, float[] audio, int size)
{
Expand All @@ -157,7 +151,7 @@ private void adjustBalance(double balance, float[] audio, int size)
}
}

internal readonly List<EffectBox> AudioFilters = new List<EffectBox>();
private readonly List<EffectBox> audioFilters = new List<EffectBox>();

private void onEffectsChanged(object? sender, NotifyCollectionChangedEventArgs e) => EnqueueAction(() =>
{
Expand All @@ -169,23 +163,23 @@ private void onEffectsChanged(object? sender, NotifyCollectionChangedEventArgs e
{
Debug.Assert(e.NewItems != null);
int startIndex = Math.Max(0, e.NewStartingIndex);
AudioFilters.InsertRange(startIndex, e.NewItems.OfType<IEffectParameter>().Select(eff => new EffectBox(eff)));
audioFilters.InsertRange(startIndex, e.NewItems.OfType<IEffectParameter>().Select(eff => new EffectBox(eff)));
break;
}

case NotifyCollectionChangedAction.Move:
{
EffectBox effect = AudioFilters[e.OldStartingIndex];
AudioFilters.RemoveAt(e.OldStartingIndex);
AudioFilters.Insert(e.NewStartingIndex, effect);
EffectBox effect = audioFilters[e.OldStartingIndex];
audioFilters.RemoveAt(e.OldStartingIndex);
audioFilters.Insert(e.NewStartingIndex, effect);
break;
}

case NotifyCollectionChangedAction.Remove:
{
Debug.Assert(e.OldItems != null);

AudioFilters.RemoveRange(e.OldStartingIndex, e.OldItems.Count);
audioFilters.RemoveRange(e.OldStartingIndex, e.OldItems.Count);
break;
}

Expand All @@ -194,13 +188,13 @@ private void onEffectsChanged(object? sender, NotifyCollectionChangedEventArgs e
Debug.Assert(e.NewItems != null);

EffectBox newFilter = new EffectBox((IEffectParameter)e.NewItems[0].AsNonNull());
AudioFilters[e.NewStartingIndex] = newFilter;
audioFilters[e.NewStartingIndex] = newFilter;
break;
}

case NotifyCollectionChangedAction.Reset:
{
AudioFilters.Clear();
audioFilters.Clear();
break;
}
}
Expand Down
27 changes: 12 additions & 15 deletions osu.Framework/Audio/ResamplingPlayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace osu.Framework.Audio
/// Abstract class that's meant to be used with a real player implementation.
/// This class provides resampling on the fly for players.
/// </summary>
internal abstract class ResamplingPlayer : AudioComponent
internal abstract class ResamplingPlayer
{
/// <summary>
/// Represents current relative rate. Use <see cref="SetRate(double)"/> to set this variable.
Expand All @@ -19,8 +19,8 @@ internal abstract class ResamplingPlayer : AudioComponent

private WdlResampler? resampler;

private readonly int srcRate;
private readonly byte srcChannels;
protected readonly int SrcRate;
protected readonly byte SrcChannels;

/// <summary>
/// Creates a new <see cref="ResamplingPlayer"/>.
Expand All @@ -29,8 +29,8 @@ internal abstract class ResamplingPlayer : AudioComponent
/// <param name="srcChannels">Channels of audio that's given from <see cref="GetRemainingRawFloats(float[], int, int)"/> or <see cref="GetRemainingRawBytes(byte[])"/></param>
protected ResamplingPlayer(int srcRate, byte srcChannels)
{
this.srcRate = srcRate;
this.srcChannels = srcChannels;
SrcRate = srcRate;
SrcChannels = srcChannels;
}

/// <summary>
Expand All @@ -56,7 +56,7 @@ public void SetRate(double relativeRate)
resampler.SetFeedMode(false);
}

resampler.SetRates(srcRate, srcRate / relativeRate);
resampler.SetRates(SrcRate, SrcRate / relativeRate);
RelativeRate = relativeRate;
}

Expand All @@ -65,11 +65,9 @@ protected double GetResampleLatency()
if (resampler == null || RelativeRate == 1)
return 0;

return latencyCache;
return resampler.GetCurrentLatency() * 1000.0d;
}

private double latencyCache;

/// <summary>
/// Returns rate adjusted audio samples. It calls a parent method if <see cref="RelativeRate"/> is 1.
/// </summary>
Expand All @@ -83,15 +81,14 @@ public virtual int GetRemainingSamples(float[] data)
if (resampler == null || RelativeRate == 1)
return GetRemainingRawFloats(data, 0, data.Length);

int requested = data.Length / srcChannels;
int needed = resampler.ResamplePrepare(requested, srcChannels, out float[] inBuffer, out int inBufferOffset);
int rawGot = GetRemainingRawFloats(inBuffer, inBufferOffset, needed * srcChannels);
int requested = data.Length / SrcChannels;
int needed = resampler.ResamplePrepare(requested, SrcChannels, out float[] inBuffer, out int inBufferOffset);
int rawGot = GetRemainingRawFloats(inBuffer, inBufferOffset, needed * SrcChannels);

if (rawGot > 0)
{
int got = resampler.ResampleOut(data, 0, rawGot / srcChannels, requested, srcChannels);
latencyCache = resampler.GetCurrentLatency() * 1000.0d;
return got * srcChannels;
int got = resampler.ResampleOut(data, 0, rawGot / SrcChannels, requested, SrcChannels);
return got * SrcChannels;
}

return 0;
Expand Down
16 changes: 7 additions & 9 deletions osu.Framework/Audio/SDL2AudioManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ public class SDL2AudioManager : AudioManager

private SDL.SDL_AudioSpec spec;

public SDL.SDL_AudioSpec Spec => spec;

private readonly AudioDecoder decoder;

/// <summary>
Expand Down Expand Up @@ -148,11 +146,11 @@ protected override bool SetAudioDevice(string deviceName = null)
Logger.Log($@"🔈 SDL Audio initialised
Driver: {SDL.SDL_GetCurrentAudioDriver()}
Device Name: {currentDeviceName}
Frequency: {Spec.freq} hz
Channels: {Spec.channels}
Format: {(SDL.SDL_AUDIO_ISSIGNED(Spec.format) ? "" : "un")}signed {SDL.SDL_AUDIO_BITSIZE(Spec.format)} bits{(SDL.SDL_AUDIO_ISFLOAT(Spec.format) ? " (float)" : "")}
Samples: {Spec.samples} samples
Buffer size: {Spec.size} bytes");
Frequency: {spec.freq} hz
Channels: {spec.channels}
Format: {(SDL.SDL_AUDIO_ISSIGNED(spec.format) ? "" : "un")}signed {SDL.SDL_AUDIO_BITSIZE(spec.format)} bits{(SDL.SDL_AUDIO_ISFLOAT(spec.format) ? " (float)" : "")}
Samples: {spec.samples} samples
Buffer size: {spec.size} bytes");

return true;
}
Expand All @@ -169,13 +167,13 @@ protected override bool SetAudioDevice(int deviceIndex)

internal override Track.Track GetNewTrack(Stream data, string name)
{
TrackSDL2 track = new TrackSDL2(name, Spec.freq, Spec.channels, Spec.samples);
TrackSDL2 track = new TrackSDL2(name, spec.freq, spec.channels, spec.samples);
decoder.StartDecodingAsync(data, track.AddToQueue, null);
return track;
}

internal override SampleFactory GetSampleFactory(Stream data, string name, AudioMixer mixer, int playbackConcurrency)
=> new SampleSDL2Factory(data, name, (SDL2AudioMixer)mixer, playbackConcurrency, Spec, decoder);
=> new SampleSDL2Factory(data, name, (SDL2AudioMixer)mixer, playbackConcurrency, spec, decoder);

protected override void Dispose(bool disposing)
{
Expand Down
17 changes: 2 additions & 15 deletions osu.Framework/Audio/Sample/SampleChannelSDL2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,6 @@ public SampleChannelSDL2(SampleSDL2 sample)
this.sample = sample;
}

protected override void UpdateChildren()
{
base.UpdateChildren();

if (player != null)
{
lock (syncRoot)
player.Update();
}
}

public override void Play()
{
enqueuedPlaybackStart = true;
Expand Down Expand Up @@ -107,7 +96,7 @@ int ISDL2AudioChannel.GetRemainingSamples(float[] data)

ret = player.GetRemainingSamples(data);

if (player.IsDone())
if (player.Done)
playing = false;
}

Expand All @@ -134,12 +123,10 @@ protected override void Dispose(bool disposing)

lock (syncRoot)
{
player?.Dispose();
playing = false;
player = null;
}

playing = false;

base.Dispose(disposing);
}
}
Expand Down
11 changes: 3 additions & 8 deletions osu.Framework/Audio/Sample/SampleSDL2AudioPlayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ namespace osu.Framework.Audio.Sample
{
internal class SampleSDL2AudioPlayer : ResamplingPlayer
{
public override bool IsLoaded => true;

private int position;
private bool done;

private volatile bool done;
public bool Done => done;

private readonly float[] audioData;

Expand Down Expand Up @@ -67,10 +67,5 @@ public void Reset(bool resetIndex = true)
if (resetIndex)
position = 0;
}

public bool IsDone()
{
return done;
}
}
}
Loading

0 comments on commit 711035d

Please sign in to comment.