Specified argument was out of the range of valid values. Parameter name: offset

Feb 7, 2014 at 5:26 PM
Edited Feb 8, 2014 at 9:10 PM
Hello,

I'm building my own media player using NAudio for mp3 support and NVorbis for ogg vorbis support. I'm experiencing issues to play some ogg files.

When executing the line
Me.mInputStream = New WaveChannel32(Me.ActiveStream)
in the code below, I get this exception:

Specified argument was out of the range of valid values. Parameter name: offset.

Here is the stacktrace:
   at NVorbis.StreamReadBuffer.Read(Int64 offset, Byte[] buffer, Int32 index, Int32 count)
   at NVorbis.BufferedReadStream.Read(Byte[] buffer, Int32 offset, Int32 count)
   at NVorbis.Ogg.ContainerReader.ReadPageHeader(Int64 position)
   at NVorbis.Ogg.ContainerReader.FindNextPageHeader()
   at NVorbis.Ogg.ContainerReader.GatherNextPage()
   at NVorbis.Ogg.ContainerReader.GatherNextPage(Int32 streamSerial, PageReaderLock pageLock)
   at NVorbis.Ogg.PacketReader.ReadAllPages()
   at NVorbis.Ogg.PacketReader.GetLastPacket()
   at NVorbis.Ogg.PacketReader.GetGranuleCount()
   at NVorbis.VorbisStreamDecoder.GetLastGranulePos()
   at NVorbis.VorbisReader.get_TotalTime()
   at NVorbis.NAudioSupport.VorbisWaveReader.get_Length()
   at NAudio.Wave.WaveChannel32..ctor(WaveStream sourceStream, Single volume, Single pan)
   at NAudio.Wave.WaveChannel32..ctor(WaveStream sourceStream)
   at RaphaelGodart.musiX.NAudioPlayer.CreateInputStream(String fileName) in C:\Users\Raphaël\Documents\Visual Studio 2013\Projects\QuickPlay\Dev\RaphaelGodart.QuickPlay\RaphaelGodart.QuickPlay\Classes\NAudioPlayer.vb:line 215
   at RaphaelGodart.musiX.NAudioPlayer.Play(String iPath) in C:\Users\Raphaël\Documents\Visual Studio 2013\Projects\QuickPlay\Dev\RaphaelGodart.QuickPlay\RaphaelGodart.QuickPlay\Classes\NAudioPlayer.vb:line 176
   at RaphaelGodart.musiX.MainWindowViewModel.PlayAction(SongViewModel iSong, Boolean iPlayNext) in C:\Users\Raphaël\Documents\Visual Studio 2013\Projects\QuickPlay\Dev\RaphaelGodart.QuickPlay
Here is the function in which the exception occurs:
Private Function CreateInputStream(fileName As String) As WaveStream

        If fileName.EndsWith(".mp3") Then
            'Me.ActiveStream = New Mp3FileReader(fileName)
            Me.ActiveStream = New Mp3FileReader(GetMemoryStream(fileName))
        ElseIf fileName.EndsWith(".ogg") Then
            Me.ActiveStream = New VorbisWaveReader(GetMemoryStream(fileName))
        Else
            Throw New InvalidOperationException("Unsupported extension")
        End If

        Me.mInputStream = New WaveChannel32(Me.ActiveStream)
        mSampleAggregator = New SampleAggregator(mFftDataSize)
        AddHandler Me.mInputStream.Sample, AddressOf Me.inputStream_Sample
        Me.mVolumeStream = Me.mInputStream

        Me.mVolumeStream.Volume = mVolume

        Return Me.mVolumeStream
    End Function
GetMemoryStream() is a function which returns a memorystream based on the audio file bytes. The exception above occurs even if I directly provide the path to the ogg file in the VorbisWaveReader constructor.

Any ideas what could be causing this? Or how I could track the cause?

It doesn't happen for all ogg files. Some of them play fine.

Thank you.
Coordinator
Feb 10, 2014 at 12:23 AM
Just curious... Why are you pre-buffering the file in memory? I don't expect that to be part of the issue, though...

The issue you are seeing is possibly due to a miscalculation in the buffering logic... Feel free to debug it, but 8.x has a new buffering layer that still has bugs... I'll try to get to it soon, but my real job has me pretty tied up for a good long while.
Coordinator
Feb 19, 2014 at 3:35 PM
I had some time this morning to debug this, and basically ended up rewriting the buffering logic... It's a lot simpler than before :)

Please try doing a custom build from source and replace the contents of StreamReadBuffer.cs with this: http://pastebin.com/xk2gxZPu. I'm not going to check that in yet, but I think it should fix all the weird little quirks in the buffering layer.

Let me know how it goes...
Coordinator
Feb 25, 2014 at 2:29 AM
I went ahead and released this. If you have any other issues, please post them.
Feb 28, 2014 at 8:36 AM
Thank you very much!

