SFML community forums
Bindings - other languages => DotNet => Topic started by: s.baus on September 05, 2014, 11:56:41 am
-
Hello,
I implemented a SoundStream which can read MP3 Codec via Nlayer (https://nlayer.codeplex.com/ (https://nlayer.codeplex.com/)). It works fine, but sometimes I get a System.IO.EndOfStreamException from NLayer. It appers randomly and the developer is not shure, where it comes from, so I wanted to ask here, if you see any errors in my implementation:
namespace AudioCuesheetEditor
.AudioBackend.SFML{ /// <summary> /// Class for mp3 decoded audio files to use in SFML as Soundstream, since SFML doesn't support mp3 decoding (for legal reasons). /// </summary> public class Mp3StreamSFML
: SoundStream
{ private static readonly Logfile log
= Logfile
.getLogfile(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); private MpegFile mp3file
; private Mutex mutex
; /// <summary> /// Initializes a new instance of the <see cref="AudioCuesheetEditor.AudioBackend.SFML.Mp3StreamSFML"/> class. /// </summary> /// <param name="_filename">Full path to the file</param> public Mp3StreamSFML
(String _filename
) { log
.debug("Constructor called with " + _filename
); this.mp3file = new MpegFile
(_filename
); this.Initialize((uint)this.mp3file.Channels,
(uint)this.mp3file.SampleRate); this.mutex = new Mutex
(); } public TimeSpan Duration
{ get { log
.debug("Duration = " + this.mp3file.Duration); return this.mp3file.Duration; } } #region implemented abstract members of SoundStream protected override bool OnGetData
(out short[] samples
) { log
.debug("OnGetData called"); this.mutex.WaitOne(); //Buffer data for about 1 second float[] normalizedaudiodata
= new float[48000]; int readSamples
= this.mp3file.ReadSamples(normalizedaudiodata,
0, normalizedaudiodata
.Length); short[] pcmaudiodata
; if (readSamples
> 0) { pcmaudiodata
= new short[readSamples
]; // converted data for (int i
= 0; i
< readSamples
; i
++) { // clip the data if (normalizedaudiodata
[i
] > 1
.0f
) { normalizedaudiodata
[i
] = 1
.0f
; } else { if (normalizedaudiodata
[i
] < -1
.0f
) { normalizedaudiodata
[i
] = -1
.0f
; } } // convert to pcm data pcmaudiodata
[i
] = (short)(normalizedaudiodata
[i
] * short.MaxValue); } samples
= pcmaudiodata
; this.mutex.ReleaseMutex(); return true; } else { samples
= null; this.mutex.ReleaseMutex(); return false; } } protected override void OnSeek
(TimeSpan timeOffset
) { log
.debug("OnSeek called with " + timeOffset
); this.mutex.WaitOne(); if ((timeOffset
<= this.mp3file.Duration) && (timeOffset
>= TimeSpan
.Zero)) { while (this.mp3file.CanSeek == false) { Thread
.Sleep(100); } this.mp3file.Time = timeOffset
; } this.mutex.ReleaseMutex(); } #endregion }}
Exception:
16.07.2014 15:47:37 AudioCuesheetEditor.AudioBackend.SFML.Mp3StreamSFML: ERROR | System.IO.EndOfStreamException: Es wurde versucht, über das Ende des Datenstroms hinaus zu lesen.
bei NLayer.Decoder.MpegFrame.ReadBits(Int32 bitCount) in d:\tmp\AudioCuesheetEditor\src\NLayer\Decoder\MpegFrame.cs:Zeile 528.
bei NLayer.Decoder.LayerIIIDecoder.ReadSideInfo(IMpegFrame frame) in d:\tmp\AudioCuesheetEditor\src\NLayer\Decoder\LayerIIIDecoder.cs:Zeile 687.
bei NLayer.Decoder.LayerIIIDecoder.DecodeFrame(IMpegFrame frame, Single[] ch0, Single[] ch1) in d:\tmp\AudioCuesheetEditor\src\NLayer\Decoder\LayerIIIDecoder.cs:Zeile 502.
bei NLayer.MpegFrameDecoder.DecodeFrameImpl(IMpegFrame frame, Array dest, Int32 destOffset) in d:\tmp\AudioCuesheetEditor\src\NLayer\MpegFrameDecoder.cs:Zeile 110.
bei NLayer.MpegFrameDecoder.DecodeFrame(IMpegFrame frame, Single[] dest, Int32 destOffset) in d:\tmp\AudioCuesheetEditor\src\NLayer\MpegFrameDecoder.cs:Zeile 74.
bei NLayer.MpegFile.set_Position(Int64 value) in d:\tmp\AudioCuesheetEditor\src\NLayer\MpegFile.cs:Zeile 92.
bei NLayer.MpegFile.set_Time(TimeSpan value) in d:\tmp\AudioCuesheetEditor\src\NLayer\MpegFile.cs:Zeile 107.
bei AudioCuesheetEditor.AudioBackend.SFML.Mp3StreamSFML.OnSeek(TimeSpan timeOffset) in d:\tmp\AudioCuesheetEditor\src\AudioCuesheetEditor\AudioBackend\SFML\Mp3StreamSFML.cs:Zeile 92.
My code can be found here (for further searching): http://sourceforge.net/p/audiocuesheet/code/HEAD/tree/trunk/ (http://sourceforge.net/p/audiocuesheet/code/HEAD/tree/trunk/)
I'm looking forward to hearing from you ;).
Greets
Sven
-
No one any idea? We are searching for the problem, but have no idea, why it sometimes works, sometimes not :(.
-
It really has nothing to do with SFML... I don't know enough of this other library, but it really sounds like you should be checking if the EOF has been reached before trying to read data.
-
Thanks for your help. But I already check if the seeking is beyond the end of the file.
What I found out, is that it works, if I reset the reference of this.mp3file everytime "OnSeek" is called. But that is a bit bad, to throw the object away everytime. Also the error comes more often if I trigger seeking faster (more times a second) than if I seek just once every ten seconds. Maybe it has something to do with the threads of SFML? I doesn't really know, how the multithreading of SFML works. Any idea?
Thanks for every help.
-
NLayer had a bug with seeking, so the problem was there. Just for your information, everybody having this problem needs to update NLayer ;).