Sound uploader: split clips play back with clip 2 skipped #1310

Closed
opened 2026-10-30 02:15:01 +00:00 by sky_line · 4 comments
Owner

What happened

I uploaded a long MP3 (about 3 minutes) through the sound uploader. It was split into 30-second clips automatically, and played back in sequence the song has audible jumps: it seems to cut at the wrong points.

Evidence (viewer log, 2026-10-30)

Decode:

llviewermenufile.cpp(538) upload_single_file : Decoded MP3 <file>.mp3: 181.336 s, 48000 Hz, 2 ch

Split and upload (7 parts):

llsoundsplitupload.cpp(178) start : Sound split upload: 7 parts of 'DECO - Monitoring'
llsoundsplitupload.cpp(215) uploadPart : part 1/7 frames 0..1318590
llsoundsplitupload.cpp(215) uploadPart : part 2/7 frames 1318590..2637180
llsoundsplitupload.cpp(215) uploadPart : part 3/7 frames 2637180..3955770
llsoundsplitupload.cpp(215) uploadPart : part 4/7 frames 3955770..5274360
llsoundsplitupload.cpp(215) uploadPart : part 5/7 frames 5274360..6592950
llsoundsplitupload.cpp(215) uploadPart : part 6/7 frames 6592950..7911540
llsoundsplitupload.cpp(215) uploadPart : part 7/7 frames 7911540..7996928
llviewerassetupload.cpp(466) exportTempFile : Encoding decoded audio (1318590 frames) as an ogg file   (once per part)
lltoastalertpanel.cpp(197) : Alert: All 7 clips of DECO - Monitoring were uploaded (L$0 in total).
llviewerassetupload.cpp(878) finishUpload : Inventory item DECO - Monitoring saved into <folder>   (the clip-list notecard)

What the numbers say

  • The source was 48 kHz stereo. It is downmixed to mono and resampled to 44.1 kHz before splitting. 181.336 s x 44100 = 7,996,918, which matches the 7,996,928 total frames, so the resampled length looks right.
  • The planned cuts are contiguous: each part starts exactly where the previous one ended, every 1,318,590 frames (29.9 s at 44.1 kHz). The last part is 85,388 frames (1.94 s).
  • So the split arithmetic in the log is consistent. The jumps must come from somewhere the log doesn't show.

Where to look

  1. Per-part Ogg encoding: each clip is encoded separately. Check the encoder's start and end handling: Vorbis pre-skip and priming samples, and whether the last block of each part gets padded or trimmed. Decode each uploaded clip back and compare its length and its first and last samples with the slice it came from.
  2. The MP3 decode: check for dropped or duplicated frames, encoder delay or padding, and the resampler's edges. Compare the decoded length with the MP3's real duration, and check for discontinuities inside a part (not only at the cuts).
  3. Playback timing: the clips are 29.9 s, not 30 s. Find out what the clip-list notecard tells a player script about each clip's length. Any player that assumes another length will cut each clip early or leave a gap. Also check how the uploader's own preview plays the sequence.

To reproduce

Upload a 3-minute 48 kHz stereo MP3 with the default split settings and play the clips in sequence. Listen at the 29.9 s boundaries and also mid-clip.

