Search code examples
c#naudio

How to play an exact part of MP3 file between given positions in ms?


(Newbie question)

NAudio allows to start playing an MP3 file from a given position (by converting it from ms into bytes using Waveformat.AverageBytesPerSecond), but is it possible to make it stop playing exactly at another given position (in ms)? Do I have to somehow manipulate the wavestream or there are easier ways?

There is a solution using a Timer simultaneously together with starting playback and stopping playback after the timer ticks, but it doesn't produce reliable results at all.


Solution

  • I'd create a custom IWaveProvider that only returns a maximum of a specified number of bytes from Read. Then reposition your Mp3FileReader to the start, and pass it in to the custom trimming wave provider

    Here's some completely untested example code to give you an idea.

     class TrimWaveProvider
     {
         private readonly IWaveProvider source;
         private int bytesRead;
         private readonly int maxBytesToRead;
    
         public TrimWaveProvider(IWaveProvider source, int maxBytesToRead)
         { 
             this.source = source;
             this.maxBytesToRead = maxBytesToRead;
         }
    
         public WaveFormat WaveFormat { get { return source.WaveFormat; } }
    
         public int Read(byte[] buffer, int offset, int bytesToRead)
         {
             int bytesToReadThisTime = Math.Min(bytesToRead, maxBytesToRead - bytesRead);
             int bytesReadThisTime = source.Read(buffer, offset, bytesToReadThisTime);
             bytesRead += bytesReadThisTime;
             return bytesReadThisTime;
         }
     }
    
     // and call it like this...
     var reader = new Mp3FileReader("myfile.mp3");
     reader.Position = reader.WaveFormat.AverageBytesPerSecond * 3; // start 3 seconds in
     // read 5 seconds
     var trimmer = new TrimWaveProvider(reader, reader.WaveFormat.AverageBytesPerSecond * 5);
     WaveOut waveOut = new WaveOut();
     waveOut.Init(trimmer);