Zeugma440 / atldotnet

Fully managed, portable and easy-to-use C# library to read and edit audio data and metadata (tags) from various audio formats, playlists and CUE sheets
MIT License
459 stars 61 forks source link

Index out of bounds while processing vorbistag chapters that start at index 0 #180

Closed itzexor closed 1 year ago

itzexor commented 1 year ago

Hello, I'm the reporter from the other issue you were talking to @sandreas about recently. During my work in figuring out what the general behavior should be with those kind of files, I found that ffmpeg automatically rearranges any vorbis chapter metadata that it finds so that it starts at index 0.

Once I tested transforming my file with ffmpeg in order to see what it decided to do with the "out of bounds" chapter data, it no longer worked with tone. I started getting this backtrace:

Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index')

   at System.Collections.Generic.List`1.get_Item(Int32 index)
   at ATL.AudioData.IO.VorbisTag.setChapter(String fieldName, String fieldValue)
   at ATL.AudioData.IO.VorbisTag.read(BinaryReader source, ReadTagParams readTagParams)
   at ATL.AudioData.IO.Ogg.readCommentPacket(BinaryReader source, Int32 contentType, VorbisTag tag, ReadTagParams readTagParams)
   at ATL.AudioData.IO.Ogg.getInfo(BufferedBinaryReader source, FileInfo info, ReadTagParams readTagParams)
   at ATL.AudioData.IO.Ogg.Read(BinaryReader source, ReadTagParams readTagParams)
   at ATL.AudioData.IO.Ogg.Read(BinaryReader source, SizeInfo sizeInfo, ReadTagParams readTagParams)
   at ATL.AudioData.AudioDataManager.read(BinaryReader source, ReadTagParams readTagParams)
   at ATL.AudioData.AudioDataManager.read(BinaryReader source, Boolean readEmbeddedPictures, Boolean readAllMetaFrames, Boolean prepareForWriting)
   at ATL.AudioData.AudioDataManager.ReadFromFile(Boolean readEmbeddedPictures, Boolean readAllMetaFrames)

── /home/exor/Desktop/no_sound_test_000_chapter.opus ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index')

   at System.Collections.Generic.List`1.get_Item(Int32 index)
   at ATL.AudioData.IO.VorbisTag.setChapter(String fieldName, String fieldValue)
   at ATL.AudioData.IO.VorbisTag.read(BinaryReader source, ReadTagParams readTagParams)
   at ATL.AudioData.IO.Ogg.readCommentPacket(BinaryReader source, Int32 contentType, VorbisTag tag, ReadTagParams readTagParams)
   at ATL.AudioData.IO.Ogg.getInfo(BufferedBinaryReader source, FileInfo info, ReadTagParams readTagParams)
   at ATL.AudioData.IO.Ogg.Read(BinaryReader source, ReadTagParams readTagParams)
   at ATL.AudioData.IO.Ogg.Read(BinaryReader source, SizeInfo sizeInfo, ReadTagParams readTagParams)
   at ATL.AudioData.AudioDataManager.read(BinaryReader source, ReadTagParams readTagParams)
   at ATL.AudioData.AudioDataManager.read(BinaryReader source, Boolean readEmbeddedPictures, Boolean readAllMetaFrames, Boolean prepareForWriting)
   at ATL.AudioData.AudioDataManager.ReadFromFile(Boolean readEmbeddedPictures, Boolean readAllMetaFrames)

            properties             
┌───────────────────┬─────────────┐
│            format │ Unknown:    │
│          channels │ 0 (Unknown) │
│     1 meta format │ Unknown     │
└───────────────────┴─────────────┘
                    metadata                     
┌───────────────────┬───────────────────────────┐
│             title │ no_sound_test_000_chapter │
└───────────────────┴───────────────────────────┘

The output shown above is from a super basic file I crafted for the test using this command with opusenc: $ opusenc --comment CHAPTER000=00:00:00.000 --comment CHAPTER000NAME="Chapter 1" --comment CHAPTER001=00:00:07.000 --comment CHAPTER001NAME="Chapter 2" no_sound_test.wav no_sound_test_000_chapter.opus

however changing that command to simply use chapter001 and chapter002 instead works fine:

── /home/exor/Desktop/no_sound_test_001_chapter.opus ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

                 properties                  
┌───────────────────┬───────────────────────┐
│            format │ OGG (Opus): audio/ogg │
│           bitrate │ 102                   │
│       sample-rate │ 48000                 │
│          duration │ 00:00:14.809          │
│               vbr │ True                  │
│          channels │ 2 (Stereo (2/0.0))    │
│     1 meta format │ Native / Vorbis (OGG) │
└───────────────────┴───────────────────────┘
                    metadata                     
┌───────────────────┬───────────────────────────┐
│             title │ no_sound_test_001_chapter │
└───────────────────┴───────────────────────────┘
              additional metadata fields               
┌───────────────────┬─────────────────────────────────┐
│     VORBIS-VENDOR │ libopus 1.3.1, libopusenc 0.2.1 │
└───────────────────┴─────────────────────────────────┘
            chapters             
┌───────────────────┬───────────┐
│      00:00:00.000 │ Chapter 1 │
│      00:00:07.000 │ Chapter 2 │
└───────────────────┴───────────┘

That page I referenced in the other issue (https://wiki.xiph.org/Chapter_Extension) shows their example starting at index 1: CHAPTER001=00:00:00.000 and this is the format I've been putting into my files the whole time so I hadn't noticed. After encountering this issue, and going back to that page, I see it does specify the range as index 000-999.

I guess maybe atl is expecting that vorbistag chapters start at index 1 or something? To be extra clear this is occurring in as far as I can tell completely valid ogg opus files, I haven't done any weird chapter length trickery to these test files.

Here's the wav and the resulting file if you need them: no_sound_test.zip

Zeugma440 commented 1 year ago

Hi and thanks for the detailed report 👍

I found the issue and wrote a more robust piece of code to handle Vorbis chapters. ATL was indeed expecting 1-indexed chapters only.

The fix will be available with next release.

Zeugma440 commented 1 year ago

Fix available in today's v4.18