I'm looking for a way to mix thousands of WAV files into a single file using NAudio's MixingSampleProvider. I'm building a drum sampler and I'd like to be able to create a whole song (based on MIDI information) that could then be exported into a single WAV file.
The issue I'm running into is that the MixingSampleProvider has a limit of 1024 sources and throws and exception saying Too many mixer inputs if that limit is reached. I'm sure this limit is there for a reason, I'd like to know how to achieve my goal despite it.
I've searched through the NAudio demos and Mark Heath's blog, but I haven't found exactly what I need there.
I was thinking I could split the song into smaller segments (under 1024 sampler inputs) and merge the separate parts afterwards. Is that the way to go, or is there a better one? Thanks for any advice.
Here's a part of my code:
public class DrumSampler
{
private readonly MixingSampleProvider _mixer;
private readonly Dictionary<string, SampleSource> _cachedSamples = new();
public DrumSampler()
{
var waveFormat = WaveFormat.CreateIeeeFloatWaveFormat(44100, 2);
_mixer = new MixingSampleProvider(waveFormat);
LoadSamples();
}
private void LoadSamples()
{
LoadSample("kick", @"C:\Samples\kick.wav");
LoadSample("snare", @"C:\Samples\snare.wav");
LoadSample("crash", @"C:\Samples\crash.wav");
}
private void LoadSample(string key, string filePath)
{
_cachedSamples.Add(key, SampleSource.CreateFromWaveFile(filePath, _mixer.WaveFormat));
}
public void ExportSong()
{
AddDrums();
WaveFileWriter.CreateWaveFile16("song.wav", _mixer);
}
private void AddDrums()
{
//simulate adding drum samples based on MIDI information
for (int i = 0; i < 1000; i++)
{
var sample = _cachedSamples["kick"];
var delayed = new DelayedSampleProvider(sample, TimeSpan.FromSeconds(123));
_mixer.AddMixerInput(delayed);
}
}
}
The SampleSource implementation is taken from NAudio's DrumMachineDemo.
The DelayedSampleProvider implementation is inspired by NAudio's OffsetSampleProvider.
I've been able to resolve this issue by splitting the song into smaller chungs (under 1024 mixer inputs), each chunk having its own
MixingSampleProviderand then concatenating all the chungs using theConcatenatingSampleProvider.It works, however, I'd like to know if there's a more elegant solution...
Here's my code: