Skip to content

Commit

Permalink
Simplify StemChannel inheritance heirarchy
Browse files Browse the repository at this point in the history
Refactor Mogg Stem subclass to no longer hold a list of channels *while also* inheriting from the IStemChannel interface. Just inherit from BassStemChannel

+ Change the IStemMixer Dictionary values to lists of channels.
  • Loading branch information
sonicfind committed Jul 8, 2023
1 parent 3122ca7 commit a1dcdc2
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 289 deletions.
80 changes: 33 additions & 47 deletions Assets/Script/Audio/Bass/BassAudioManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -292,35 +292,26 @@ public void LoadMogg(byte[] moggArray, List<(SongStem, int[], float[])> stemMaps

for (var i = 0; i < stemMaps.Count; i++)
{
int[] channelStreams = new int[stemMaps[i].Item2.Length];
var matrixes = new List<float[]>();
for (int j = 0; j < channelStreams.Length; ++j)
for (int j = 0; j < stemMaps[i].Item2.Length; ++j)
{
int channelIndex = stemMaps[i].Item2[j];
channelMap[0] = channelIndex;
channelMap[0] = stemMaps[i].Item2[j];
int splitHandle = BassMix.CreateSplitStream(moggStreamHandle, BassFlags.Decode | BassFlags.SplitPosition, channelMap);
if (splitHandle == 0)
{
throw new Exception($"Failed to create MOGG stream handle: {Bass.LastError}");
}
channelStreams[j] = splitHandle;

var matrix = new float[2];
matrix[0] = stemMaps[i].Item3[2 * j];
matrix[1] = stemMaps[i].Item3[2 * j + 1];
matrixes.Add(matrix);
}

var channel = new BassMoggStemChannel(this, stemMaps[i].Item1, channelStreams, matrixes);
if (channel.Load(speed) < 0)
{
throw new Exception($"Failed to load MOGG stem channel: {Bass.LastError}");
}
var channel = new BassMoggStemChannel(this, stemMaps[i].Item1, splitHandle, stemMaps[i].Item3[2 * j], stemMaps[i].Item3[2 * j + 1]);
if (channel.Load(speed) < 0)
{
throw new Exception($"Failed to load MOGG stem channel: {Bass.LastError}");
}

int code = mixer.AddChannel(channel);
if (code != 0)
{
throw new Exception($"Failed to add MOGG stem channel to mixer: {Bass.LastError}");
int code = mixer.AddChannel(channel);
if (code != 0)
{
throw new Exception($"Failed to add MOGG stem channel to mixer: {Bass.LastError}");
}
}
}

Expand Down Expand Up @@ -353,7 +344,7 @@ public void LoadCustomAudioFile(string audioPath, float speed)
return;
}

if (_mixer.GetChannel(SongStem.Song) != null)
if (_mixer.GetChannels(SongStem.Song) != null)
{
Debug.LogError($"Stem already loaded! {audioPath}");
return;
Expand Down Expand Up @@ -394,17 +385,7 @@ private void Play(bool fadeIn)
return;
}

foreach (var channel in _mixer.Channels.Values)
{
if (fadeIn)
{
channel.SetVolume(0);
}
else
{
channel.SetVolume(channel.Volume);
}
}
_mixer.SetPlayVolume(fadeIn);

if (_mixer.Play() != 0)
{
Expand Down Expand Up @@ -432,10 +413,8 @@ public void Pause()
public void FadeIn(float maxVolume)
{
Play(true);
if (IsPlaying)
{
_mixer?.FadeIn(maxVolume);
}
if (IsPlaying && _mixer != null)
_mixer.FadeIn(maxVolume);
}

public async UniTask FadeOut(CancellationToken token = default)
Expand Down Expand Up @@ -463,9 +442,12 @@ public void PlaySoundEffect(SfxSample sample)

public void SetStemVolume(SongStem stem, double volume)
{
var channel = _mixer?.GetChannel(stem);
if (_mixer == null)
return;

channel?.SetVolume(volume);
var stemChannels = _mixer?.GetChannels(stem);
for (int i = 0; i < stemChannels.Count; ++i)
stemChannels[i].SetVolume(volume);
}

public void SetAllStemsVolume(double volume)
Expand All @@ -475,10 +457,9 @@ public void SetAllStemsVolume(double volume)
return;
}

foreach (var (_, channel) in _mixer.Channels)
{
channel.SetVolume(volume);
}
foreach (var (_, stem) in _mixer.Channels)
for (int i = 0; i < stem.Count; ++i)
stem[i].SetVolume(volume);
}

