Skip to content

Commit

Permalink
Added events when fade-in/fade-out are complete
Browse files Browse the repository at this point in the history
  • Loading branch information
SMSapereAude committed Mar 15, 2024
1 parent a106da4 commit b229424
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 1 deletion.
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.BeginFadeIn(2000);
fade.FadeInComplete += (sender, e) => {
Console.WriteLine("Fade in was done!");
};
```

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.BeginFadeOut(2000);
fade.FadeOutComplete += (sender, e) => {
Console.WriteLine("Fade out was done!");
};
```

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)
}
}
}

0 comments on commit b229424

Please sign in to comment.