## What happened I uploaded a long MP3 (about 3 minutes) through the sound uploader. It was split into 30-second clips automatically, and played back in sequence the song has audible jumps: it seems to cut at the wrong points. ## Evidence (viewer log, 2026-10-30) Decode: ``` llviewermenufile.cpp(538) upload_single_file : Decoded MP3 <file>.mp3: 181.336 s, 48000 Hz, 2 ch ``` Split and upload (7 parts): ``` llsoundsplitupload.cpp(178) start : Sound split upload: 7 parts of 'DECO - Monitoring' llsoundsplitupload.cpp(215) uploadPart : part 1/7 frames 0..1318590 llsoundsplitupload.cpp(215) uploadPart : part 2/7 frames 1318590..2637180 llsoundsplitupload.cpp(215) uploadPart : part 3/7 frames 2637180..3955770 llsoundsplitupload.cpp(215) uploadPart : part 4/7 frames 3955770..5274360 llsoundsplitupload.cpp(215) uploadPart : part 5/7 frames 5274360..6592950 llsoundsplitupload.cpp(215) uploadPart : part 6/7 frames 6592950..7911540 llsoundsplitupload.cpp(215) uploadPart : part 7/7 frames 7911540..7996928 llviewerassetupload.cpp(466) exportTempFile : Encoding decoded audio (1318590 frames) as an ogg file (once per part) lltoastalertpanel.cpp(197) : Alert: All 7 clips of DECO - Monitoring were uploaded (L$0 in total). llviewerassetupload.cpp(878) finishUpload : Inventory item DECO - Monitoring saved into <folder> (the clip-list notecard) ``` ## What the numbers say - The source was 48 kHz stereo. It is downmixed to mono and resampled to 44.1 kHz before splitting. 181.336 s x 44100 = 7,996,918, which matches the 7,996,928 total frames, so the resampled length looks right. - The planned cuts are contiguous: each part starts exactly where the previous one ended, every 1,318,590 frames (29.9 s at 44.1 kHz). The last part is 85,388 frames (1.94 s). - So the split arithmetic in the log is consistent. The jumps must come from somewhere the log doesn't show. ## Where to look 1. **Per-part Ogg encoding:** each clip is encoded separately. Check the encoder's start and end handling: Vorbis pre-skip and priming samples, and whether the last block of each part gets padded or trimmed. Decode each uploaded clip back and compare its length and its first and last samples with the slice it came from. 2. **The MP3 decode:** check for dropped or duplicated frames, encoder delay or padding, and the resampler's edges. Compare the decoded length with the MP3's real duration, and check for discontinuities inside a part (not only at the cuts). 3. **Playback timing:** the clips are 29.9 s, not 30 s. Find out what the clip-list notecard tells a player script about each clip's length. Any player that assumes another length will cut each clip early or leave a gap. Also check how the uploader's own preview plays the sequence. ## To reproduce Upload a 3-minute 48 kHz stereo MP3 with the default split settings and play the clips in sequence. Listen at the 29.9 s boundaries and also mid-clip.
sky_line added this to the Slipstream project 2026-10-30 02:15:01 +00:00
Author
Owner

More detail from the reporter: the jumps are at clip boundaries only, but not at every boundary. The jump from clip 1 to clip 2 is the most noticeable.

That points away from the split itself: the cuts are evenly spaced and back to back, so a split or encoding error would show at every boundary alike. The causes that fit "some boundaries, worst at the first one":

  • The next clip isn't ready when the current one ends. Clip 2 is the first clip that has to be fetched and decoded while something else is playing. If playback starts it late, or starts it from wherever the timeline has reached by then, that sounds like a jump. Later clips may already be cached by the time they're needed.
  • Timing drift in the player: each handoff is scheduled from a timer, not from the end of the previous clip, so some boundaries land early and some late.
  • Content: a sample-level discontinuity is only audible on loud or tonal passages, so the same small error can be inaudible at quiet boundaries.

Suggested check: play the uploaded clips back to back locally, from a decoded copy with no network or timing involved. If the boundaries are clean there, the problem is in playback or preloading, not in the uploader.

More detail from the reporter: the jumps are at clip boundaries only, but **not at every boundary**. The jump from clip 1 to clip 2 is the most noticeable. That points away from the split itself: the cuts are evenly spaced and back to back, so a split or encoding error would show at every boundary alike. The causes that fit "some boundaries, worst at the first one": - **The next clip isn't ready when the current one ends.** Clip 2 is the first clip that has to be fetched and decoded while something else is playing. If playback starts it late, or starts it from wherever the timeline has reached by then, that sounds like a jump. Later clips may already be cached by the time they're needed. - **Timing drift in the player:** each handoff is scheduled from a timer, not from the end of the previous clip, so some boundaries land early and some late. - **Content:** a sample-level discontinuity is only audible on loud or tonal passages, so the same small error can be inaudible at quiet boundaries. Suggested check: play the uploaded clips back to back locally, from a decoded copy with no network or timing involved. If the boundaries are clean there, the problem is in playback or preloading, not in the uploader.
Author
Owner

Found by the reporter: this isn't a playback-timing problem. The audio for segment 2 is missing from the uploaded clips. All 7 clips uploaded and are named _01 to _07, but the clip named _02 contains what should be segment 3's audio (29.9-59.8 s of the source).

What the log shows for part 2: the planned frames are correct (1318590..2637180); it encoded 1,318,590 frames; it uploaded as its own asset (15309430-…) with the right name; and each part waited for the previous upload's server reply before starting. So the plan, the names and the ordering are right in the log, and the wrong content comes in somewhere between taking that slice of the decoded audio and the asset the server stores. Places to check:

  • the encode reads mSamples.data() + mAudioClipStart from the shared decoded clip: check that each upload object still holds its own start offset when the encode actually runs;
  • the temporary Ogg file and the local cache entry for each part: check whether one part's encoded file can be picked up by another part's upload or cache rename;
  • decode each uploaded asset back and compare it with the source slices, to find which slice each clip really holds, and whether segment 3 appears twice or every clip after the first is shifted.
