Search Issue Tracker
By Design
Votes
1
Found in
2022.3.52f1
6000.0.28f1
6000.1.0a5
6000.2.0a1
6000.3.0a1
Issue ID
UUM-87265
Regression
No
.mp3 playback position is inaccurate when loaded with .streamAudio while in Play Mode
Reproduction steps:
1. Open the attached “UUM-87265“ project
2. Open the “Assets/Scenes/SampleScene.unity“ Scene
3. Enter the Play Mode
4. Press the “Start Audio OK“ button and listen to the audio
5. Press the “Stop Audio“ button
6. Press the “Start Audio Broken“ button and listen to the audio
Expected result: Audio started by both buttons sounds identical as the playback position is the same
Actual result: Audio started by the “Start Audio Broken“ button has a different starting position
Reproducible with: 2021.3.46f1, 2022.3.52f1, 6000.0.28f1, 6000.1.0a5
Reproducible on: Windows 10 (22H2), MacOS 15.1
Not reproducible on: No other environments tested
Note: Reproducible in Player
Add comment
All about bugs
View bugs we have successfully reproduced, and vote for the bugs you want to see fixed most urgently.
Latest issues
- Shadows are not visible in Player when using DX12 with Forward+ or Deferred+ rendering in URP
- Rendering Debugger Playmode debug UI scrolling is jittery when using click and drag to scroll
- Frame Debugger Target Selection Search Results window becomes too tiny to even see the default “Editor” selection when there are no search results
- Element name field has no character limit in UI Builder
- Async method in Play Mode being aborted when calling `new System.Windows.Forms.Form`
Resolution Note:
The audio seeking was bad because the provided mp3 test file had no seek table embedded.
# Explanation
## 1. MP3 seeking
MP3 files are notoriously bad at seeking and looping. The reason for this is rooted in the notion that audio samples are grouped in frames (think "packet") and while these frames are identical in binary size they contain a different count of samples, due to variable bit rates and compression techniques. Consequently, with simple MP3 files you cannot seek precisely to a specific sample or time. You can only estimate a position based on the size of the file and seek to the beginning of the closest frame, which will frequently lead around the desired position, likely with a gap in the order of a few seconds.
To improve on that, a seek table (historically called Xing table) can be embedded in MP3 files, and acts as a table of content allowing to target much more accurately the desired position.
Unity happens to support this, and if we add a seek table to the file provided in the bug repro, it seeks as precisely as the OGG file does. This can easily be done with FFMPEG.
## 2. Issue only happening when streaming audio
In the bug repro, the audio files are loaded via WebRequest. They are downloaded from a remote or local source, decoded on the fly and made available as an AudioClip. The download handler has an option allowing the streaming of the audio (for faster playback start and lower memory footprint, at the cost of more CPU).
In the scenario where the audio file it fetched without streaming, the binary file is completely downloaded, fully read and decompressed with the MP3 codec. Then when seeking happens, all the audio samples are already decoded and available, so the audio file can be seeked as a PCM array with a basic DSP, with an almost-sample-perfect precision.
In the scenario where the audio file it fetched with streaming enabled, the binary file is downloaded a few kB at the time, partially read and decoded by the MP3 codec. When the seeking operation happens, if no seek table was available in the file header when the streaming started, it will have no choice to approximate the seeking position based on the file size, download that file chunk and start reading from there. If a seek table is available, then it will detect it when starting the file streaming and be able to know what binary offset to look for to make the better choice of chunk to download.