diff --git a/Assets/Script/Audio/Bass/BassAudioManager.cs b/Assets/Script/Audio/Bass/BassAudioManager.cs index df697d415..cc0344314 100644 --- a/Assets/Script/Audio/Bass/BassAudioManager.cs +++ b/Assets/Script/Audio/Bass/BassAudioManager.cs @@ -4,6 +4,7 @@ using ManagedBass; using UnityEngine; using YARG.Serialization; +using YARG.Song; using Debug = UnityEngine.Debug; namespace YARG { @@ -210,10 +211,8 @@ public void LoadMogg(XboxMoggData moggData, bool isSpeedUp) { int moggOffset = moggData.MoggAddressAudioOffset; long moggLength = moggData.MoggAudioLength; - //byte[] moggArray = File.ReadAllBytes(moggData.MoggPath)[moggOffset..]; byte[] moggArray = moggData.GetOggDataFromMogg(); - //int moggStreamHandle = Bass.CreateStream(moggArray, 0, moggArray.Length, BassFlags.Prescan | BassFlags.Decode | BassFlags.AsyncFile); int moggStreamHandle = Bass.CreateStream(moggArray, 0, moggLength, BassFlags.Prescan | BassFlags.Decode | BassFlags.AsyncFile); if (moggStreamHandle == 0) { Debug.LogError($"Failed to load mogg file or position: {Bass.LastError}"); @@ -247,14 +246,30 @@ public void UnloadSong() { _mixer = null; } - public void Play() { + public void LoadPreviewAudio(SongEntry song) { + if (song is ExtractedConSongEntry conSong) { + LoadMogg(conSong.MoggInfo, false); + } else { + LoadSong(AudioHelpers.GetSupportedStems(song.Location), false); + } + + SetPosition(song.PreviewStartTimeSpan.TotalSeconds); + } + + public void Play() => Play(false); + + private void Play(bool fadeIn) { // Don't try to play if there's no audio loaded or if it's already playing if (!IsAudioLoaded || IsPlaying) { return; } foreach (var channel in _mixer.Channels.Values) { - channel.SetVolume(channel.Volume); + if (fadeIn) { + channel.SetVolume(0); + } else { + channel.SetVolume(channel.Volume); + } } if (_mixer.Play() != 0) { Debug.Log($"Play error: {Bass.LastError}"); @@ -275,6 +290,19 @@ public void Pause() { IsPlaying = _mixer.IsPlaying; } + public void FadeIn() { + Play(true); + if (IsPlaying) { + _mixer?.FadeIn(); + } + } + + public void FadeOut() { + if (IsPlaying) { + _mixer?.FadeOut(); + } + } + public void PlaySoundEffect(SfxSample sample) { var sfx = _sfxSamples[(int) sample]; @@ -311,9 +339,7 @@ public double GetVolumeSetting(SongStem stem) { }; } - public void ApplyReverb(SongStem stem, bool reverb) { - _mixer?.GetChannel(stem)?.SetReverb(reverb); - } + public void ApplyReverb(SongStem stem, bool reverb) => _mixer?.GetChannel(stem)?.SetReverb(reverb); public double GetPosition() { if (_mixer is null) @@ -322,9 +348,7 @@ public double GetPosition() { return _mixer.GetPosition(); } - public void SetPosition(double position) { - throw new NotImplementedException(); - } + public void SetPosition(double position) => _mixer?.SetPosition(position); private void OnApplicationQuit() { Unload(); diff --git a/Assets/Script/Audio/Bass/BassHelpers.cs b/Assets/Script/Audio/Bass/BassHelpers.cs index dc736964a..add703652 100644 --- a/Assets/Script/Audio/Bass/BassHelpers.cs +++ b/Assets/Script/Audio/Bass/BassHelpers.cs @@ -7,6 +7,8 @@ namespace YARG { public static class BassHelpers { public const float SONG_VOLUME_MULTIPLIER = 0.7f; + + public const int FADE_TIME_MILLISECONDS = 2000; public const int REVERB_SLIDE_IN_MILLISECONDS = 300; public const int REVERB_SLIDE_OUT_MILLISECONDS = 500; diff --git a/Assets/Script/Audio/Bass/BassMoggStem.cs b/Assets/Script/Audio/Bass/BassMoggStem.cs index 3fa6f600a..37b4f8001 100644 --- a/Assets/Script/Audio/Bass/BassMoggStem.cs +++ b/Assets/Script/Audio/Bass/BassMoggStem.cs @@ -120,6 +120,21 @@ public int Load(bool isSpeedUp, float speed) { return 0; } + public void FadeIn() { + double volumeSetting = _manager.GetVolumeSetting(Stem); + + foreach (int channel in BassChannels) { + Bass.ChannelSetAttribute(channel, ChannelAttribute.Volume, 0); + Bass.ChannelSlideAttribute(channel, ChannelAttribute.Volume, (float)volumeSetting, BassHelpers.FADE_TIME_MILLISECONDS); + } + } + + public void FadeOut() { + foreach (int channel in BassChannels) { + Bass.ChannelSlideAttribute(channel, ChannelAttribute.Volume, 0, BassHelpers.FADE_TIME_MILLISECONDS); + } + } + public void SetVolume(double newVolume) { if (!_isLoaded) { return; diff --git a/Assets/Script/Audio/Bass/BassStemChannel.cs b/Assets/Script/Audio/Bass/BassStemChannel.cs index ddee3c223..909c7da22 100644 --- a/Assets/Script/Audio/Bass/BassStemChannel.cs +++ b/Assets/Script/Audio/Bass/BassStemChannel.cs @@ -112,6 +112,16 @@ public int Load(bool isSpeedUp, float speed) { return 0; } + public void FadeIn() { + double volumeSetting = _manager.GetVolumeSetting(Stem); + Bass.ChannelSetAttribute(StreamHandle, ChannelAttribute.Volume, 0); + Bass.ChannelSlideAttribute(StreamHandle, ChannelAttribute.Volume, (float)volumeSetting, BassHelpers.FADE_TIME_MILLISECONDS); + } + + public void FadeOut() { + Bass.ChannelSlideAttribute(StreamHandle, ChannelAttribute.Volume, 0, BassHelpers.FADE_TIME_MILLISECONDS); + } + public void SetVolume(double newVolume) { if (StreamHandle == 0) { return; diff --git a/Assets/Script/Audio/Bass/BassStemMixer.cs b/Assets/Script/Audio/Bass/BassStemMixer.cs index 1224c1c21..5704cdf81 100644 --- a/Assets/Script/Audio/Bass/BassStemMixer.cs +++ b/Assets/Script/Audio/Bass/BassStemMixer.cs @@ -115,6 +115,18 @@ public int Play(bool restart = false) { return 0; } + public void FadeIn() { + foreach (var channel in Channels.Values) { + channel.FadeIn(); + } + } + + public void FadeOut() { + foreach (var channel in Channels.Values) { + channel.FadeOut(); + } + } + public int Pause() { if (!IsPlaying) { return 0; @@ -137,6 +149,19 @@ public double GetPosition() { return LeadChannel.GetPosition(); } + public void SetPosition(double position) { + if (LeadChannel is null) { + return; + } + + foreach (var channel in Channels.Values) { + int handle = ((BassStemChannel)channel).StreamHandle; + + long channelPosition = Bass.ChannelSeconds2Bytes(handle, position); + BassMix.ChannelSetPosition(handle, channelPosition); + } + } + public int AddChannel(IStemChannel channel) { if (channel is not BassStemChannel bassChannel) { throw new ArgumentException("Channel must be of type BassStemChannel"); diff --git a/Assets/Script/Audio/Interfaces/IAudioManager.cs b/Assets/Script/Audio/Interfaces/IAudioManager.cs index 310b98f6e..fb6449e46 100644 --- a/Assets/Script/Audio/Interfaces/IAudioManager.cs +++ b/Assets/Script/Audio/Interfaces/IAudioManager.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using YARG.Serialization; +using YARG.Song; namespace YARG { public interface IAudioManager { @@ -29,8 +30,13 @@ public interface IAudioManager { public void LoadMogg(XboxMoggData moggData, bool isSpeedUp); public void UnloadSong(); + public void LoadPreviewAudio(SongEntry song); + public void Play(); public void Pause(); + + public void FadeIn(); + public void FadeOut(); public void PlaySoundEffect(SfxSample sample); diff --git a/Assets/Script/Audio/Interfaces/IStemChannel.cs b/Assets/Script/Audio/Interfaces/IStemChannel.cs index 2c7db07ce..fbb01d877 100644 --- a/Assets/Script/Audio/Interfaces/IStemChannel.cs +++ b/Assets/Script/Audio/Interfaces/IStemChannel.cs @@ -10,6 +10,9 @@ public interface IStemChannel : IDisposable { public double Volume { get; } public int Load(bool isSpeedUp, float speed); + + public void FadeIn(); + public void FadeOut(); public void SetVolume(double newVolume); diff --git a/Assets/Script/Audio/Interfaces/IStemMixer.cs b/Assets/Script/Audio/Interfaces/IStemMixer.cs index b014e3b58..b1dae226c 100644 --- a/Assets/Script/Audio/Interfaces/IStemMixer.cs +++ b/Assets/Script/Audio/Interfaces/IStemMixer.cs @@ -17,10 +17,15 @@ public interface IStemMixer : IDisposable { public int Play(bool restart = false); + public void FadeIn(); + public void FadeOut(); + public int Pause(); public double GetPosition(); + public void SetPosition(double position); + public int AddChannel(IStemChannel channel); public int AddMoggChannel(IStemChannel channel, IList matrixes);