naudio / NLayer

MPEG 1 & 2 Decoder for Layers 1, 2, & 3
MIT License
124 stars 30 forks source link

Array index is out of range #7

Open IanPhilips opened 6 years ago

IanPhilips commented 6 years ago

I'm getting:

Array index is out of range.
NLayer.Decoder.LayerIIIDecoder.Dequantize (Int32 idx, Single val, Int32 gr, Int32 ch)
NLayer.Decoder.LayerIIIDecoder.ReadSamples (Int32 sfBits, Int32 gr, Int32 ch)
NLayer.Decoder.LayerIIIDecoder.DecodeFrame (IMpegFrame frame, System.Single[] ch0, System.Single[] ch1)
NLayer.MpegFrameDecoder.DecodeFrameImpl (IMpegFrame frame, System.Array dest, Int32 destOffset)
NLayer.MpegFrameDecoder.DecodeFrame (IMpegFrame frame, System.Single[] dest, Int32 destOffset)
NLayer.MpegFile.ReadSamplesImpl (System.Array buffer, Int32 index, Int32 count)
NLayer.MpegFile.ReadSamples (System.Single[] buffer, Int32 index, Int32 count)

after loading a mpeg stream into mpegfile and calling read samples with a float[]. I'm not sure what's going on in the dequantize function so I'm at a loss on how to fix this. I'd love your help!

Frooxius commented 6 years ago

I found the same issue, I found that it is tied to seeking (changing the Time/Position property) and then decoding, but tend to be kinda random - seeking directly to problematic position from the beginning won't trigger it.

Most reliable way to reproduce this is seeking backwards and decoding a few hundred/thousand samples forwards. It tends to throw the exception sooner or later. When used in application, I noticed it sometimes doesn't throw an exception, but instead produces silence or glitchy audio.

Here's the code I used to trigger the error:

` var stream = System.IO.File.OpenRead("FILENAME"); var file = new MpegFile(stream);

        Console.WriteLine(file.CanSeek);
        Console.WriteLine(file.SampleRate);
        Console.WriteLine(file.Length);
        Console.WriteLine(file.Time);
        Console.WriteLine(file.StereoMode);
        Console.WriteLine(file.Duration);
        Console.WriteLine(file.Channels);

        var dummyBuffer = new float[4096];

        var r = new Random();

        for(int i = 0; i < 100000; i ++)
        {
            if (file.Position <= 15000)
                file.Time = file.Duration - TimeSpan.FromSeconds(10);

            file.Position -= r.Next(1, 10000);
            var read = file.ReadSamples(dummyBuffer, 0, r.Next(256, dummyBuffer.Length));
        }`
PuneetKohli commented 5 years ago

Was anyone able to find a fix for this?

Dichi13 commented 3 years ago

After toying with the Position getter, it appears that in my case this issue only happens when I tried to seek backward from the "max loaded Position".

For example, if the playback is at Position 10 and I tried to seek to Position 15, it plays fine. But if I take the Position back to anything below 15, the audio starts glitching out (and exceptions are thrown) until the playback gets above 15; in which the audio starts to play fine again.

As for now, my workaround is by disposing the old MpegFile instance and read samples from a new one whenever a backward seek is done to ensure the "max loaded Position" gets reset.

public void SeekTo (long position)
{
   long _position = position * sizeof(float) * mpegFile.Channels;

   if (_position < mpegFile.Position)
   {
      mpegFile.Dispose();
      mpegFile = new MpegFile(filePath);
   }

   mpegFile.Position = _position;
}

Although it's not a really viable solution as it does unneeded operations, but at least it works for my case until this problem is fixed.

wei-kris commented 2 years ago

I found the same issue, It seems to be related to mp3 files.