I'd didn't get the chance yet to try your changes, but I should be able to test it this weekend with the files causing the problem. I'll let you know how it went.
Mar 1, 2014 at 9:00 AM
Edited Mar 1, 2014 at 9:19 AM
I tried version 0.8.1, but I'm still getting the exception. I then downloaded the source and integrated the NVorbis solution into my project for debugging.

I'm getting the ArgumentOutOfRangeException on offset.

Read(...) is called multiple times until the value for offset below is reached. Then the exception is thrown:

offset = 15372304
_wrapper.EofOffset = 15372304
public int Read(long offset, byte[] buffer, int index, int count)
        {
            if (offset < 0L || offset >= _wrapper.EofOffset) throw new ArgumentOutOfRangeException("offset");
           ...
        }
Coordinator
Mar 3, 2014 at 4:59 PM
Darnit! I thought I had this one nailed... Any chance you can send a code sample that exhibits the bug?
Mar 3, 2014 at 7:03 PM
Edited Mar 3, 2014 at 7:03 PM
Sure. I've put together a small solution with test ogg file which reproduces the bug. You can download it here: https://onedrive.live.com/?cid=366a692eaa292a28&id=366A692EAA292A28!20989&ithint=file,.zip&authkey=!ANItYa0OhlBI6Kw
Coordinator
Mar 3, 2014 at 8:16 PM
Your file ends without indicating the end of the logical Vorbis stream. That would typically indicate a truncated file. Either way, NVorbis was choking on the unexpected EOF, so I've checked in a change that just gracefully ends the stream instead. Give it a shot?
Mar 3, 2014 at 9:39 PM
I've tested your last checkin. I'm not getting the ArgumentOutOfRangeException anymore, but there's no sound when the file is playing. It is reporting progress though. I've updated the sample with your latest code and simple progress reporting and skipping (after 10 seconds playing) in the console. Skipping causes the application to hang for several seconds, then after hanging it finally skips to the selected seconds but there is still no sound.

https://onedrive.live.com/redir?resid=366A692EAA292A28!20990&authkey=!AIGgdcaTPJEygA0&ithint=file%2c.zip
Coordinator
Mar 3, 2014 at 10:37 PM
Edited Mar 3, 2014 at 10:39 PM
Replace the dll file in $(SolutionDir)/bin with a new build from the NVorbis code in your solution and I believe you'll find that it corrects the issue. I deleted it outright and your code is working for me.
Coordinator
Mar 3, 2014 at 10:43 PM
Strike that, you'll need to update to latest source... There's a small glitch in the packet reader that I introduced in the last commit that is causing it to quit reading more packets almost immediately.

Now, it should work. :)
Mar 4, 2014 at 7:12 AM
Edited Mar 4, 2014 at 7:36 AM
Great thanks! The problematic songs now all play. Skipping is still a problem though. Depending how far into the song we are, sometimes skipping works fast, sometimes it locks the application for multiple seconds before actually skipping. You can reproduce this with sample2 from yesterday by forcing to skip after 5 seconds instead of 10 (skipping after 10 seconds seems to work fine).

Edit: I've updated the sample (now sample3). It reproduces the skipping problem as is: https://onedrive.live.com/redir?resid=366A692EAA292A28!20991&authkey=!ALZd769uzLVM0Uc&ithint=file%2c.zip
Coordinator
Mar 4, 2014 at 12:00 PM
Can you use pastebin to upload just NVorbisPlayer.vb (and Module1.vb if necessary)? Downloading all the binaries over and over seems like a waste... :)

Looking at sample 2, I can get almost instant seeks if I stop playback before seeking. In Sub Skip(Integer), call mWaveOutDevice.[Stop], seek the input stream, then call mWaveOutDevice.Play().

On a related note, I haven't done much with ensuring VorbisReader is threadsafe... You may be running into some contention issues due to that.
Mar 4, 2014 at 5:02 PM
No problem for using pastebin in the future.
I added mWaveOutDevice.[Stop] and mWaveOutDevice.Play() to the Skip() method (like below), but it didn't fix the issue.
Public Sub Skip(iGotoSeconds As Integer)

        If Me.CanSkip Then
            Try
                mWaveOutDevice.[Stop]()
                Me.ActiveStream.CurrentTime = New TimeSpan(0, 0, iGotoSeconds)
                mWaveOutDevice.Play()
            Catch ex As Exception

            End Try
        End If
    End Sub
Might indeed be a threading issue...
Coordinator
Mar 5, 2014 at 12:30 PM
I spent some time looking at this (and a couple other things) last night, and you might try latest source. I have it working with your test app with nearly instant short seeks while still playing back (no stop/restart).

If it's working well for you, I think I'll make this v0.8.2.
Mar 5, 2014 at 1:10 PM
Edited Mar 5, 2014 at 1:11 PM
I've compiled nvorbis.dll from the latest code and immediately integrated it in my full app (it has a seek bar which allows seeking to any location in the file). Seeking works perfectly with this version (with all the "bad" ogg files I have here).

Thanks a lot for looking into this!