Closed matteofabbri closed 2 years ago
Hi, thanks )
It's a common problem. Clicks (high-frequency noise) are caused by abrupt change of the amplitude of two adjacent samples. There are 2 simplest approachs to get rid of this effect: 1) simple fast fade in/out to zero at the edges of concatenated signals; 2) crossfading.
Code:
// s1 and s2 are discrete signals (e.g. sinusoids)
// approach 1:
s1.FadeInOut(0.002, 0.005); // e.g., fade-in 2ms; fade-out 5ms
s2.FadeInOut(0.005, 0.002); // e.g., fade-in 5ms; fade-out 2ms
var res1 = s1.Concatenate(s2)
.Concatenate(s1);
// approach 2:
var res2 = s1.CrossFade(s2, 0.005) // cross-fade 5ms
.CrossFade(s1, 0.005);
Extension methods (I will refactor them and add them to next version of the lib, since it's quite useful functionality):
public static class SignalFadeExtensions
{
/// <summary>
/// Simple fade-in/out of the signal.
/// </summary>
/// <param name="signal"></param>
/// <param name="fadeInDuration"></param>
/// <param name="fadeOutDuration"></param>
public static void FadeInOut(this DiscreteSignal signal, double fadeInDuration, double fadeOutDuration)
{
var fadeInSampleCount = Math.Min(signal.Length, (int)(signal.SamplingRate * fadeInDuration));
for (var i = 0; i < fadeInSampleCount; i++)
{
signal[i] *= (float)i / fadeInSampleCount;
}
var fadeOutSampleCount = Math.Min(signal.Length, (int)(signal.SamplingRate * fadeOutDuration));
for (int i = signal.Length - fadeOutSampleCount, idx = fadeOutSampleCount - 1; i < signal.Length; i++, idx--)
{
signal[i] *= (float)idx / fadeOutSampleCount;
}
}
/// <summary>
/// Crossfade between <paramref name="signal1"/> and <paramref name="signal2"/>.
/// </summary>
/// <param name="signal1"></param>
/// <param name="signal2"></param>
/// <param name="duration"></param>
public static DiscreteSignal CrossFade(this DiscreteSignal signal1, DiscreteSignal signal2, double duration)
{
var crossfadeSampleCount = (int)(signal1.SamplingRate * duration); // Math.Min(crossfaded.Length, (int)(crossfaded.SamplingRate * duration));
var crossfaded = new DiscreteSignal(signal1.SamplingRate, signal1.Length + signal2.Length - crossfadeSampleCount);
Array.Copy(signal1.Samples, crossfaded.Samples, signal1.Length - crossfadeSampleCount);
Array.Copy(signal2.Samples, crossfadeSampleCount, crossfaded.Samples, signal1.Length, signal2.Length - crossfadeSampleCount);
var startPos = signal1.Length - crossfadeSampleCount;
for (int i = 0, idx = startPos; i < crossfadeSampleCount; i++, idx++)
{
var frac = (float)i / crossfadeSampleCount;
crossfaded[idx] = (1 - frac) * signal1[idx] + frac * signal2[i];
}
return crossfaded;
}
}
...I closed this issue accidentally ). Feel free to continue this thread if there are still questions.
Hi, thanks for this wonderful code ! I'm trying to make some music with it, but when i concatenate two signal, for example two sins, i got a terrible clipping effect between every sound. What can i do to avoid that ?