public void UpdateVolumeSetting(SongStem stem, double volume)
Expand Down Expand Up @@ -509,14 +490,19 @@ public double GetVolumeSetting(SongStem stem)
};
}

public void ApplyReverb(SongStem stem, bool reverb) => _mixer?.GetChannel(stem)?.SetReverb(reverb);

public void ApplyReverb(SongStem stem, bool reverb)
{
foreach (var channel in _mixer.GetChannels(stem))
channel.SetReverb(reverb);
}

public void SetWhammyPitch(SongStem stem, float percent)
{
if (!AudioHelpers.PitchBendAllowedStems.Contains(stem))
if (_mixer == null || !AudioHelpers.PitchBendAllowedStems.Contains(stem))
return;

_mixer?.GetChannel(stem)?.SetWhammyPitch(percent);
foreach (var channel in _mixer.GetChannels(stem))
channel.SetWhammyPitch(percent);
}

public double GetPosition(bool desyncCompensation = true)
Expand Down
186 changes: 7 additions & 179 deletions Assets/Script/Audio/Bass/BassMoggStemChannel.cs
Original file line number Diff line number Diff line change
@@ -1,190 +1,18 @@
using System;
using System;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;

namespace YARG.Audio.BASS
{
public class BassMoggStemChannel : IStemChannel
public class BassMoggStemChannel : BassStemChannel
{
public SongStem Stem { get; }
public double LengthD { get; private set; }
public double Volume { get; private set; }
readonly public float left;
readonly public float right;

public event Action ChannelEnd
public BassMoggStemChannel(IAudioManager manager, SongStem stem, int splitStreams, float left, float right) : base(manager, stem, splitStreams)
{
add
{
if (_leadChannel is null)
{
throw new InvalidOperationException("No song is currently loaded!");
}

_leadChannel.ChannelEnd += value;
}
remove
{
if (_leadChannel is null)
{
throw new InvalidOperationException("No song is currently loaded!");
}

_leadChannel.ChannelEnd -= value;
}
}

private readonly IAudioManager _manager;

private IStemChannel _leadChannel;
private List<IStemChannel> _channels = new();
public IReadOnlyList<IStemChannel> Channels => _channels;

private List<float[]> _matrixes;
public IReadOnlyList<float[]> Matrixes => _matrixes;

private bool _isLoaded;
private bool _disposed;

public BassMoggStemChannel(IAudioManager manager, SongStem stem, int[] splitStreams, List<float[]> matrixes)
{
_manager = manager;
Stem = stem;

foreach (int stream in splitStreams)
{
_channels.Add(new BassStemChannel(_manager, Stem, stream));
}

_matrixes = matrixes;

Volume = 1;
}

~BassMoggStemChannel()
{
Dispose(false);
}

public int Load(float speed)
{
if (_disposed)
{
return -1;
}

if (_isLoaded)
{
return 0;
}

foreach (var channel in _channels)
{
channel.Load(speed);

// Get longest channel as part of this stem
double length = channel.LengthD;
if (length > LengthD)
{
_leadChannel = channel;
LengthD = length;
}
}

_isLoaded = true;

return 0;
}

public void FadeIn(float maxVolume)
{
foreach (var channel in _channels)
{
channel.FadeIn(maxVolume);
}
}

public UniTask FadeOut()
{
var fadeOuts = new List<UniTask>();
foreach (var channel in _channels)
{
fadeOuts.Add(channel.FadeOut());
}

return UniTask.WhenAll(fadeOuts);
}

public void SetVolume(double newVolume)
{
if (!_isLoaded)
{
return;
}

Volume = newVolume;

foreach (var channel in _channels)
{
channel.SetVolume(newVolume);
}
}

public void SetReverb(bool reverb)
{
foreach (var channel in _channels)
{
channel.SetReverb(reverb);
}
}

public void SetWhammyPitch(float percent)
{
foreach (var channel in _channels)
{
channel.SetWhammyPitch(percent);
}
}

public double GetPosition(bool desyncCompensation = true)
{
return _leadChannel.GetPosition(desyncCompensation);
}

public void SetPosition(double position, bool desyncCompensation = true)
{
foreach (var channel in _channels)
{
channel.SetPosition(position, desyncCompensation);
}
}

public double GetLengthInSeconds()
{
return _leadChannel.GetLengthInSeconds();
}

public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

private void Dispose(bool disposing)
{
if (!_disposed)
{
// Free managed resources here
if (disposing)
{
foreach (var channel in _channels)
{
channel.Dispose();
}

_channels = null;
}

_disposed = true;
}
this.left = left;
this.right = right;
}
}
}
Loading

0 comments on commit a1dcdc2

Please sign in to comment.