When you play audio or render audio to a file, you create a single ISampleProvider
or IWaveProvider
that represents the whole piece of audio to be played. So playback will continue until you reach the end, and then stop.
But what if you have two pieces of audio you want to play back to back? The ConcatenatingSampleProvider
enables you to schedule one or more pieces of audio to play one after the other.
Here's a simple example where we have three audio files that are going to play back to back. Note that the three audio files must have exactly the same sample rate, channel count and bit depth, because it's not possible to change those during playback.
var first = new AudioFileReader("first.mp3");
var second = new AudioFileReader("second.mp3");
var third = new AudioFileReader("third.mp3");
var playlist = new ConcatenatingSampleProvider(new[] { first, second, third });)
// to play:
outputDevice.Init(playlist);
outputDevice.Play();
// ... OR ... to save to file
WaveFileWriter.CreateWaveFile16("playlist.wav", playlist);
Note that the ConcatenatingSampleProvider
does not provide repositioning. If you want that, you can quite simply copy the code for ConcatenatingSampleProvider
and adjust it to allow you to rewind, or jump to the beginning of one of the inputs, depending on your specific requirements.
There are some helpful extension methods you can make use of to simplify concatenating. For example, to append one ISampleProvider
onto the end of another, use FollowedBy
. Under the hood this simply creates a ConcatenatingSampleProvider
:
var first = new AudioFileReader("first.mp3");
var second = new AudioFileReader("second.mp3");
var playlist = first.FollowedBy(second);
You can also provide a duration of silence that you want after the first sound has finished and before the second begins:
var first = new AudioFileReader("first.mp3");
var second = new AudioFileReader("second.mp3");
var playlist = first.FollowedBy(TimeSpan.FromSeconds(1), second);
This makes use of an OffsetSampleProvider
in conjunction with a ConcatenatingSampleProvider