Пример #1
0
        /// <summary>
        /// Method concatenates two signals.
        /// </summary>
        /// <param name="signal1"></param>
        /// <param name="signal2"></param>
        /// <returns></returns>
        public static DiscreteSignal Concatenate(this DiscreteSignal signal1, DiscreteSignal signal2)
        {
            Guard.AgainstInequality(signal1.SamplingRate, signal2.SamplingRate,
                                    "Sampling rate of signal1", "sampling rate of signal2");

            return(new DiscreteSignal(
                       signal1.SamplingRate,
                       signal1.Samples.MergeWithArray(signal2.Samples)));
        }
Пример #2
0
        /// <summary>
        /// In-place signal attenuation by coeff
        /// </summary>
        /// <param name="signal"></param>
        /// <param name="coeff"></param>
        public static void Attenuate(this DiscreteSignal signal, float coeff)
        {
            if (Math.Abs(coeff) < 1e-10)
            {
                throw new ArgumentException("Attenuation coefficient can't be zero");
            }

            signal.Amplify(1 / coeff);
        }
        /// <summary>
        /// Creates new signal from last <paramref name="n"/> samples of <paramref name="signal"/>.
        /// </summary>
        /// <param name="signal">Signal</param>
        /// <param name="n">Number of samples to copy</param>
        public static DiscreteSignal Last(this DiscreteSignal signal, int n)
        {
            Guard.AgainstNonPositive(n, "Number of samples");
            Guard.AgainstExceedance(n, signal.Length, "Number of samples", "signal length");

            return(new DiscreteSignal(
                       signal.SamplingRate,
                       signal.Samples.FastCopyFragment(n, signal.Length - n)));
        }
Пример #4
0
 /// <summary>
 /// Half rectification (in-place)
 /// </summary>
 /// <param name="signal">Signal</param>
 /// <returns>Half rectified signal</returns>
 public static void HalfRectify(this DiscreteSignal signal)
 {
     for (var i = 0; i < signal.Length; i++)
     {
         if (signal[i] < 0)
         {
             signal[i] = 0;
         }
     }
 }
        /// <summary>
        /// Fades signal out linearly (in-place).
        /// </summary>
        /// <param name="signal">Signal</param>
        /// <param name="duration">Fade-out duration (in seconds)</param>
        public static void FadeOut(this DiscreteSignal signal, double duration)
        {
            Guard.AgainstNonPositive(duration, "Fade-out duration");

            var fadeSampleCount = Math.Min(signal.Length, (int)(signal.SamplingRate * duration));

            for (int i = signal.Length - fadeSampleCount, fadeIndex = fadeSampleCount - 1; i < signal.Length; i++, fadeIndex--)
            {
                signal[i] *= (float)fadeIndex / fadeSampleCount;
            }
        }
        /// <summary>
        /// Fades signal in linearly (in-place).
        /// </summary>
        /// <param name="signal">Signal</param>
        /// <param name="duration">Fade-in duration (in seconds)</param>
        public static void FadeIn(this DiscreteSignal signal, double duration)
        {
            Guard.AgainstNonPositive(duration, "Fade-in duration");

            var fadeSampleCount = Math.Min(signal.Length, (int)(signal.SamplingRate * duration));

            for (var i = 0; i < fadeSampleCount; i++)
            {
                signal[i] *= (float)i / fadeSampleCount;
            }
        }
Пример #7
0
        /// <summary>
        /// More or less efficient LINQ-less version.
        /// Skip() would require unnecessary enumeration.
        /// </summary>
        /// <param name="signal"></param>
        /// <param name="sampleCount"></param>
        /// <returns></returns>
        public static DiscreteSignal Last(this DiscreteSignal signal, int sampleCount)
        {
            if (sampleCount <= 0 || sampleCount > signal.Length)
            {
                throw new ArgumentException("Number of samples must be positive and must not exceed the signal length!");
            }

            return(new DiscreteSignal(
                       signal.SamplingRate,
                       signal.Samples.FastCopyFragment(sampleCount, signal.Length - sampleCount)));
        }
Пример #8
0
        /// <summary>
        /// Method concatenates two signals.
        /// </summary>
        /// <param name="signal1"></param>
        /// <param name="signal2"></param>
        /// <returns></returns>
        public static DiscreteSignal Concatenate(this DiscreteSignal signal1, DiscreteSignal signal2)
        {
            if (signal1.SamplingRate != signal2.SamplingRate)
            {
                throw new ArgumentException("Sampling rates must be the same!");
            }

            return(new DiscreteSignal(
                       signal1.SamplingRate,
                       signal1.Samples.MergeWithArray(signal2.Samples)));
        }
Пример #9
0
        /// <summary>
        /// Reverse signal in-place
        /// </summary>
        /// <param name="signal"></param>
        public static void Reverse(this DiscreteSignal signal)
        {
            var samples = signal.Samples;

            for (int i = 0, j = samples.Length - 1; i < samples.Length / 2; i++, j--)
            {
                var tmp = samples[i];
                samples[i] = samples[j];
                samples[j] = tmp;
            }
        }
        /// <summary>
        /// Normalizes <paramref name="signal"/> by its max absolute value (to range [-1, 1]).
        /// </summary>
        /// <param name="signal">Signal</param>
        /// <param name="bitsPerSample">Bit depth</param>
        public static void NormalizeMax(this DiscreteSignal signal, int bitsPerSample = 0)
        {
            var norm = 1 / signal.Samples.Max(s => Math.Abs(s));

            if (bitsPerSample > 0)
            {
                norm *= (float)(1 - 1 / Math.Pow(2, bitsPerSample));
            }

            signal.Amplify(norm);
        }
Пример #11
0
        /// <summary>
        /// Method returns repeated n times copy of the signal
        /// </summary>
        /// <param name="signal"></param>
        /// <param name="times"></param>
        /// <returns></returns>
        public static DiscreteSignal Repeat(this DiscreteSignal signal, int times)
        {
            if (times <= 0)
            {
                throw new ArgumentException("Number of repeat times must be at least once");
            }

            return(new DiscreteSignal(
                       signal.SamplingRate,
                       signal.Samples.RepeatArray(times)));
        }
Пример #12
0
        /// <summary>
        /// Method delays the signal
        ///     either by shifting it to the right (positive, e.g. Delay(1000))
        ///         or by shifting it to the left (negative, e.g. Delay(-1000))
        /// </summary>
        /// <param name="signal"></param>
        /// <param name="delay"></param>
        /// <returns></returns>
        public static DiscreteSignal Delay(this DiscreteSignal signal, int delay)
        {
            var length = signal.Length;

            if (delay <= 0)
            {
                delay = -delay;

                Guard.AgainstInvalidRange(delay, length, "Delay", "signal length");

                return(new DiscreteSignal(
                           signal.SamplingRate,
                           signal.Samples.FastCopyFragment(length - delay, delay)));
            }

            return(new DiscreteSignal(
                       signal.SamplingRate,
                       signal.Samples.FastCopyFragment(length, destinationOffset: delay)));
        }
Пример #13
0
        /// <summary>
        /// Method delays the signal
        ///     either by shifting it to the right (positive, e.g. Delay(1000))
        ///         or by shifting it to the left (negative, e.g. Delay(-1000))
        /// </summary>
        /// <param name="signal"></param>
        /// <param name="delay"></param>
        /// <returns></returns>
        public static DiscreteSignal Delay(this DiscreteSignal signal, int delay)
        {
            var length = signal.Length;

            if (delay <= 0)
            {
                delay = -delay;

                if (delay >= length)
                {
                    throw new ArgumentException("Delay can not exceed the length of the signal!");
                }

                return(new DiscreteSignal(
                           signal.SamplingRate,
                           signal.Samples.FastCopyFragment(length - delay, delay)));
            }

            return(new DiscreteSignal(
                       signal.SamplingRate,
                       signal.Samples.FastCopyFragment(length, destinationOffset: delay)));
        }
Пример #14
0
        /// <summary>
        /// Method superimposes two signals.
        /// If sizes are different then the smaller signal is broadcasted
        /// to fit the size of the larger signal.
        /// </summary>
        /// <param name="signal1"></param>
        /// <param name="signal2"></param>
        /// <returns></returns>
        public static DiscreteSignal SuperimposeMany(this DiscreteSignal signal1, DiscreteSignal signal2, int[] positions)
        {
            Guard.AgainstInequality(signal1.SamplingRate, signal2.SamplingRate,
                                    "Sampling rate of signal1", "sampling rate of signal2");

            var totalLength = Math.Max(signal1.Length, signal2.Length + positions.Max());

            DiscreteSignal superimposed = new DiscreteSignal(signal1.SamplingRate, totalLength);

            signal1.Samples.FastCopyTo(superimposed.Samples, signal1.Length);

            for (var p = 0; p < positions.Length; p++)
            {
                var offset = positions[p];

                for (var i = 0; i < signal2.Length; i++)
                {
                    superimposed[offset + i] += signal2.Samples[i];
                }
            }

            return(superimposed);
        }
        /// <summary>
        /// <para>
        /// Crossfades linearly between signals and returns crossfaded signal of length
        /// equal to sum of signal lengths minus length of crossfade section.
        /// </para>
        /// <para>
        /// The length of crossfade section will be calculated
        /// based on the sampling rate of the first signal.
        /// </para>
        /// </summary>
        /// <param name="signal1">First signal</param>
        /// <param name="signal2">Second signal</param>
        /// <param name="duration">Crossfade duration (in seconds)</param>
        public static DiscreteSignal Crossfade(this DiscreteSignal signal1, DiscreteSignal signal2, double duration)
        {
            Guard.AgainstNonPositive(duration, "Crossfade duration");

            var minSignalLength      = Math.Min(signal1.Length, signal2.Length);
            var crossfadeSampleCount = Math.Min((int)(signal1.SamplingRate * duration), minSignalLength);

            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 = startPos, fadeIndex = 0; fadeIndex < crossfadeSampleCount; fadeIndex++, i++)
            {
                var frac = (float)fadeIndex / crossfadeSampleCount;

                crossfaded[i] = (1 - frac) * signal1[i] + frac * signal2[fadeIndex];
            }

            return(crossfaded);
        }
Пример #16
0
 /// <summary>
 /// Method copies discrete signal samples into complex signal
 /// </summary>
 /// <param name="signal">Real-valued signal</param>
 /// <returns>Corresponding complex-valued signal</returns>
 public static ComplexDiscreteSignal ToComplex(this DiscreteSignal signal)
 {
     return(new ComplexDiscreteSignal(signal.SamplingRate, signal.Samples.ToDoubles()));
 }
 /// <summary>
 /// Fades signal in and out linearly (in-place).
 /// </summary>
 /// <param name="signal">Signal</param>
 /// <param name="fadeInDuration">Fade-in duration</param>
 /// <param name="fadeOutDuration">Fade-out duration</param>
 public static void FadeInFadeOut(this DiscreteSignal signal, double fadeInDuration, double fadeOutDuration)
 {
     signal.FadeIn(fadeInDuration);
     signal.FadeOut(fadeOutDuration);
 }
Пример #18
0
        /// <summary>
        /// In-place signal attenuation by coeff
        /// </summary>
        /// <param name="signal"></param>
        /// <param name="coeff"></param>
        public static void Attenuate(this DiscreteSignal signal, float coeff)
        {
            Guard.AgainstNonPositive(coeff, "Attenuation coefficient");

            signal.Amplify(1 / coeff);
        }