rasx
rasx

Reputation: 5338

Reusing a mixed Channel with NAudio

Surely I'm missing a fundamental here with NAudio. I am trying to play the same sound twice and cannot. What's going on?

var path = @"\Rim Shot 2.wav";
var path2 = @"\Rim Shot 4.wav";

var mStream1 = new MemoryStream(File.ReadAllBytes(path));
var mStream2 = new MemoryStream(File.ReadAllBytes(path2));

var stream1 = (new WaveFileReader(mStream1)).ToStandardWaveStream();
var stream2 = (new WaveFileReader(mStream2)).ToStandardWaveStream();

stream1.WaveFormat.Dump();
stream2.WaveFormat.Dump();

var channel1 = new SampleChannel(stream1);
var channel2 = new SampleChannel(stream2);

var format = stream1.WaveFormat;
format = WaveFormat.CreateIeeeFloatWaveFormat(format.SampleRate, format.Channels);
var mixer = new MixingSampleProvider(format);
mixer.ReadFully = true;

try
{
    output.Init(mixer);
    output.Play();

    mixer.AddMixerInput(channel1);
    Task.Delay(10).Wait();

    mixer.AddMixerInput(channel2);
    Task.Delay(10).Wait();

    mixer.AddMixerInput(channel1);
    Task.Delay(2000).Wait();
}
catch(Exception ex)
{
    ex.Dump();
}
finally
{
    if(mStream1 != null) mStream1.Dispose();
    if(mStream2 != null) mStream2.Dispose();

    if(stream1 != null) stream1.Dispose();
    if(stream2 != null) stream2.Dispose();
}

where ToStandardWaveStream() is my extension method:

public static WaveStream ToStandardWaveStream(this WaveStream stream)
{
    if(stream == null) throw new ArgumentNullException("The expected Wave Stream is not here.");

    var encoding = stream.WaveFormat.Encoding;
    var isNotPcmFormat = (encoding != WaveFormatEncoding.Pcm);
    var isNotIeeeFloatFormat = (encoding != WaveFormatEncoding.IeeeFloat);

    Func<WaveStream> convert = () =>
    {
        stream = WaveFormatConversionStream.CreatePcmStream(stream);
        stream = new BlockAlignReductionStream(stream);
        return stream;
    };

    return (isNotPcmFormat && isNotIeeeFloatFormat) ? convert() : stream;
}

Upvotes: 0

Views: 827

Answers (1)

Mark Heath
Mark Heath

Reputation: 49482

You can't add the same stream as an input to the mixer twice. You need to create a second, brand new stream reading from the same WAV file to add. This second stream will be at the beginning. For efficiency, in a drum machine, I'd cache the sound data (as you are doing), but you'd still need to create new WaveFileReaders (or RawSourceStreams), so they start from the beginning

For an example of this in action, look at the NAudio source code for the WPF Drum machine demo.

Upvotes: 2

Related Questions