**Found by the reporter:** this isn't a playback-timing problem. The audio for segment 2 is missing from the uploaded clips. All 7 clips uploaded and are named `_01` to `_07`, but the clip named `_02` contains what should be segment 3's audio (29.9-59.8 s of the source). What the log shows for part 2: the planned frames are correct (`1318590..2637180`); it encoded 1,318,590 frames; it uploaded as its own asset (`15309430-…`) with the right name; and each part waited for the previous upload's server reply before starting. So the plan, the names and the ordering are right in the log, and the wrong content comes in somewhere between taking that slice of the decoded audio and the asset the server stores. Places to check: - the encode reads `mSamples.data() + mAudioClipStart` from the shared decoded clip: check that each upload object still holds its own start offset when the encode actually runs; - the temporary Ogg file and the local cache entry for each part: check whether one part's encoded file can be picked up by another part's upload or cache rename; - decode each uploaded asset back and compare it with the source slices, to find which slice each clip really holds, and whether segment 3 appears twice or every clip after the first is shifted.
sky_line changed title from Sound uploader: long files split into clips play back with jumps to Sound uploader: split upload of a long file loses segment 2 (clip _02 holds segment 3) 2026-10-30 02:19:48 +00:00
Author
Owner

Correction: the upload is fine, and playback skips clip 2.

I matched the decoded clips in the reporter's local sound cache against the source song (cross-correlation on a 0.5 s window from the middle of each clip):

Decoded at Length Matches song at Correlation
22:10:01 29.90 s 0.00 s (segment 1) 0.991
22:10:32 29.90 s 59.80 s (segment 3) 0.990
22:10:32 29.90 s 89.70 s (segment 4) 0.985
22:11:02 29.90 s 119.60 s (segment 5) 0.970
22:11:32 29.90 s 149.50 s (segment 6) 0.981
22:18:27 29.90 s 29.90 s (segment 2) 0.978
  • Segment 2 exists as its own asset with the correct audio. It was only decoded at 22:18, about 8 minutes after the sequence played.
  • During the playback (22:10-22:11) the player went from segment 1 straight to segment 3, preloading the next clip each time. So the list of sounds the player used had segment 3 in position 2.
  • So the slicing, encoding and upload are correct, and the bug is in the order or content of what playback was given. Next step: check where that list came from (the uploader's "copy UUIDs as an LSL list" output, the notecard written after the upload, or the script's inventory order), and check which asset ID each _0N inventory item and each list entry actually points to.
**Correction: the upload is fine, and playback skips clip 2.** I matched the decoded clips in the reporter's local sound cache against the source song (cross-correlation on a 0.5 s window from the middle of each clip): | Decoded at | Length | Matches song at | Correlation | |---|---|---|---| | 22:10:01 | 29.90 s | 0.00 s (segment 1) | 0.991 | | 22:10:32 | 29.90 s | 59.80 s (segment 3) | 0.990 | | 22:10:32 | 29.90 s | 89.70 s (segment 4) | 0.985 | | 22:11:02 | 29.90 s | 119.60 s (segment 5) | 0.970 | | 22:11:32 | 29.90 s | 149.50 s (segment 6) | 0.981 | | 22:18:27 | 29.90 s | **29.90 s (segment 2)** | 0.978 | - Segment 2 exists as its own asset with the correct audio. It was only decoded at 22:18, about 8 minutes after the sequence played. - During the playback (22:10-22:11) the player went from segment 1 straight to segment 3, preloading the next clip each time. So the list of sounds the player used had segment 3 in position 2. - So the slicing, encoding and upload are correct, and the bug is in the order or content of what playback was given. Next step: check where that list came from (the uploader's "copy UUIDs as an LSL list" output, the notecard written after the upload, or the script's inventory order), and check which asset ID each `_0N` inventory item and each list entry actually points to.
sky_line changed title from Sound uploader: split upload of a long file loses segment 2 (clip _02 holds segment 3) to Sound uploader: split clips play back with clip 2 skipped 2026-10-30 02:24:46 +00:00
Author
Owner

Closing: not a viewer bug. The viewer uploaded all 7 clips correctly (verified against the source above). The clips were dropped by the external player's song database: its stored clip list had segments 2 and 3 missing after an overwrite. That has been fixed on the player's side.

Closing: not a viewer bug. The viewer uploaded all 7 clips correctly (verified against the source above). The clips were dropped by the external player's song database: its stored clip list had segments 2 and 3 missing after an overwrite. That has been fixed on the player's side.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
sky_line/Slipstream#1310
No description provided.