This project has moved and is read-only. For the latest updates, please go here.

Playback Audio with FadeIn and FadeOut

Dec 19, 2014 at 8:24 PM
Hello,

I want to build an Application which allows me to Playback some Audiofiles (.wav and .mp3), this was realy easy with an online Tutorial on Youtube [1].

My Problem is that i want to have an FadeIn when i press "Play" and an FadeOut when i press Stop. I found an solution[2] for naudio to do this but i cant bring this solution together with my existing code for normal Playback without Fading.

My Code:
OpenFileDialog dialog = new OpenFileDialog();
            dialog.Filter = "Audio File (*.mp3;*.wav)|*.mp3;*.wav;";
            if (dialog.ShowDialog() != DialogResult.OK) return;
          
            if (this.audioFile.EndsWith(".mp3"))
            {
                NAudio.Wave.WaveStream pcm = NAudio.Wave.WaveFormatConversionStream.CreatePcmStream(new NAudio.Wave.Mp3FileReader(this.audioFile));
                stream = new NAudio.Wave.BlockAlignReductionStream(pcm);
            }
            else if (this.audioFile.EndsWith(".wav"))
            {
                NAudio.Wave.WaveStream pcm = new NAudio.Wave.WaveChannel32(new NAudio.Wave.WaveFileReader(this.audioFile));
                stream = new NAudio.Wave.BlockAlignReductionStream(pcm);
            }
            else throw new InvalidOperationException("Not a correct audio file type.");          
            output = new NAudio.Wave.DirectSoundOut();         
            output.Init(stream);
            this.btn_play.Enabled = true;
My "Play" button Click-Event triggers only the output.play() function.

The Code i found online for Fading:
public class FadeInOutSampleProvider : ISampleProvider
{
    enum FadeState
    {
        Silence,
        FadingIn,
        FullVolume,
        FadingOut,
    }

    private readonly object lockObject = new object();
    private readonly ISampleProvider source;
    private int fadeSamplePosition;
    private int fadeSampleCount;
    private FadeState fadeState;

    public FadeInOutSampleProvider(ISampleProvider source)
    {
        this.source = source;
        this.fadeState = FadeState.FullVolume;
    }

    public void BeginFadeIn(double fadeDurationInMilliseconds)
    {
        lock (lockObject)
        { 
            fadeSamplePosition = 0;
            fadeSampleCount = (int)((fadeDurationInMilliseconds * source.WaveFormat.SampleRate) / 1000);
            fadeState = FadeState.FadingIn;
        }
    }

    public void BeginFadeOut(double fadeDurationInMilliseconds)
    {
        lock (lockObject)
        {
            fadeSamplePosition = 0;
            fadeSampleCount = (int)((fadeDurationInMilliseconds * source.WaveFormat.SampleRate) / 1000);
            fadeState = FadeState.FadingOut;
        }
    }

    public int Read(float[] buffer, int offset, int count)
    {
        int sourceSamplesRead = source.Read(buffer, offset, count);
        lock (lockObject)
        {
            if (fadeState == FadeState.FadingIn)
            {
                FadeIn(buffer, offset, sourceSamplesRead);
            }
            else if (fadeState == FadeState.FadingOut)
            {
                FadeOut(buffer, offset, sourceSamplesRead);
            }
            else if (fadeState == FadeState.Silence)
            {
                ClearBuffer(buffer, offset, count);
            }
        }
        return sourceSamplesRead;
    }

    private static void ClearBuffer(float[] buffer, int offset, int count)
    {
        for (int n = 0; n < count; n++)
        {
            buffer[n + offset] = 0;
        }
    }

    private void FadeOut(float[] buffer, int offset, int sourceSamplesRead)
    {
        int sample = 0;
        while (sample < sourceSamplesRead)
        {
            float multiplier = 1.0f - (fadeSamplePosition / (float)fadeSampleCount);
            for (int ch = 0; ch < source.WaveFormat.Channels; ch++)
            {
                buffer[offset + sample++] *= multiplier;
            }
            fadeSamplePosition++;
            if (fadeSamplePosition > fadeSampleCount)
            {
                fadeState = FadeState.Silence;
                // clear out the end
                ClearBuffer(buffer, sample + offset, sourceSamplesRead - sample);
                break;
            }
        }
    }

    private void FadeIn(float[] buffer, int offset, int sourceSamplesRead)
    {
        int sample = 0;
        while (sample < sourceSamplesRead)
        {
            float multiplier = (fadeSamplePosition / (float)fadeSampleCount);
            for (int ch = 0; ch < source.WaveFormat.Channels; ch++)
            {
                buffer[offset + sample++] *= multiplier;
            }
            fadeSamplePosition++;
            if (fadeSamplePosition > fadeSampleCount)
            {
                fadeState = FadeState.FullVolume;
                // no need to multiply any more
                break;
            }
        }
    }

    public WaveFormat WaveFormat
    {
        get { return source.WaveFormat; }
    }
}
my problem is to connect this sampleProvider to my Playback. Can somebody show a small example on how i do this.

Thanks in advance and sorry for my bad english.


Links:
[1] https://www.youtube.com/watch?v=2ij2vqgprU0
[2] http://stackoverflow.com/a/9471208
Dec 28, 2014 at 3:35 PM
you're using quite an old tutorial there, Try just using an AudioFileReader, and then passing that directly into the FadeInOutSampleProvider. Then pass that into the Init method of your WaveOut device

Mark