Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added events when fade-in/fade-out are complete #1136

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions Docs/FadeInOutSampleProvider.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ var fade = new FadeInOutSampleProvider(audio, true);
fade.BeginFadeIn(2000);
```

After fade in is complete, `FadeInComplete` event is triggered:
```c#
fade.FadeInComplete += (sender, e) => {
Console.WriteLine("Fade in was done!");
};
fade.BeginFadeIn(2000);
```

Now we can pass our `FadeInOutSampleProvider` to an output device and start playing. We'll hear the audio fading in over the first two seconds.

```c#
Expand All @@ -28,6 +36,15 @@ At some point in the future, we might want to fade out, and we can trigger that
fade.BeginFadeOut(2000);
```

It also triggers `FadeOutComplete` event, when fade out is complete

```c#
fade.FadeOutComplete += (sender, e) => {
Console.WriteLine("Fade out was done!");
};
fade.BeginFadeOut(2000);
```

Once the audio has faded out, the `FadeInOutSampleProvider` continues to read from its source but emits silence until it reaches its end, or until you call `BeginFadeIn` again.

### Taking it further
Expand Down
18 changes: 17 additions & 1 deletion NAudio.Core/Wave/SampleProviders/FadeInOutSampleProvider.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace NAudio.Wave.SampleProviders
using System;

namespace NAudio.Wave.SampleProviders
{
/// <summary>
/// Sample Provider to allow fading in and out
Expand All @@ -13,6 +15,16 @@ enum FadeState
FadingOut,
}

/// <summary>
/// Raised when scheduled fade-in is done
/// </summary>
public event EventHandler FadeInComplete;

/// <summary>
/// Raised when scheduled fade-out is done
/// </summary>
public event EventHandler FadeOutComplete;

private readonly object lockObject = new object();
private readonly ISampleProvider source;
private int fadeSamplePosition;
Expand Down Expand Up @@ -108,6 +120,8 @@ private void FadeOut(float[] buffer, int offset, int sourceSamplesRead)
if (fadeSamplePosition > fadeSampleCount)
{
fadeState = FadeState.Silence;
FadeOutComplete?.Invoke(this, EventArgs.Empty);

// clear out the end
ClearBuffer(buffer, sample + offset, sourceSamplesRead - sample);
break;
Expand All @@ -129,6 +143,8 @@ private void FadeIn(float[] buffer, int offset, int sourceSamplesRead)
if (fadeSamplePosition > fadeSampleCount)
{
fadeState = FadeState.FullVolume;
FadeInComplete?.Invoke(this, EventArgs.Empty);

// no need to multiply any more
break;
}
Expand Down
56 changes: 56 additions & 0 deletions NAudioTests/WaveStreams/FadeInOutSampleProviderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,5 +120,61 @@ public void BufferIsZeroedAfterFadeOut()
Assert.AreEqual(20, read);
Assert.AreEqual(0, buffer[0]);
}

[Test]
public void FadeInCompleteInvoked()
{
// given
var source = new TestSampleProvider(10, 1); // 10 samples per second
source.UseConstValue = true;
source.ConstValue = 100;
var fade = new FadeInOutSampleProvider(source);
var fadeInsCount = 0;
fade.FadeInComplete += (sender, e) =>
{
fadeInsCount++;
};

// when
fade.BeginFadeIn(1000);

// then
float[] buffer = new float[20];
int read = fade.Read(buffer, 0, 20);
Assert.AreEqual(20, read);
Assert.AreEqual(0, buffer[0]); // start of fade-in
Assert.AreEqual(50, buffer[5]); // half-way
Assert.AreEqual(100, buffer[10]); // fully fade in
Assert.AreEqual(100, buffer[15]); // fully fade in
Assert.AreEqual(1, fadeInsCount); // we want one-shot event (when fade in was completed once)
}

[Test]
public void FadeOutCompleteInvoked()
{
// given
var source = new TestSampleProvider(10, 1); // 10 samples per second
source.UseConstValue = true;
source.ConstValue = 100;
var fade = new FadeInOutSampleProvider(source);
var fadeOutsCount = 0;
fade.FadeOutComplete += (sender, e) =>
{
fadeOutsCount++;
};

// when
fade.BeginFadeOut(1000);

// then
float[] buffer = new float[20];
int read = fade.Read(buffer, 0, 20);
Assert.AreEqual(20, read);
Assert.AreEqual(100, buffer[0]); // start of fade-out
Assert.AreEqual(50, buffer[5]); // half-way
Assert.AreEqual(0, buffer[10]); // fully fade out
Assert.AreEqual(0, buffer[15]); // fully fade out
Assert.AreEqual(1, fadeOutsCount); // we want one-shot event (when fade out was completed once)
}
}
}