DmoResampler reports the wrong length of a sound file

Jul 21, 2014 at 2:10 PM
Hello,

I'm using the function SoundOut.WaveSource.GetPosition to get the current position in a playing file, and the function SoundOut.WaveSource.GetLength to get the total length of the file. However it seems GetLength is not always returning the correct total length (sometime a length which is much shorter as the real length is reported. Below is a link to a mp3 file which has a length of 6:52 but is reported only being of length 2:01 by the function GetLength.

Link to mp3 file: https://drive.google.com/file/d/0B-kioOJ2Tg7Sbmo5MHQtampXZ0U/edit?usp=sharing
Coordinator
Jul 21, 2014 at 2:31 PM
Edited Jul 21, 2014 at 2:33 PM
There are currently two decoders which are not marked as obsolete. The DmoMp3Decoder and the Mp3MediafoundationDecoder. If the Mp3MediafoundationDecoder is available on the current platform the CodecFactory class will use the Mp3MediafoundationDecoder. If not it will use the DmoMp3Decoder (which should be also supported on Windows XP).
I don't know which platform you are using, so I've tried out both decoders on Windows 8.1 Prof x64:
    internal class Program
    {
        private static void Main(string[] args)
        {
            const string testfile = @"D:\Temp\issue.mp3";
            using(var dmoDecoder = new DmoMp3Decoder(testfile))
            using (var mediafoundationDecoder = new MediaFoundationDecoder(testfile))
            {
                Console.WriteLine(dmoDecoder.GetLength());
                Console.WriteLine(mediafoundationDecoder.GetLength());
            }

            Console.ReadKey();
        }
    }
The code displays the following results on the console:
00:06:51.4800000
00:06:51.5040000
As you can see there is a difference of about ~2ms. But I really could not reproduce a total length of about 2:01. Which operating system are you using? The MediafoundationDecoder got implemented by microsoft itself. So I can't tell you how they are calculating the length of an mp3 file. The DmoMp3Decoder is also implemented by microsoft but I had to parse the mp3 frames myself. AND I also had to implement the calculation of the length and the position myself. So you may tryout the DmoMp3Decoder since the calculation of the length is purely implemented by cscore. Anyway... I can't imagine that the Mediafoundation is not able to calculate the correct length of an Mp3 file...

So another possibility would be that I've made a mistake by the implementation of other classes which are getting used by source chain. So try out the following code above. If it displays the correct timing, please tell me which other components are you using inside of the source chain.
Jul 21, 2014 at 2:48 PM
Edited Jul 21, 2014 at 3:05 PM
I'm using windows 8.1. When using your code above, the correct length is reported for both DmoMp3Decoder and MediaFoundationDecoder. I'm basically initializing the SoundOut object as follows:
' Contains the sound to play
        Dim soundSource As IWaveSource = CodecFactory.Instance.GetCodec(mPlayingSong)

        ' SoundOut implementation which plays the sound
        mSoundOut = New WasapiOut()

        ' Initialize the soundOut 
        Me.mNotificationSource = New SingleBlockNotificationStream(soundSource)
        Me.mSoundOut.Initialize(Me.mNotificationSource.ToWaveSource(16))

        ' Create the FFT provider
        Me.mFftProvider = New FftProvider(Me.mSoundOut.WaveSource.WaveFormat.Channels, FftSize.Fft2048)

        AddHandler Me.mNotificationSource.SingleBlockRead, AddressOf Me.inputStream_Sample
        AddHandler Me.mSoundOut.Stopped, AddressOf Me.SoundOutStoppedHandler

        Me.mSoundOut.Volume = mVolume
And then getting the length like this:
mSoundOut.WaveSource.GetLength
I'm guessing I'm missing a piece of code to get the correct length? Should I always create an extra DmoMp3Decoder or MediaFoundationDecoder object and use their Getlength function instead of the WaveSource's GetLength?

Edit, to summarize:

mSoundOut.WaveSource.GetLength: reports incorrect length of 2:01 for the mp3 file above
DmoMp3Decoder.GetLength: reports correct length
MediaFoundationDecoder: reports correct length
Coordinator
Jul 21, 2014 at 5:24 PM
Edited Jul 21, 2014 at 6:08 PM
I am sorry. This mistake just should not happen. I've fixed the bug with changeset 2eb8006f3a79. Again I'm sorry ... just bad mistake.
Marked as answer by filoe on 7/24/2014 at 8:55 AM
Jul 21, 2014 at 6:46 PM
No problem. Thanks for fixing it so quickly!

Just wondering, the changes to the WasapiOut class (concerning the nullreference exceptions), are they also already checked in?
Coordinator
Jul 21, 2014 at 10:16 PM
Edited Jul 21, 2014 at 10:17 PM
The unit tests just finished. Both, the WasapiOut and the DirectSoundOut class passed, so I've just commited the changes.