LSXPrime / LSXPrime/SoundFlow

[PERF] MP3 seeking gets progressively slower in long files with MiniAudio-backed decoder.

Open
#115 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C#
Stars
512
Forks
56
PR merge metrics
No merged PRs in 30d

Description

### 1. Describe the Performance Issue

Seeking within long MP3 files appears to become progressively slower as the target position gets later in the file when using SoundFlow's built-in MiniAudio MP3 decoder path. I have not verified whether the issue exists when using the FFMPEG module.

### 2. Area of the Library Affected

The suspected culprit is:

SoundFlow’s built-in MiniAudio-backed MP3 decoder seek path, specifically:
`StreamDataProvider.Seek(...)`
→ `MiniAudioDecoder.Seek(...)`
→ `ma_decoder_seek_to_pcm_frame(...)`

### 3. Scenario Causing Slowness

Seeking within long MP3 files appears to become progressively slower as the target position gets later in the file when using SoundFlow's built-in MiniAudio MP3 decoder path.

In my app, Auzi, playback is using SoundFlow `1.4.1`. Auzi delegates seeking directly to SoundFlow, and the slowdown appears to happen inside the MiniAudio decoder seek call rather than in the app's own playback layer.

### 4. Expected Performance

Seeking to an arbitrary position in a long MP3 should be roughly bounded and should not scale linearly with the target timestamp, at least when the input stream is seekable.

### 5. Actual Performance

For a long MP3 file, seeks near the beginning complete quickly, but seeks later in the file take much longer.

Example timings from the same file:

| Target position | Seek time |
| --- | ---: |
| 00:00:30 | `21 ms` |
| 00:10:00 | `391 ms` |
| 00:30:00 | `809 ms` |
| 01:00:00 | `1210 ms` |
| 02:00:00 | `2421 ms` |

This makes timeline scrubbing feel increasingly delayed on long MP3s.

### 6. Minimal Reproducible Example (MRE) (Highly Recommended)

```csharp
A minimal repro should be possible with a long seekable MP3 file:

using System.Diagnostics;
using SoundFlow.Backends.MiniAudio;
using SoundFlow.Providers;
using SoundFlow.Structs;

using var engine = new MiniAudioEngine();

using var stream = File.OpenRead(args[0]);
using var provider = new StreamDataProvider(engine, AudioFormat.DvdHq, stream);

var formatInfo =
provider.FormatInfo
?? throw new InvalidOperationException(
"Stream data provider did not report audio format information."
);

foreach (var seconds in new[] { 30, 600, 1800, 3600, 7200 })
{
var sampleOffset = checked(seconds * provider.SampleRate * formatInfo.ChannelCount);

var sw = Stopwatch.StartNew();
provider.Seek(sampleOffset);
sw.Stop();

Console.WriteLine($"{TimeSpan.FromSeconds(seconds)}: {sw.ElapsedMilliseconds} ms");
}
```

### 7. Profiling Data (if available)

```markdown

```

### SoundFlow Version

1.4.1

### .NET Version

.NET 10

### Operating System

Windows 11, macOS Tahoe, Ubuntu 25.10

### Architecture

Windows and Ubuntu (x64), macOS (ARM64)

### Audio Backend Used (if known)

MiniAudioEngine usage varies by OS.

### Specific Audio Hardware (if relevant)

_No response_

### Audio Buffer Size / Sample Rate

_No response_

### 9. Additional Context

_No response_

### Requirements Checklist

- [x] I have searched the existing issues to ensure this performance issue has not already been reported.
- [x] I have provided a clear description of the issue and the scenario.
- [x] I have included performance metrics if possible.
- [x] I have considered providing an MRE.
- [x] I have completed the environment information.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the timings with the long seekable MP3 example, then trace StreamDataProvider.Seek(...) through MiniAudioDecoder.Seek(...) to ma_decoder_seek_to_pcm_frame(...). Compare the built-in MiniAudio path with FFMPEG if available. Done means later seeks no longer show the reported progressive slowdown, with measurements covering the listed target positions.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
performance
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.