Best strategy to avoid gaps in playing MP3s

Nov 20, 2012 at 5:14 PM

Great API! I am having 2 small problems, I get gaps when the WPF gui I created does a big visual tree rebuild on changing tabs. Once the tab is built the problem goes away. The second problem may be related, but we did a comparison of playing the same mp3 on multiple computers and the playbacks get out of phase and wander up to a second in a 20 minute mp3. This happens if you do the same test using Windows Multimedia player on multiple PCs.

What is the best strategy to avoid audio gaps and try to maintain a consistent play rate? 

Here is how I'm playing the MP3, followed by how its being opened.

		public void Play()
		{
			if (!CanPlay)
				return;

			if (waveOutDevice != null)
			{
				waveOutDevice.Play();
			}

			IsPlaying = true;
			CanPause = true;
			CanPlay = false;
			CanStop = true;
		}

		public bool OpenFile( string path )
		{
			CloseFile();

			if (!System.IO.File.Exists(path))
				return false;

			try
			{
				waveOutDevice = new WaveOut()
				{
					DesiredLatency = 100,
					NumberOfBuffers = 64,
				};
				ActiveStream = new Mp3FileReader(path);

				inputStream = new WaveChannel32(ActiveStream);
				sampleAggregator = new SampleAggregator(4096);
				inputStream.Sample += inputStream_Sample;
				waveOutDevice.Init(inputStream);
				ChannelLength = inputStream.TotalTime.TotalSeconds;
				CanPlay = true;

				GenerateWaveformData(path);

			}
			catch(Exception ex)
			{
				ActiveStream = null;
				CanPlay = false;
				log.ErrorFormat("Can not play wav file {0} - {1}", path, ex.Message);
			}
			return CanPlay;
		}

Thanks for any advice,

 

Neil

Nov 20, 2012 at 6:23 PM

Try changing "waveOutDevice = new WaveOut()" to "waveOutDevice = new WaveOutEvent()".  This will move the decoding to a background thread so your UI updates don't affect the playback.

This should also fix the "de-sync" issue you mentioned.

Coordinator
Nov 20, 2012 at 6:30 PM

also, NumberOfBuffers should not be 64. It should be 2 or at most 3. You're giving the soundcard much more work than it needs by constantly cycling through very short buffers. Pushing latency up also protects more against the chance that a garbage collect could make you miss a buffer refill. 200 or even 300ms might be acceptable for your case.

Nov 20, 2012 at 10:06 PM

The change to WaveOutEvent and setting number of buffers to 2 did the trick.

The latency I need to experiment with, so that it corresponds roughly to the wireless sending of the fire message and ignition of the electrical match and the firing of the fireworks.  It cannot be perfect timing, but its more than good enough when the brain combines the sound  of the music and sight of the pyro. I think I may need to add a slider to advance/delay the pyro cues if the operator thinks the audio is a bit off from the actual firing.

The timing issue became apparent when a broadcaster could not accept our audio feed. We decided on a simple "ready set go" to sync the pyro system with their playing of the mp3 on their computer. We tested it a few times and were surprised how much timing wander between the two systems there was. Tested again using windows media player on both systems and saw the same result. Any ideas why? 

Thanks Again!

Coordinator
Nov 21, 2012 at 6:46 AM

One thing to note about the "latency" is that really I shouldn't have called it latency. It is the total duration of all the buffers. Actual latency is half that if you are working with two buffers (the computer is playing one buffer while it fills the other). Does NAudio lag behind the other PC or get ahead? I know the soundcards on windows PCs can sometimes be running at 48kHz even when they are playing 44.1kHz audio. It does of course do sample rate conversion, but it might account for a small drift perhaps. I don't know what the actual tolerance of audio clocks on soundcards is.

Obviously with fireworks you have the bigger issue with the speed of sound which is much slower than people realise. It is 340m/s, so so moving just a few metres closer to the source of the sound will mean you hear it 30ms earlier. Unless everyone is exactly the same distance from the speakers, they will not experience the same synchronization

Anyway, sounds a really interesting use you are putting NAudio to.

Mark