From 97562291efe9b4c021cbf40ba6a96d0793c3a076 Mon Sep 17 00:00:00 2001 From: hwsmm Date: Mon, 30 Oct 2023 21:16:48 +0900 Subject: [PATCH] Fix wrong bytes per sample in TrackBass Waveform will also no longer bring the constant from TrackBass since Waveform still uses float samples. --- osu.Framework/Audio/Track/TrackBass.cs | 12 +++++++++--- osu.Framework/Audio/Track/Waveform.cs | 8 +++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/osu.Framework/Audio/Track/TrackBass.cs b/osu.Framework/Audio/Track/TrackBass.cs index fae4c5427e..05eef247b1 100644 --- a/osu.Framework/Audio/Track/TrackBass.cs +++ b/osu.Framework/Audio/Track/TrackBass.cs @@ -20,8 +20,6 @@ namespace osu.Framework.Audio.Track { public sealed class TrackBass : Track, IBassAudio, IBassAudioChannel { - public const int BYTES_PER_SAMPLE = 4; - private Stream? dataStream; /// @@ -106,14 +104,22 @@ internal TrackBass(Stream data, string name, bool quick = false) // will be -1 in case of an error double seconds = Bass.ChannelBytes2Seconds(activeStream, byteLength); + int channels = 2; + + if (Bass.ChannelGetInfo(activeStream, out ChannelInfo info)) + channels = info.Channels; + bool success = seconds >= 0; if (success) { Length = seconds * 1000; + // Bass uses 16-bit samples by default if neither BassFlags.Byte nor BassFlags.Float is specified + const int bytes_per_sample = 2; + // Bass does not allow seeking to the end of the track, so the last available position is 1 sample before. - lastSeekablePosition = Bass.ChannelBytes2Seconds(activeStream, byteLength - BYTES_PER_SAMPLE) * 1000; + lastSeekablePosition = Bass.ChannelBytes2Seconds(activeStream, byteLength - bytes_per_sample * channels) * 1000; isLoaded = true; diff --git a/osu.Framework/Audio/Track/Waveform.cs b/osu.Framework/Audio/Track/Waveform.cs index 99e3b25b77..957c5138ca 100644 --- a/osu.Framework/Audio/Track/Waveform.cs +++ b/osu.Framework/Audio/Track/Waveform.cs @@ -89,6 +89,8 @@ public Waveform(Stream? data) fileCallbacks = new FileCallbacks(new DataStreamFileProcedures(data)); + const int bytes_per_sample = 4; + int decodeStream = Bass.CreateStream(StreamSystem.NoBuffer, BassFlags.Decode | BassFlags.Float, fileCallbacks.Callbacks, fileCallbacks.Handle); float[]? sampleBuffer = null; @@ -102,7 +104,7 @@ public Waveform(Stream? data) // Each "point" is generated from a number of samples, each sample contains a number of channels int samplesPerPoint = (int)(info.Frequency * resolution * info.Channels); - int bytesPerPoint = samplesPerPoint * TrackBass.BYTES_PER_SAMPLE; + int bytesPerPoint = samplesPerPoint * bytes_per_sample; int pointCount = (int)(length / bytesPerPoint); @@ -111,7 +113,7 @@ public Waveform(Stream? data) // Each iteration pulls in several samples int bytesPerIteration = bytesPerPoint * points_per_iteration; - sampleBuffer = ArrayPool.Shared.Rent(bytesPerIteration / TrackBass.BYTES_PER_SAMPLE); + sampleBuffer = ArrayPool.Shared.Rent(bytesPerIteration / bytes_per_sample); int pointIndex = 0; @@ -119,7 +121,7 @@ public Waveform(Stream? data) while (length > 0) { length = Bass.ChannelGetData(decodeStream, sampleBuffer, bytesPerIteration); - int samplesRead = (int)(length / TrackBass.BYTES_PER_SAMPLE); + int samplesRead = (int)(length / bytes_per_sample); // Each point is composed of multiple samples for (int i = 0; i < samplesRead && pointIndex < pointCount; i += samplesPerPoint)