diff --git a/NWaves/Audio/ByteConverter.cs b/NWaves/Audio/ByteConverter.cs
index 8bce105..e0b40a7 100644
--- a/NWaves/Audio/ByteConverter.cs
+++ b/NWaves/Audio/ByteConverter.cs
@@ -1,12 +1,12 @@
namespace NWaves.Audio
{
///
- /// Static class providing methods for conversion between PCM bytes and float[] data.
+ /// Provides methods for conversion between PCM bytes and float[] data.
///
public static class ByteConverter
{
///
- /// Convert Pcm_8bit to arrays of .
+ /// Converts Pcm_8bit to arrays of .
///
/// Array of bytes
/// Arrays of floats
@@ -38,7 +38,7 @@ public static void ToFloats8Bit(byte[] bytes, float[][] floats, bool normalize =
}
///
- /// Convert arrays of to Pcm_8bit .
+ /// Converts arrays of to Pcm_8bit .
///
/// Array of bytes
/// Arrays of floats
@@ -70,7 +70,7 @@ public static void FromFloats8Bit(float[][] floats, byte[] bytes, bool normalize
}
///
- /// Convert Pcm_16bit to arrays of (little-endian or big-endian).
+ /// Converts Pcm_16bit to arrays of (little-endian or big-endian).
///
/// Array of bytes
/// Arrays of floats
@@ -130,7 +130,7 @@ public static void ToFloats16Bit(byte[] bytes, float[][] floats, bool normalize
}
///
- /// Convert arrays of to Pcm_16bit (little-endian or big-endian).
+ /// Converts arrays of to Pcm_16bit (little-endian or big-endian).
///
/// Array of bytes
/// Arrays of floats
diff --git a/NWaves/Audio/Interfaces/IAudioContainer.cs b/NWaves/Audio/Interfaces/IAudioContainer.cs
index 1351090..0f6f134 100644
--- a/NWaves/Audio/Interfaces/IAudioContainer.cs
+++ b/NWaves/Audio/Interfaces/IAudioContainer.cs
@@ -9,12 +9,12 @@ namespace NWaves.Audio.Interfaces
public interface IAudioContainer
{
///
- /// Get the list of discrete signals in container.
+ /// Gets the list of discrete signals in container.
///
List Signals { get; }
///
- /// Return container's signal using indexing based on channel type.
+ /// Gets the signal from container using indexing scheme based on channel type.
///
/// Channel (left, right, interleave, sum, average, or ordinary index)
DiscreteSignal this[Channels channel] { get; }
diff --git a/NWaves/Audio/Interfaces/IAudioPlayer.cs b/NWaves/Audio/Interfaces/IAudioPlayer.cs
index 4fe7905..51224e5 100644
--- a/NWaves/Audio/Interfaces/IAudioPlayer.cs
+++ b/NWaves/Audio/Interfaces/IAudioPlayer.cs
@@ -9,12 +9,12 @@ namespace NWaves.Audio.Interfaces
public interface IAudioPlayer
{
///
- /// Gets or sets sound volume (usually in range [0.0f, 1.0f]).
+ /// Gets or sets sound volume (usually in range [0..1]).
///
float Volume { get; set; }
///
- /// Play samples contained in asynchronously.
+ /// Plays samples contained in asynchronously.
///
/// Signal to play
/// Index of the first sample to play
@@ -23,7 +23,7 @@ public interface IAudioPlayer
Task PlayAsync(DiscreteSignal signal, int startPos = 0, int endPos = -1, short bitDepth = 16);
///
- /// Play samples contained in WAV file (or some other source) asynchronously.
+ /// Plays samples contained in WAV file (or some other source) asynchronously.
///
/// Path to WAV file (or other source) to play
/// Index of the first sample to play
@@ -31,17 +31,17 @@ public interface IAudioPlayer
Task PlayAsync(string source, int startPos = 0, int endPos = -1);
///
- /// Pause playing audio.
+ /// Pauses playing audio.
///
void Pause();
///
- /// Resume playing audio.
+ /// Resumes playing audio.
///
void Resume();
///
- /// Stop playing audio.
+ /// Stops playing audio.
///
void Stop();
}
diff --git a/NWaves/Audio/Interfaces/IAudioRecorder.cs b/NWaves/Audio/Interfaces/IAudioRecorder.cs
index dac5616..497aed5 100644
--- a/NWaves/Audio/Interfaces/IAudioRecorder.cs
+++ b/NWaves/Audio/Interfaces/IAudioRecorder.cs
@@ -6,7 +6,7 @@
public interface IAudioRecorder
{
///
- /// Start recording audio with specific settings.
+ /// Starts recording audio with specific settings.
///
/// Sampling rate
/// Number of channels (1=mono, 2=stereo)
@@ -14,7 +14,7 @@ public interface IAudioRecorder
void StartRecording(int samplingRate, short channelCount, short bitsPerSample);
///
- /// Stop recording audio and save recorded sound to file or any other destination.
+ /// Stops recording audio and saves recorded sound to file or any other destination.
///
/// Path to output file (destination)
void StopRecording(string destination);
diff --git a/NWaves/Audio/Mci/Mci.cs b/NWaves/Audio/Mci/Mci.cs
index c29eeea..379cd4b 100644
--- a/NWaves/Audio/Mci/Mci.cs
+++ b/NWaves/Audio/Mci/Mci.cs
@@ -4,7 +4,7 @@
namespace NWaves.Audio.Mci
{
///
- /// Static class containing MCI functions imported from winmm.dll
+ /// Provides MCI functions imported from winmm.dll.
///
public static class Mci
{
diff --git a/NWaves/Audio/Mci/MciAudioPlayer.cs b/NWaves/Audio/Mci/MciAudioPlayer.cs
index 82d897f..2ed943a 100644
--- a/NWaves/Audio/Mci/MciAudioPlayer.cs
+++ b/NWaves/Audio/Mci/MciAudioPlayer.cs
@@ -40,12 +40,12 @@ public class MciAudioPlayer : IAudioPlayer
private bool _isPaused;
///
- /// Gets or sets audio volume (measured in percents from the range [0.0f, 1.0f]).
+ /// Gets or sets audio volume (measured in percents from the range [0..1]).
///
public float Volume { get; set; }
///
- /// Play audio contained in WAV file asynchronously.
+ /// Plays audio contained in WAV file asynchronously.
///
/// Path to WAV file to play
/// Index of the first sample to play
@@ -137,7 +137,7 @@ public Task PlayAsync(DiscreteSignal signal, int startPos = 0, int endPos = -1,
}
///
- /// Pause playing audio.
+ /// Pauses playing audio.
///
public void Pause()
{
@@ -157,7 +157,7 @@ public void Pause()
}
///
- /// Resume playing audio.
+ /// Resumes playing audio.
///
public void Resume()
{
@@ -176,7 +176,7 @@ public void Resume()
}
///
- /// Stop playing audio and close MCI device.
+ /// Stops playing audio and close MCI device.
///
public void Stop()
{
diff --git a/NWaves/Audio/Mci/MciAudioRecorder.cs b/NWaves/Audio/Mci/MciAudioRecorder.cs
index f40290b..27c8a63 100644
--- a/NWaves/Audio/Mci/MciAudioRecorder.cs
+++ b/NWaves/Audio/Mci/MciAudioRecorder.cs
@@ -11,7 +11,7 @@ namespace NWaves.Audio.Mci
public class MciAudioRecorder : IAudioRecorder
{
///
- /// Start recording audio with specific settings.
+ /// Starts recording audio with specific settings.
///
/// Sampling rate
/// Number of channels (1=mono, 2=stereo)
@@ -40,7 +40,7 @@ public void StartRecording(int samplingRate = 44100, short channelCount = 1, sho
}
///
- /// Stop recording audio and save it to WAV file.
+ /// Stops recording audio and save it to WAV file.
///
/// Path to output WAV file containing recorded sound
public void StopRecording(string destination)
diff --git a/NWaves/Audio/WaveFile.cs b/NWaves/Audio/WaveFile.cs
index 770e0ab..213636c 100644
--- a/NWaves/Audio/WaveFile.cs
+++ b/NWaves/Audio/WaveFile.cs
@@ -11,9 +11,9 @@ namespace NWaves.Audio
///
/// PCM WAV container.
///
- /// is not intended to be a "wrapper around the stream", or to acquire any resource
- /// (it doesn't affect the underlying stream). It's more like a "constructor of signals in memory based on data
- /// from the stream" and its lifetime is not synchronized with the stream whatsoever.
+ /// is not intended to be a wrapper around the stream, or to acquire any resource
+ /// (it doesn't affect the underlying stream). It's more like a constructor of signals in memory based on data
+ /// from the stream, and its lifetime is not synchronized with the stream whatsoever.
/// The synonym name of this class could be also "WaveContainer".
///
///
@@ -25,7 +25,7 @@ public class WaveFile : IAudioContainer
public List Signals { get; protected set; }
///
- /// WAV header (WAVE format).
+ /// Gets WAV header (WAVE format).
///
public WaveFormat WaveFmt { get; protected set; }
@@ -34,6 +34,16 @@ public class WaveFile : IAudioContainer
///
public short[] SupportedBitDepths = { 8, 16, 24, 32 };
+ ///
+ /// Constructs WAV container by loading signals from .
+ ///
+ /// Input stream
+ /// Normalize samples
+ public WaveFile(Stream waveStream, bool normalized = true)
+ {
+ ReadWaveStream(waveStream, normalized);
+ }
+
///
/// Constructs WAV container by loading signals from a byte array (i.e. byte content of WAV file).
///
@@ -62,17 +72,7 @@ public WaveFile(byte[] waveBytes, int index, bool normalized = true)
}
///
- /// Constructs WAV container by loading signals from .
- ///
- /// Input stream
- /// Normalize samples
- public WaveFile(Stream waveStream, bool normalized = true)
- {
- ReadWaveStream(waveStream, normalized);
- }
-
- ///
- /// Read PCM WAV binary data and fill and structure.
+ /// Reads PCM WAV binary data and fills and structure.
///
/// Input stream of PCM WAV binary data
/// Normalize samples
@@ -241,13 +241,13 @@ protected void ReadWaveStream(Stream waveStream, bool normalized = true)
}
///
- /// Construct WAV container by loading into it collection of with given .
+ /// Constructs WAV container by loading into it collection of with given .
///
/// Signals to be loaded into container
/// Bit depth
public WaveFile(IList signals, short bitsPerSample = 16)
{
- if (signals == null || !signals.Any())
+ if (signals is null || !signals.Any())
{
throw new ArgumentException("At least one signal must be provided");
}
@@ -285,7 +285,7 @@ public WaveFile(IList signals, short bitsPerSample = 16)
}
///
- /// Construct WAV container by loading into it one with given .
+ /// Constructs WAV container by loading into it one with given .
///
/// Signal to be loaded into container
/// Bit depth
@@ -294,7 +294,7 @@ public WaveFile(DiscreteSignal signal, short bitsPerSample = 16) : this(new [] {
}
///
- /// Return the contents of PCM WAV container as array of bytes.
+ /// Returns the contents of PCM WAV container as array of bytes.
///
/// True if samples are normalized
public byte[] GetBytes(bool normalized = true)
@@ -307,7 +307,7 @@ public byte[] GetBytes(bool normalized = true)
}
///
- /// Save the contents of PCM WAV container to .
+ /// Saves the contents of PCM WAV container to .
///
/// Output stream
/// True if samples are normalized
@@ -400,7 +400,7 @@ public void SaveTo(Stream waveStream, bool normalized = true)
}
///
- /// Return container's signal using indexing based on channel type. Examples
+ /// Gets the signal from container using indexing scheme based on channel type. Examples
///
/// waveFile[Channels.Left] -> waveFile.Signals[0]
///
diff --git a/NWaves/Operations/DynamicsMode.cs b/NWaves/Operations/DynamicsMode.cs
index 8275679..03cbfa9 100644
--- a/NWaves/Operations/DynamicsMode.cs
+++ b/NWaves/Operations/DynamicsMode.cs
@@ -1,24 +1,27 @@
namespace NWaves.Operations
{
+ ///
+ /// Types (modes) of dynamics processors.
+ ///
public enum DynamicsMode
{
///
- /// Smaller ratios, like 1:1, 2:1
+ /// Smaller ratios, like 1:1, 2:1.
///
Compressor,
///
- /// Bigger ratios, like 5:1, 10:1
+ /// Bigger ratios, like 5:1, 10:1.
///
Limiter,
///
- /// Smaller ratios, like 1:1, 2:1
+ /// Smaller ratios, like 1:1, 2:1.
///
Expander,
///
- /// Very high ratios, like 5:1
+ /// Very high ratios, like 5:1.
///
NoiseGate
}
diff --git a/NWaves/Operations/DynamicsProcessor.cs b/NWaves/Operations/DynamicsProcessor.cs
index 4d878a8..8ab6910 100644
--- a/NWaves/Operations/DynamicsProcessor.cs
+++ b/NWaves/Operations/DynamicsProcessor.cs
@@ -6,52 +6,52 @@
namespace NWaves.Operations
{
///
- /// Dynamics processor: limiter / compressor / expander / noise gate
+ /// Represents dynamics processor: limiter or compressor or expander or noise gate.
///
public class DynamicsProcessor : IFilter, IOnlineFilter
{
///
- /// Dynamics processor mode
+ /// Dynamics processor mode.
///
private readonly DynamicsMode _mode;
///
- /// Envelope follower
+ /// Envelope follower.
///
private readonly EnvelopeFollower _envelopeFollower;
///
- /// Sampling rate
+ /// Sampling rate.
///
private readonly int _fs;
///
- /// Min threshold for dB amplitude
+ /// Min threshold for dB amplitude.
///
private readonly float _minAmplitudeDb;
///
- /// Attack/Release time coefficient
+ /// Attack/Release time coefficient.
///
private readonly float T = 1 / (float)Math.Log(9); // = approx. 2.2
///
- /// Compression threshold
+ /// Gets or sets compression/expansion threshold.
///
public float Threshold { get; set; }
///
- /// Compression ratio
+ /// Gets or sets compression/expansion ratio.
///
public float Ratio { get; set; }
///
- /// Makeup gain
+ /// Gets or sets makeup gain.
///
public float MakeupGain { get; set; }
///
- /// Attack time
+ /// Gets or sets attack time.
///
public float Attack
{
@@ -86,7 +86,7 @@ public float Attack
}
///
- /// Release time
+ /// Gets or sets release time.
///
public float Release
{
@@ -121,16 +121,16 @@ public float Release
}
///
- /// Constructor
+ /// Constructs in given .
///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
+ /// Type (mode) of dynamics processor
+ /// Sampling rate
+ /// Compression/expansion threshold
+ /// Compression/expansion ratio
+ /// Makeup gain
+ /// Attack time (in seconds)
+ /// Release time (in seconds)
+ /// Min threshold for dB amplitude
public DynamicsProcessor(DynamicsMode mode,
int samplingRate,
float threshold,
@@ -152,6 +152,10 @@ public DynamicsProcessor(DynamicsMode mode,
Release = release;
}
+ ///
+ /// Processes one sample.
+ ///
+ /// Input sample
public float Process(float sample)
{
var abs = Math.Abs(sample);
@@ -183,11 +187,19 @@ public float Process(float sample)
return sample * gain;
}
+ ///
+ /// Resets dynamics processor.
+ ///
public void Reset()
{
_envelopeFollower.Reset();
}
+ ///
+ /// Processes entire and returns new signal (dynamics).
+ ///
+ /// Input signal
+ /// Filtering method
public DiscreteSignal ApplyTo(DiscreteSignal signal, FilteringMethod method = FilteringMethod.Auto) => this.FilterOnline(signal);
}
}
diff --git a/NWaves/Operations/EnvelopeFollower.cs b/NWaves/Operations/EnvelopeFollower.cs
index daa30fd..c5cdf66 100644
--- a/NWaves/Operations/EnvelopeFollower.cs
+++ b/NWaves/Operations/EnvelopeFollower.cs
@@ -5,14 +5,13 @@
namespace NWaves.Operations
{
///
- /// Envelope follower (detector)
+ /// Represents envelope follower (envelope detector).
///
public class EnvelopeFollower : IFilter, IOnlineFilter
{
///
- /// Attack time
+ /// Gets or sets attack time (in seconds).
///
- private float _attackTime;
public float AttackTime
{
get => _attackTime;
@@ -22,11 +21,11 @@ public float AttackTime
_ga = value < 1e-20 ? 0 : (float)Math.Exp(-1.0 / (value * _fs));
}
}
+ private float _attackTime;
///
- /// Release time
+ /// Gets or sets release time (in seconds).
///
- private float _releaseTime;
public float ReleaseTime
{
get => _releaseTime;
@@ -36,33 +35,34 @@ public float ReleaseTime
_gr = value < 1e-20 ? 0 : (float)Math.Exp(-1.0 / (value * _fs));
}
}
+ private float _releaseTime;
///
- /// Sampling rate
+ /// Sampling rate.
///
private readonly int _fs;
///
- /// Current envelope sample
+ /// Current envelope sample.
///
private float _env;
///
- /// Attack coefficient
+ /// Attack coefficient.
///
private float _ga;
///
- /// Release coefficient
+ /// Release coefficient.
///
private float _gr;
///
- /// Constructor
+ /// Constructs .
///
- ///
- ///
- ///
+ /// Sampling rate
+ /// Attack time (in seconds)
+ /// Release time (in seconds)
public EnvelopeFollower(int samplingRate, float attackTime = 0.01f, float releaseTime = 0.05f)
{
_fs = samplingRate;
@@ -71,24 +71,33 @@ public EnvelopeFollower(int samplingRate, float attackTime = 0.01f, float releas
}
///
- /// Envelope following is essentialy a low-pass filtering
+ /// Processes one sample.
///
- ///
- ///
- public float Process(float input)
+ /// Input sample
+ public float Process(float sample)
{
- var sample = Math.Abs(input);
+ // envelope following is essentially a low-pass filtering
+
+ var s = Math.Abs(sample);
- _env = _env < sample ? _ga * _env + (1 - _ga) * sample : _gr * _env + (1 - _gr) * sample;
+ _env = _env < s ? _ga * _env + (1 - _ga) * s : _gr * _env + (1 - _gr) * s;
return _env;
}
+ ///
+ /// Resets envelope follower.
+ ///
public void Reset()
{
_env = 0;
}
+ ///
+ /// Processes entire and returns new signal (envelope).
+ ///
+ /// Input signal
+ /// Filtering method
public DiscreteSignal ApplyTo(DiscreteSignal signal, FilteringMethod method = FilteringMethod.Auto) => this.FilterOnline(signal);
}
}
diff --git a/NWaves/Operations/GriffinLimReconstructor.cs b/NWaves/Operations/GriffinLimReconstructor.cs
index b72126c..d48115e 100644
--- a/NWaves/Operations/GriffinLimReconstructor.cs
+++ b/NWaves/Operations/GriffinLimReconstructor.cs
@@ -6,18 +6,18 @@
namespace NWaves.Operations
{
///
- /// Class for reconstructing signal from a given power / magnitude spectrogram
+ /// Represents reconstructing signal from a given power / magnitude spectrogram
/// based on Griffin-Lim iterative algorithm.
///
public class GriffinLimReconstructor
{
///
- /// STFT transformer
+ /// STFT transformer.
///
private readonly Stft _stft;
///
- /// Magnitude part of the spectrogram
+ /// Magnitude part of the spectrogram.
///
private readonly List _magnitudes;
@@ -54,15 +54,14 @@ public GriffinLimReconstructor(List spectrogram, Stft stft, int power =
}
///
- /// One iteration of reconstruction
+ /// Does one iteration of reconstruction and returns reconstructed signal at current step.
///
/// Signal reconstructed at previous iteration
- /// Reconstructed signal
public float[] Iterate(float[] signal = null)
{
var magPhase = new MagnitudePhaseList() { Magnitudes = _magnitudes };
- if (signal == null)
+ if (signal is null)
{
var spectrumSize = _magnitudes[0].Length;
@@ -87,10 +86,9 @@ public float[] Iterate(float[] signal = null)
}
///
- /// Reconstruct iteratively
+ /// Reconstructs signal from spectrogram iteratively.
///
- ///
- ///
+ /// Number of iterations in Griffin-Lim algorithm
public float[] Reconstruct(int iterations = 20)
{
var reconstructed = Iterate();
diff --git a/NWaves/Operations/HarmonicPercussiveSeparator.cs b/NWaves/Operations/HarmonicPercussiveSeparator.cs
index 9d6311a..b070ed2 100644
--- a/NWaves/Operations/HarmonicPercussiveSeparator.cs
+++ b/NWaves/Operations/HarmonicPercussiveSeparator.cs
@@ -6,42 +6,42 @@
namespace NWaves.Operations
{
+ // D.Fitzgerald. Harmonic/percussive separation using median filtering.
+ // 13th International Conference on Digital Audio Effects (DAFX10), Graz, Austria, 2010.
+
///
- /// HPS based on median filtering.
- ///
- /// D.Fitzgerald. Harmonic/percussive separation using median filtering.
- /// 13th International Conference on Digital Audio Effects (DAFX10), Graz, Austria, 2010.
+ /// Represents harmonic/percussive separator based on median filtering.
///
public class HarmonicPercussiveSeparator
{
///
- /// Internal STFT transformer
+ /// Internal STFT transformer.
///
private readonly Stft _stft;
///
- /// Masking function
+ /// Masking function.
///
private readonly Func _mask;
///
- /// Median filter for time axis
+ /// Median filter along time axis.
///
private readonly MedianFilter _medianHarmonic;
///
- /// Median filter for frequency axis
+ /// Median filter along frequency axis.
///
private readonly MedianFilter _medianPercussive;
///
- /// Constructor
+ /// Constructs .
///
- ///
- ///
- ///
- ///
- ///
+ /// FFT size
+ /// Hop length (number of samples)
+ /// Size of median filter along time axis
+ /// Size of median filter along frequency axis
+ /// Masking mode
public HarmonicPercussiveSeparator(int fftSize = 2048,
int hopSize = 512,
int harmonicWinSize = 17,
@@ -68,11 +68,9 @@ public HarmonicPercussiveSeparator(int fftSize = 2048,
}
///
- /// Evaluate harmonic and percussive mag-phase spectrograms from given signal.
+ /// Evaluates harmonic and percussive mag-phase spectrograms from given .
/// Both spectrogram objects share the same phase array.
///
- ///
- ///
public (MagnitudePhaseList, MagnitudePhaseList) EvaluateSpectrograms(DiscreteSignal signal)
{
// spectrogram memory will be reused for harmonic magnitudes
@@ -131,10 +129,8 @@ public HarmonicPercussiveSeparator(int fftSize = 2048,
}
///
- /// Evaluate harmonic and percussive signals from given signal
+ /// Extracts harmonic and percussive signals from given .
///
- ///
- /// Harmonic signal and percussive signal
public (DiscreteSignal, DiscreteSignal) EvaluateSignals(DiscreteSignal signal)
{
var (harmonicSpectrogram, percussiveSpectrogram) = EvaluateSpectrograms(signal);
@@ -158,7 +154,7 @@ public HarmonicPercussiveSeparator(int fftSize = 2048,
}
///
- /// Masking mode for HPS algorithm
+ /// Masking modes for HPS algorithm.
///
public enum HpsMasking
{
diff --git a/NWaves/Operations/Modulator.cs b/NWaves/Operations/Modulator.cs
index da0eaca..c687bda 100644
--- a/NWaves/Operations/Modulator.cs
+++ b/NWaves/Operations/Modulator.cs
@@ -7,24 +7,22 @@
namespace NWaves.Operations
{
///
- /// Class providing modulation methods:
- ///
- /// - ring
- /// - amplitude
- /// - frequency
- /// - phase
- ///
+ /// Provides various modulation methods:
+ ///
+ /// - ring
+ /// - amplitude
+ /// - frequency
+ /// - phase
+ ///
///
public class Modulator
{
///
- /// Ring modulation (RM)
+ /// Does ring modulation (RM) and returns RM signal.
///
/// Carrier signal
/// Modulator signal
- /// RM signal
- public DiscreteSignal Ring(DiscreteSignal carrier,
- DiscreteSignal modulator)
+ public static DiscreteSignal Ring(DiscreteSignal carrier, DiscreteSignal modulator)
{
if (carrier.SamplingRate != modulator.SamplingRate)
{
@@ -36,15 +34,14 @@ public DiscreteSignal Ring(DiscreteSignal carrier,
}
///
- /// Amplitude modulation (AM)
+ /// Does amplitude modulation (AM) and returns AM signal.
///
/// Carrier signal
/// Modulator frequency
/// Modulation index (depth)
- /// AM signal
- public DiscreteSignal Amplitude(DiscreteSignal carrier,
- float modulatorFrequency = 20/*Hz*/,
- float modulationIndex = 0.5f)
+ public static DiscreteSignal Amplitude(DiscreteSignal carrier,
+ float modulatorFrequency = 20/*Hz*/,
+ float modulationIndex = 0.5f)
{
var fs = carrier.SamplingRate;
var mf = modulatorFrequency; // just short aliases //
@@ -57,17 +54,16 @@ public DiscreteSignal Amplitude(DiscreteSignal carrier,
}
///
- /// Frequency modulation (FM)
+ /// Does frequency modulation (FM) and returns FM signal.
///
/// Baseband signal
/// Carrier amplitude
/// Carrier frequency
/// Frequency deviation
- /// RM signal
- public DiscreteSignal Frequency(DiscreteSignal baseband,
- float carrierAmplitude,
- float carrierFrequency,
- float deviation = 0.1f/*Hz*/)
+ public static DiscreteSignal Frequency(DiscreteSignal baseband,
+ float carrierAmplitude,
+ float carrierFrequency,
+ float deviation = 0.1f/*Hz*/)
{
var fs = baseband.SamplingRate;
var ca = carrierAmplitude; // just short aliases //
@@ -82,7 +78,7 @@ public DiscreteSignal Frequency(DiscreteSignal baseband,
}
///
- /// Sinusoidal frequency modulation (FM)
+ /// Does sinusoidal frequency modulation (FM) and returns sinusoidal FM signal.
///
/// Carrier signal frequency
/// Carrier signal amplitude
@@ -90,8 +86,7 @@ public DiscreteSignal Frequency(DiscreteSignal baseband,
/// Modulation index (depth)
/// Length of FM signal
/// Sampling rate
- /// Sinusoidal FM signal
- public DiscreteSignal FrequencySinusoidal(
+ public static DiscreteSignal FrequencySinusoidal(
float carrierFrequency,
float carrierAmplitude,
float modulatorFrequency,
@@ -113,15 +108,14 @@ public DiscreteSignal FrequencySinusoidal(
}
///
- /// Linear frequency modulation (FM)
+ /// Does linear frequency modulation (FM) and returns FM signal.
///
/// Carrier signal frequency
/// Carrier signal amplitude
/// Modulation index (depth)
/// Length of FM signal
/// Sampling rate
- /// Sinusoidal FM signal
- public DiscreteSignal FrequencyLinear(
+ public static DiscreteSignal FrequencyLinear(
float carrierFrequency,
float carrierAmplitude,
float modulationIndex,
@@ -140,17 +134,16 @@ public DiscreteSignal FrequencyLinear(
}
///
- /// Phase modulation (PM)
+ /// Does phase modulation (PM) and returns PM signal.
///
/// Baseband signal
/// Carrier amplitude
/// Carrier frequency
/// Frequency deviation
- /// RM signal
- public DiscreteSignal Phase(DiscreteSignal baseband,
- float carrierAmplitude,
- float carrierFrequency,
- float deviation = 0.8f)
+ public static DiscreteSignal Phase(DiscreteSignal baseband,
+ float carrierAmplitude,
+ float carrierFrequency,
+ float deviation = 0.8f)
{
var fs = baseband.SamplingRate;
var ca = carrierAmplitude; // just short aliases //
@@ -163,57 +156,29 @@ public DiscreteSignal Phase(DiscreteSignal baseband,
}
///
- /// Simple amplitude demodulation based on Hilbert transform
+ /// Does simple amplitude demodulation of based on Hilbert transform.
///
- ///
- ///
- public DiscreteSignal DemodulateAmplitude(DiscreteSignal signal)
+ public static DiscreteSignal DemodulateAmplitude(DiscreteSignal signal)
{
var ht = new HilbertTransform(signal.Length);
- var mag = ht.AnalyticSignal(signal.Samples).Magnitude();
+ var mag = ht.AnalyticSignal(signal.Samples).Magnitude;
- return new DiscreteSignal(signal.SamplingRate, mag) - 1.0f;
+ return new DiscreteSignal(signal.SamplingRate, mag.ToFloats()) - 1.0f;
}
///
- /// Simple frequency demodulation based on Hilbert transform
+ /// Does simple frequency demodulation pf based on Hilbert transform.
///
- ///
- ///
- public DiscreteSignal DemodulateFrequency(DiscreteSignal signal)
+ public static DiscreteSignal DemodulateFrequency(DiscreteSignal signal)
{
var diff = new float[signal.Length];
MathUtils.Diff(signal.Samples, diff);
var ht = new HilbertTransform(signal.Length);
- var mag = ht.AnalyticSignal(diff).Magnitude();
-
- return new DiscreteSignal(signal.SamplingRate, mag) - 1.0f;
- }
- }
-
- ///
- /// Class with extension methods for .
- ///
- public static class ModulatorExtensions
- {
- ///
- /// Create array of magnitudes of complex numbers given as tuple of arrays (real and imaginary parts).
- ///
- /// Tuple of real-valued arrays (real and imaginary parts)
- public static float[] Magnitude(this (float[], float[]) signal)
- {
- var (real, imag) = signal;
-
- var magnitude = new float[real.Length];
-
- for (var i = 0; i < magnitude.Length; i++)
- {
- magnitude[i] = (float)Math.Sqrt(real[i] * real[i] + imag[i] * imag[i]);
- }
+ var mag = ht.AnalyticSignal(diff).Magnitude;
- return magnitude;
+ return new DiscreteSignal(signal.SamplingRate, mag.ToFloats()) - 1.0f;
}
}
}
diff --git a/NWaves/Operations/Operation.cs b/NWaves/Operations/Operation.cs
index e7d9c37..9a9ead0 100644
--- a/NWaves/Operations/Operation.cs
+++ b/NWaves/Operations/Operation.cs
@@ -11,89 +11,72 @@
namespace NWaves.Operations
{
///
- /// Static class for DSP/audio operations.
- ///
- /// Main operations implemented:
- ///
- /// - convolution
- /// - cross-correlation
- /// - block convolution
- /// - deconvolution
- /// - resampling
- /// - time-stretching
- /// - rectification
- /// - envelope detection
- /// - spectral subtraction
- /// - normalization (peak / RMS)
- /// - periodogram (Welch / Lomb-Scargle)
- ///
+ /// Provides methods for various DSP/audio operations:
+ ///
+ /// - convolution
+ /// - cross-correlation
+ /// - block convolution
+ /// - deconvolution
+ /// - resampling
+ /// - time-stretching
+ /// - rectification
+ /// - envelope detection
+ /// - spectral subtraction
+ /// - normalization (peak / RMS)
+ /// - periodogram (Welch / Lomb-Scargle)
+ ///
///
public static class Operation
{
///
- /// Fast convolution via FFT of real-valued signals.
+ /// Does fast convolution of with via FFT.
///
- /// Signal
- /// Convolution kernel
- /// Convolution of signal with kernel
public static DiscreteSignal Convolve(DiscreteSignal signal, DiscreteSignal kernel)
{
return new Convolver().Convolve(signal, kernel);
}
///
- /// Fast convolution via FFT for general complex-valued case
+ /// Does fast convolution of with via FFT.
///
- /// Signal
- /// Convolution kernel
- /// Convolution of signal with kernel
public static ComplexDiscreteSignal Convolve(ComplexDiscreteSignal signal, ComplexDiscreteSignal kernel)
{
return new ComplexConvolver().Convolve(signal, kernel);
}
///
- /// Fast convolution for double arrays (used mainly in filter design)
+ /// Does fast convolution of with via FFT.
///
- /// Array of samples
- /// Convolution kernel
- /// Convolution of signal with kernel
- public static double[] Convolve(double[] input, double[] kernel)
+ public static double[] Convolve(double[] signal, double[] kernel)
{
- return Convolve(new ComplexDiscreteSignal(1, input),
+ return Convolve(new ComplexDiscreteSignal(1, signal),
new ComplexDiscreteSignal(1, kernel)).Real;
}
///
- /// Fast cross-correlation via FFT
+ /// Does fast cross-correlation between and via FFT.
///
- /// First signal
- /// Second signal
- /// Cross-correlation between the first and the second signal
public static DiscreteSignal CrossCorrelate(DiscreteSignal signal1, DiscreteSignal signal2)
{
return new Convolver().CrossCorrelate(signal1, signal2);
}
///
- /// Fast complex cross-correlation via FFT
+ /// Does fast cross-correlation between and via FFT.
///
- /// First signal
- /// Second signal
- /// Cross-correlation between the first and the second signal
public static ComplexDiscreteSignal CrossCorrelate(ComplexDiscreteSignal signal1, ComplexDiscreteSignal signal2)
{
return new ComplexConvolver().CrossCorrelate(signal1, signal2);
}
///
- /// Method implements block convolution of signals (using either OLA or OLS algorithm)
+ /// Does block convolution of with
+ /// (using either Overlap-Add or Overlap-Save algorithm).
///
/// Signal
/// Convolution kernel
/// FFT size
/// Block convolution method (OverlapAdd / OverlapSave)
- /// Result of block convolution of signal with kernel
public static DiscreteSignal BlockConvolve(DiscreteSignal signal,
DiscreteSignal kernel,
int fftSize,
@@ -112,81 +95,71 @@ public static DiscreteSignal BlockConvolve(DiscreteSignal signal,
return blockConvolver.ApplyTo(signal);
}
-
+
///
- /// Deconvolution via FFT for general complex-valued case.
- ///
- /// NOTE!
- ///
- /// Deconvolution is an experimental feature.
- /// It's problematic due to division by zero.
- ///
+ /// Deconvolves and .
///
/// Signal
/// Kernel
- /// Deconvolved signal
public static ComplexDiscreteSignal Deconvolve(ComplexDiscreteSignal signal, ComplexDiscreteSignal kernel)
{
return new ComplexConvolver().Deconvolve(signal, kernel);
}
///
- /// Interpolation followed by low-pass filtering
+ /// Does interpolation of followed by lowpass filtering.
///
/// Signal
/// Interpolation factor (e.g. factor=2 if 8000 Hz -> 16000 Hz)
- /// Low-pass anti-aliasing filter
- /// Interpolated signal
+ /// Lowpass anti-aliasing filter
public static DiscreteSignal Interpolate(DiscreteSignal signal, int factor, FirFilter filter = null)
{
return new Resampler().Interpolate(signal, factor, filter);
}
///
- /// Decimation preceded by low-pass filtering
+ /// Does decimation of preceded by lowpass filtering.
///
/// Signal
/// Decimation factor (e.g. factor=2 if 16000 Hz -> 8000 Hz)
- /// Low-pass anti-aliasing filter
- /// Decimated signal
+ /// Lowpass anti-aliasing filter
public static DiscreteSignal Decimate(DiscreteSignal signal, int factor, FirFilter filter = null)
{
return new Resampler().Decimate(signal, factor, filter);
}
///
- /// Band-limited resampling
+ /// Does band-limited resampling of .
///
/// Signal
/// Desired sampling rate
- /// Low-pass anti-aliasing filter
- /// Resampled signal
- public static DiscreteSignal Resample(DiscreteSignal signal, int newSamplingRate, FirFilter filter = null)
+ /// Lowpass anti-aliasing filter
+ /// Order
+ public static DiscreteSignal Resample(DiscreteSignal signal, int newSamplingRate, FirFilter filter = null, int order = 15)
{
- return new Resampler().Resample(signal, newSamplingRate, filter);
+ return new Resampler().Resample(signal, newSamplingRate, filter, order);
}
///
- /// Simple resampling (as the combination of interpolation and decimation)
+ /// Does simple resampling of (as the combination of interpolation and decimation).
///
/// Input signal
/// Interpolation factor
/// Decimation factor
- /// Resampled signal
- public static DiscreteSignal ResampleUpDown(DiscreteSignal signal, int up, int down)
+ /// Lowpass anti-aliasing filter
+ public static DiscreteSignal ResampleUpDown(DiscreteSignal signal, int up, int down, FirFilter filter = null)
{
- return new Resampler().ResampleUpDown(signal, up, down);
+ return new Resampler().ResampleUpDown(signal, up, down, filter);
}
///
- /// Time stretching with parameters set by user
+ /// Does time stretching of with parameters set by user.
///
/// Signal
/// Stretch factor (ratio)
/// Window size (for vocoders - FFT size)
- /// Hop size
- /// Algorithm for TSM (optional)
- /// Time stretched signal
+ /// Hop length
+ /// Algorithm for TSM
public static DiscreteSignal TimeStretch(DiscreteSignal signal,
double stretch,
int windowSize,
@@ -220,12 +193,11 @@ public static DiscreteSignal TimeStretch(DiscreteSignal signal,
}
///
- /// Time stretching with auto-derived parameters
+ /// Does time stretching of with auto-derived parameters.
///
/// Signal
/// Stretch factor (ratio)
- /// Algorithm for TSM (optional)
- /// Time stretched signal
+ /// Algorithm for TSM
public static DiscreteSignal TimeStretch(DiscreteSignal signal,
double stretch,
TsmAlgorithm algorithm = TsmAlgorithm.PhaseVocoderPhaseLocking)
@@ -259,12 +231,11 @@ public static DiscreteSignal TimeStretch(DiscreteSignal signal,
}
///
- /// Method for extracting the envelope of a signal
+ /// Extracts the envelope of .
///
/// Signal
/// Attack time (in seconds)
/// Release time (in seconds)
- /// Signal envelope
public static DiscreteSignal Envelope(DiscreteSignal signal, float attackTime = 0.01f, float releaseTime = 0.05f)
{
var envelopeFollower = new EnvelopeFollower(signal.SamplingRate, attackTime, releaseTime);
@@ -273,10 +244,8 @@ public static DiscreteSignal Envelope(DiscreteSignal signal, float attackTime =
}
///
- /// Full rectification
+ /// Full-rectifies .
///
- /// Signal
- /// Fully rectified signal
public static DiscreteSignal FullRectify(DiscreteSignal signal)
{
return new DiscreteSignal(signal.SamplingRate,
@@ -284,10 +253,8 @@ public static DiscreteSignal FullRectify(DiscreteSignal signal)
}
///
- /// Half rectification
+ /// Half-rectifies .
///
- /// Signal
- /// Half rectified signal
public static DiscreteSignal HalfRectify(DiscreteSignal signal)
{
return new DiscreteSignal(signal.SamplingRate,
@@ -295,23 +262,23 @@ public static DiscreteSignal HalfRectify(DiscreteSignal signal)
}
///
- /// Spectral subtraction
+ /// De-noises using spectral subtraction.
+ /// Subtracts from .
///
/// Signal
/// Noise signal
/// FFT size
/// Hop size (number of samples)
- /// De-noised signal
public static DiscreteSignal SpectralSubtract(DiscreteSignal signal,
DiscreteSignal noise,
int fftSize = 1024,
- int hopSize = 410)
+ int hopSize = 256)
{
return new SpectralSubtractor(noise, fftSize, hopSize).ApplyTo(signal);
}
///
- /// Peak normalization
+ /// Normalizes peak level.
///
/// Samples
/// Peak level in decibels (dbFS), e.g. -1dB, -3dB, etc.
@@ -326,7 +293,7 @@ public static void NormalizePeak(float[] samples, double peakDb)
}
///
- /// Peak normalization
+ /// Normalizes peak level.
///
/// Signal
/// Peak level in decibels (dBFS), e.g. -1dB, -3dB, etc.
@@ -338,7 +305,7 @@ public static DiscreteSignal NormalizePeak(DiscreteSignal signal, double peakDb)
}
///
- /// Change peak level relatively to input samples (in-place)
+ /// Changes peak level relatively to input (in-place).
///
/// Samples
/// Peak change in decibels, e.g. -6dB - decrease peak level twice
@@ -353,7 +320,7 @@ public static void ChangePeak(float[] samples, double peakDb)
}
///
- /// Change peak level relatively to input signal
+ /// Changes peak level relatively to input .
///
/// Signal
/// Peak change in decibels, e.g. -6dB - decrease peak level twice
@@ -365,7 +332,7 @@ public static DiscreteSignal ChangePeak(DiscreteSignal signal, double peakDb)
}
///
- /// RMS normalization
+ /// Normalizes RMS.
///
/// Samples
/// RMS in decibels (dBFS), e.g. -6dB, -18dB, -26dB, etc.
@@ -387,7 +354,7 @@ public static void NormalizeRms(float[] samples, double rmsDb)
}
///
- /// RMS normalization
+ /// Normalizes RMS.
///
/// Signal
/// RMS in decibels (dBFS), e.g. -6dB, -18dB, -26dB, etc.
@@ -399,7 +366,7 @@ public static DiscreteSignal NormalizeRms(DiscreteSignal signal, double rmsDb)
}
///
- /// Change RMS relatively to input samples
+ /// Changes RMS relatively to input .
///
/// Samples
/// RMS change in decibels, e.g. -6dB - decrease RMS twice
@@ -425,7 +392,7 @@ public static void ChangeRms(float[] samples, double rmsDb)
}
///
- /// Change RMS relatively to input signal
+ /// Changes RMS relatively to input .
///
/// Signal
/// RMS change in decibels, e.g. -6dB - decrease RMS twice
@@ -437,7 +404,8 @@ public static DiscreteSignal ChangeRms(DiscreteSignal signal, double rmsDb)
}
///
- /// Welch periodogram
+ /// Computes periodogram using Welch's method.
+ /// If =0 then power spectrum is evaluated, otherwise power spectral density is evaluated.
///
/// Signal
/// Window size (number of samples)
@@ -445,7 +413,6 @@ public static DiscreteSignal ChangeRms(DiscreteSignal signal, double rmsDb)
/// Windowing function
/// FFT size
/// If sampling rate=0 then power spectrum is evaluated, otherwise power spectral density is evaluated
- /// Welch periodogram
public static float[] Welch(DiscreteSignal signal,
int windowSize = 1024,
int hopSize = 256,
@@ -481,14 +448,13 @@ public static float[] Welch(DiscreteSignal signal,
}
///
- /// Lomb-Scargle periodogram
+ /// Computes the Lomb-Scargle periodogram.
///
/// Sample times
/// Signal values at sample times
/// Angular frequencies for output periodogram
/// Subtract mean from values before periodogram evaluation
/// Normalize periodogram by the residuals of the data around a constant reference model(at zero)
- /// Lomb-Scargle periodogram
public static float[] LombScargle(float[] x,
float[] y,
float[] freqs,
@@ -566,9 +532,6 @@ public static float[] LombScargle(float[] x,
///
/// Direct convolution by formula in time domain
///
- ///
- ///
- ///
public static DiscreteSignal ConvolveDirect(DiscreteSignal signal1, DiscreteSignal signal2)
{
var a = signal1.Samples;
@@ -594,9 +557,6 @@ public static DiscreteSignal ConvolveDirect(DiscreteSignal signal1, DiscreteSign
///
/// Direct cross-correlation by formula in time domain
///
- ///
- ///
- ///
public static DiscreteSignal CrossCorrelateDirect(DiscreteSignal signal1, DiscreteSignal signal2)
{
var a = signal1.Samples;
diff --git a/NWaves/Operations/Resampler.cs b/NWaves/Operations/Resampler.cs
index b10ec54..106e4ed 100644
--- a/NWaves/Operations/Resampler.cs
+++ b/NWaves/Operations/Resampler.cs
@@ -7,23 +7,23 @@
namespace NWaves.Operations
{
///
- /// Class responsible for sampling rate conversion
+ /// Represents signal resampler (sampling rate converter).
///
public class Resampler
{
///
- /// The order of FIR LP resampling filter (minimally required).
- /// This constant should be used for simple up/down ratios.
+ /// Gets or sets the order of lowpass anti-aliasing FIR filter
+ /// that will be created automatically if the filter is not specified explicitly.
+ /// By default, 101.
///
- private const int MinResamplingFilterOrder = 101;
+ public int MinResamplingFilterOrder { get; set; } = 101;
///
- /// Interpolation followed by low-pass filtering
+ /// Does interpolation of followed by lowpass filtering.
///
- ///
- ///
- ///
- ///
+ /// Signal
+ /// Interpolation factor (e.g. factor=2 if 8000 Hz -> 16000 Hz)
+ /// Lowpass anti-aliasing filter
public DiscreteSignal Interpolate(DiscreteSignal signal, int factor, FirFilter filter = null)
{
if (factor == 1)
@@ -42,7 +42,7 @@ public DiscreteSignal Interpolate(DiscreteSignal signal, int factor, FirFilter f
var lpFilter = filter;
- if (filter == null)
+ if (filter is null)
{
var filterSize = factor > MinResamplingFilterOrder / 2 ?
2 * factor + 1 :
@@ -55,12 +55,11 @@ public DiscreteSignal Interpolate(DiscreteSignal signal, int factor, FirFilter f
}
///
- /// Decimation preceded by low-pass filtering
+ /// Does decimation of preceded by lowpass filtering.
///
- ///
- ///
- ///
- ///
+ /// Signal
+ /// Decimation factor (e.g. factor=2 if 16000 Hz -> 8000 Hz)
+ /// Lowpass anti-aliasing filter
public DiscreteSignal Decimate(DiscreteSignal signal, int factor, FirFilter filter = null)
{
if (factor == 1)
@@ -72,11 +71,9 @@ public DiscreteSignal Decimate(DiscreteSignal signal, int factor, FirFilter filt
2 * factor + 1 :
MinResamplingFilterOrder;
- var lpFilter = filter;
-
- if (filter == null)
+ if (filter is null)
{
- lpFilter = new FirFilter(DesignFilter.FirWinLp(filterSize, 0.5f / factor));
+ var lpFilter = new FirFilter(DesignFilter.FirWinLp(filterSize, 0.5f / factor));
signal = lpFilter.ApplyTo(signal);
}
@@ -94,13 +91,12 @@ public DiscreteSignal Decimate(DiscreteSignal signal, int factor, FirFilter filt
}
///
- /// Band-limited resampling
+ /// Does band-limited resampling of .
///
- ///
- ///
- ///
- ///
- ///
+ /// Signal
+ /// Desired sampling rate
+ /// Lowpass anti-aliasing filter
+ /// Order
public DiscreteSignal Resample(DiscreteSignal signal,
int newSamplingRate,
FirFilter filter = null,
@@ -116,7 +112,7 @@ public DiscreteSignal Resample(DiscreteSignal signal,
var input = signal.Samples;
var output = new float[(int)(input.Length * g)];
- if (g < 1 && filter == null)
+ if (g < 1 && filter is null)
{
filter = new FirFilter(DesignFilter.FirWinLp(MinResamplingFilterOrder, g / 2));
@@ -149,13 +145,12 @@ public DiscreteSignal Resample(DiscreteSignal signal,
}
///
- /// Simple resampling as the combination of interpolation and decimation.
+ /// Does simple resampling of (as the combination of interpolation and decimation).
///
- ///
- ///
- ///
- ///
- ///
+ /// Input signal
+ /// Interpolation factor
+ /// Decimation factor
+ /// Lowpass anti-aliasing filter
public DiscreteSignal ResampleUpDown(DiscreteSignal signal, int up, int down, FirFilter filter = null)
{
if (up == down)
@@ -181,7 +176,7 @@ public DiscreteSignal ResampleUpDown(DiscreteSignal signal, int up, int down, Fi
var lpFilter = filter;
- if (filter == null)
+ if (filter is null)
{
var factor = Math.Max(up, down);
var filterSize = factor > MinResamplingFilterOrder / 2 ?
diff --git a/NWaves/Operations/SpectralSubtractor.cs b/NWaves/Operations/SpectralSubtractor.cs
index bca42c6..5e4c4da 100644
--- a/NWaves/Operations/SpectralSubtractor.cs
+++ b/NWaves/Operations/SpectralSubtractor.cs
@@ -5,25 +5,44 @@
namespace NWaves.Operations
{
+ // Spectral subtraction algorithm:
+ //
+ // [1979] M. Berouti, R. Schwartz, J. Makhoul
+ // "Enhancement of Speech Corrupted by Acoustic Noise".
+ //
+
///
- /// Class that implements Spectral subtraction algorithm according to
- ///
- /// [1979] M. Berouti, R. Schwartz, J. Makhoul
- /// "Enhancement of Speech Corrupted by Acoustic Noise".
- ///
+ /// Represents spectral subtraction filter.
///
public class SpectralSubtractor : OverlapAddFilter
{
- // Algorithm parameters
-
+ ///
+ /// Gets or sets spectral floor (beta coefficient).
+ ///
public float Beta { get; set; } = 0.009f;
+
+ ///
+ /// Gets or sets min threshold for subtraction factor (alpha).
+ ///
public float AlphaMin { get; set; } = 2f;
+
+ ///
+ /// Gets or sets max threshold for subtraction factor (alpha).
+ ///
public float AlphaMax { get; set; } = 5f;
+
+ ///
+ /// Gets or sets min SNR value (in dB).
+ ///
public float SnrMin { get; set; } = -5f;
+
+ ///
+ /// Gets or sets max SNR value (in dB).
+ ///
public float SnrMax { get; set; } = 20f;
///
- /// Noise estimate
+ /// Noise estimate.
///
private readonly float[] _noiseEstimate;
@@ -34,11 +53,11 @@ public class SpectralSubtractor : OverlapAddFilter
private readonly float[] _noiseAcc;
///
- /// Constructor from float[] noise
+ /// Constructs .
///
- ///
- ///
- ///
+ /// Array of noise samples
+ /// FFT size
+ /// Hop length (number of samples)
public SpectralSubtractor(float[] noise, int fftSize = 1024, int hopSize = 128) : base(hopSize, fftSize)
{
_noiseEstimate = new float[_fftSize / 2 + 1];
@@ -50,18 +69,18 @@ public SpectralSubtractor(float[] noise, int fftSize = 1024, int hopSize = 128)
}
///
- /// Constructor from DiscreteSignal noise
+ /// Constructs .
///
- ///
- ///
- ///
+ /// Noise signal
+ /// FFT size
+ /// Hop length (number of samples)
public SpectralSubtractor(DiscreteSignal noise, int fftSize = 1024, int hopSize = 128)
: this(noise.Samples, fftSize, hopSize)
{
}
///
- /// Process one spectrum at each STFT step
+ /// Processes one spectrum at each STFT step.
///
/// Real parts of input spectrum
/// Imaginary parts of input spectrum
@@ -95,11 +114,11 @@ protected override void ProcessSpectrum(float[] re,
}
///
- /// Estimate noise power spectrum
+ /// Estimates power spectrum of .
///
- ///
- ///
- ///
+ /// Array of noise samples
+ /// Index of the first sample in array for processing
+ /// Index of the last sample in array for processing
public void EstimateNoise(float[] noise, int startPos = 0, int endPos = -1)
{
if (endPos < 0)
@@ -130,11 +149,11 @@ public void EstimateNoise(float[] noise, int startPos = 0, int endPos = -1)
}
///
- /// Estimate noise power spectrum
+ /// Estimates power spectrum of signal.
///
- ///
- ///
- ///
+ /// Noise signal
+ /// Index of the first sample in signal
+ /// Index of the last sample in signal
public void EstimateNoise(DiscreteSignal noise, int startPos = 0, int endPos = -1)
{
EstimateNoise(noise.Samples, startPos, endPos);
diff --git a/NWaves/Operations/Tsm/PaulStretch.cs b/NWaves/Operations/Tsm/PaulStretch.cs
index 674ed6e..76deb59 100644
--- a/NWaves/Operations/Tsm/PaulStretch.cs
+++ b/NWaves/Operations/Tsm/PaulStretch.cs
@@ -3,30 +3,29 @@
namespace NWaves.Operations.Tsm
{
///
- /// TSM processor based on Paul stretch algorithm
+ /// Represents TSM processor based on Paul stretch algorithm.
///
class PaulStretch : PhaseVocoder
{
///
- /// Randomizer for phases
+ /// Randomizer for phases.
///
private readonly Random _rand = new Random();
///
- /// Constructor
+ /// Constructs .
///
- ///
- ///
- ///
- public PaulStretch(double stretch, int hopAnalysis, int fftSize = 0)
- : base(stretch, hopAnalysis, fftSize)
+ /// Stretch ratio
+ /// Hop length at analysis stage
+ /// FFT size
+ public PaulStretch(double stretch, int hopAnalysis, int fftSize = 0) : base(stretch, hopAnalysis, fftSize)
{
}
///
- /// Process spectrum at each STFT step: simply randomize phases
+ /// Processes spectrum at each STFT step: simply randomizes phases.
///
- public override void ProcessSpectrum()
+ protected override void ProcessSpectrum()
{
for (var j = 1; j <= _fftSize / 2; j++)
{
@@ -39,7 +38,7 @@ public override void ProcessSpectrum()
}
///
- /// Reset (nothing to do here)
+ /// Resets TSM processor.
///
public override void Reset()
{
diff --git a/NWaves/Operations/Tsm/PhaseLockingVocoder.cs b/NWaves/Operations/Tsm/PhaseLockingVocoder.cs
index a239041..dccabc2 100644
--- a/NWaves/Operations/Tsm/PhaseLockingVocoder.cs
+++ b/NWaves/Operations/Tsm/PhaseLockingVocoder.cs
@@ -4,39 +4,37 @@
namespace NWaves.Operations.Tsm
{
///
- /// Phase vocoder with identity phase locking [Puckette].
+ /// Represents Phase Vocoder with identity phase locking [Puckette].
///
public class PhaseLockingVocoder : PhaseVocoder
{
///
- /// Array of spectrum magnitudes (at current step)
+ /// Array of spectrum magnitudes (at current step).
///
private readonly double[] _mag;
///
- /// Array of spectrum phases (at current step)
+ /// Array of spectrum phases (at current step).
///
private readonly double[] _phase;
///
- /// Array of phase deltas
+ /// Array of phase deltas.
///
private readonly double[] _delta;
///
- /// Array of peak positions (indices)
+ /// Array of peak positions (indices).
///
private readonly int[] _peaks;
///
- /// Constructor
+ /// Constructs .
///
- ///
- ///
- ///
- ///
- public PhaseLockingVocoder(double stretch, int hopAnalysis, int fftSize = 0)
- : base(stretch, hopAnalysis, fftSize)
+ /// Stretch ratio
+ /// Hop length at analysis stage
+ /// FFT size
+ public PhaseLockingVocoder(double stretch, int hopAnalysis, int fftSize = 0) : base(stretch, hopAnalysis, fftSize)
{
_mag = new double[_fftSize / 2 + 1];
_phase = new double[_fftSize / 2 + 1];
@@ -45,9 +43,9 @@ public PhaseLockingVocoder(double stretch, int hopAnalysis, int fftSize = 0)
}
///
- /// Process spectrum with phase-locking at each STFT step
+ /// Processes spectrum with phase-locking at each STFT step.
///
- public override void ProcessSpectrum()
+ protected override void ProcessSpectrum()
{
for (var j = 0; j < _mag.Length; j++)
{
diff --git a/NWaves/Operations/Tsm/PhaseVocoder.cs b/NWaves/Operations/Tsm/PhaseVocoder.cs
index c1ebf5d..5a78ed2 100644
--- a/NWaves/Operations/Tsm/PhaseVocoder.cs
+++ b/NWaves/Operations/Tsm/PhaseVocoder.cs
@@ -9,37 +9,37 @@
namespace NWaves.Operations.Tsm
{
///
- /// Conventional Phase Vocoder
+ /// Represents Phase Vocoder.
///
public class PhaseVocoder : IFilter
{
///
- /// Hop size at analysis stage (STFT decomposition)
+ /// Hop size at analysis stage (STFT decomposition).
///
protected readonly int _hopAnalysis;
///
- /// Hop size at synthesis stage (STFT merging)
+ /// Hop size at synthesis stage (STFT merging).
///
protected readonly int _hopSynthesis;
///
- /// Size of FFT for analysis and synthesis
+ /// Size of FFT for analysis and synthesis.
///
protected readonly int _fftSize;
///
- /// Stretch ratio
+ /// Stretch ratio.
///
protected readonly double _stretch;
///
- /// Internal FFT transformer
+ /// Internal FFT transformer.
///
protected readonly RealFft _fft;
///
- /// Window coefficients
+ /// Window coefficients.
///
protected readonly float[] _window;
@@ -49,36 +49,36 @@ public class PhaseVocoder : IFilter
protected readonly float _gain;
///
- /// Linearly spaced frequencies
+ /// Linearly spaced frequencies.
///
protected readonly double[] _omega;
///
- /// Internal buffer for real parts of analyzed block
+ /// Internal buffer for real parts of analyzed block.
///
protected readonly float[] _re;
///
- /// Internal buffer for imaginary parts of analyzed block
+ /// Internal buffer for imaginary parts of analyzed block.
///
protected readonly float[] _im;
///
- /// Array of phases computed at previous step
+ /// Array of phases computed at previous step.
///
protected readonly double[] _prevPhase;
///
- /// Array of new synthesized phases
+ /// Array of new synthesized phases.
///
protected readonly double[] _phaseTotal;
///
- /// Constructor
+ /// Constructs .
///
- ///
- ///
- ///
+ /// Stretch ratio
+ /// Hop length at analysis stage
+ /// FFT size
public PhaseVocoder(double stretch, int hopAnalysis, int fftSize = 0)
{
_stretch = stretch;
@@ -104,13 +104,9 @@ public PhaseVocoder(double stretch, int hopAnalysis, int fftSize = 0)
}
///
- /// Phase Vocoder algorithm
+ /// Processes entire and returns new time-stretched signal.
///
- ///
- ///
- ///
- public DiscreteSignal ApplyTo(DiscreteSignal signal,
- FilteringMethod method = FilteringMethod.Auto)
+ public DiscreteSignal ApplyTo(DiscreteSignal signal, FilteringMethod method = FilteringMethod.Auto)
{
var input = signal.Samples;
var output = new float[(int)(input.Length * _stretch) + _fftSize];
@@ -155,10 +151,10 @@ public DiscreteSignal ApplyTo(DiscreteSignal signal,
}
///
- /// Process one spectrum at each STFT step.
+ /// Processes one spectrum at each STFT step.
/// This routine is different for different PV-based techniques.
///
- public virtual void ProcessSpectrum()
+ protected virtual void ProcessSpectrum()
{
for (var j = 1; j <= _fftSize / 2; j++)
{
@@ -181,7 +177,7 @@ public virtual void ProcessSpectrum()
}
///
- /// Reset phase vocoder
+ /// Resets phase vocoder.
///
public virtual void Reset()
{
diff --git a/NWaves/Operations/Tsm/TsmAlgorithm.cs b/NWaves/Operations/Tsm/TsmAlgorithm.cs
index c3c78f2..f301b89 100644
--- a/NWaves/Operations/Tsm/TsmAlgorithm.cs
+++ b/NWaves/Operations/Tsm/TsmAlgorithm.cs
@@ -1,27 +1,27 @@
namespace NWaves.Operations.Tsm
{
///
- /// Algorithm for time scale modification
+ /// Time scale modification algorithms.
///
public enum TsmAlgorithm
{
///
- /// Phase vocoder
+ /// Phase vocoder.
///
PhaseVocoder = 0,
///
- /// Phase vocoder with phase-locking
+ /// Phase vocoder with phase-locking.
///
PhaseVocoderPhaseLocking = 1,
///
- /// Waveform similarity-based Synchrnoized Overlap-Add
+ /// Waveform similarity-based Synchrnoized Overlap-Add.
///
Wsola = 2,
///
- /// Paul stretch
+ /// Paul stretch.
///
PaulStretch = 3
}
diff --git a/NWaves/Operations/Tsm/Wsola.cs b/NWaves/Operations/Tsm/Wsola.cs
index 8cedbb9..9a5d8c2 100644
--- a/NWaves/Operations/Tsm/Wsola.cs
+++ b/NWaves/Operations/Tsm/Wsola.cs
@@ -9,57 +9,58 @@
namespace NWaves.Operations.Tsm
{
///
- /// Waveform-Synchronized Overlap-Add
+ /// Represents TSM processor based on Waveform-Synchronized Overlap-Add (WSOLA) technique.
///
public class Wsola : IFilter
{
///
- /// Stretch ratio
+ /// Stretch ratio.
///
protected readonly double _stretch;
///
- /// Window size
+ /// Window size.
///
private int _windowSize;
///
- /// Hop size at analysis stage (STFT decomposition)
+ /// Hop size at analysis stage (STFT decomposition).
///
private int _hopAnalysis;
///
- /// Hop size at synthesis stage (STFT merging)
+ /// Hop size at synthesis stage (STFT merging).
///
private int _hopSynthesis;
///
- /// Maximum length of the fragment for search of the most similar waveform
+ /// Maximum length of the fragment for search of the most similar waveform.
///
private int _maxDelta;
///
- /// True if parameters were set by user (not by default)
+ /// True if parameters were set by user (not by default).
///
private readonly bool _userParameters;
///
/// Internal convolver
- /// (will be used for evaluating auto-correlation if the window size is too big)
+ /// (will be used for evaluating auto-correlation if the window size is too big).
///
private Convolver _convolver;
///
- /// Cross-correlation signal
+ /// Cross-correlation signal.
///
private float[] _cc;
-
///
- /// Constructor with detailed WSOLA settings
+ /// Constructs TSM processor.
///
/// Stretch ratio
- ///
+ /// Window size
+ /// Hop size at analysis stage
+ /// Max delta in WSOLA algorithm
public Wsola(double stretch, int windowSize, int hopAnalysis, int maxDelta = 0)
{
_stretch = stretch;
@@ -74,9 +75,9 @@ public Wsola(double stretch, int windowSize, int hopAnalysis, int maxDelta = 0)
}
///
- /// Constructor with smart parameter autoderivation
+ /// Constructs TSM processor and auto-derives WSOLA parameters for given ratio.
///
- ///
+ /// Stretch ratio
public Wsola(double stretch)
{
_stretch = stretch;
@@ -111,7 +112,7 @@ public Wsola(double stretch)
}
///
- /// For large window sizes prepare the internal convolver
+ /// Prepares the internal convolver (for large window sizes).
///
private void PrepareConvolver()
{
@@ -125,13 +126,9 @@ private void PrepareConvolver()
}
///
- /// WSOLA algorithm
+ /// Processes entire and returns new time-stretched signal.
///
- ///
- ///
- ///
- public DiscreteSignal ApplyTo(DiscreteSignal signal,
- FilteringMethod method = FilteringMethod.Auto)
+ public DiscreteSignal ApplyTo(DiscreteSignal signal, FilteringMethod method = FilteringMethod.Auto)
{
// adjust default parameters for a new sampling rate
@@ -197,20 +194,19 @@ public DiscreteSignal ApplyTo(DiscreteSignal signal,
}
///
- /// Position of the best found waveform similarity
+ /// Finds position of the best waveform similarity.
///
- ///
- ///
- ///
- ///
- public int WaveformSimilarityPos(float[] current, float[] prev, int maxDelta)
+ /// Current window
+ /// Previous window
+ /// Max delta
+ protected int WaveformSimilarityPos(float[] current, float[] prev, int maxDelta)
{
var optimalShift = 0;
var maxCorrelation = 0.0f;
// for small window sizes cross-correlate directly:
- if (_convolver == null)
+ if (_convolver is null)
{
for (var i = 0; i < maxDelta; i++)
{
diff --git a/NWaves/Operations/WaveShaper.cs b/NWaves/Operations/WaveShaper.cs
index b1a2fb1..bffa5b0 100644
--- a/NWaves/Operations/WaveShaper.cs
+++ b/NWaves/Operations/WaveShaper.cs
@@ -4,21 +4,44 @@
namespace NWaves.Operations
{
+ ///
+ /// Represents wave shaper.
+ ///
+ /// Wave shaper is a filter that maps an input signal to the output signal
+ /// by applying arbitrary mathematical function (shaping function) to the input signal.
+ ///
+ ///
public class WaveShaper : IFilter, IOnlineFilter
{
- private readonly Func _waveShaperFunction;
+ private readonly Func _waveShapingFunction;
- public WaveShaper(Func waveShaperFunction)
+ ///
+ /// Constructs using .
+ ///
+ /// Wave shaping function
+ public WaveShaper(Func waveShapingFunction)
{
- _waveShaperFunction = waveShaperFunction;
+ _waveShapingFunction = waveShapingFunction;
}
- public float Process(float input) => _waveShaperFunction(input);
+ ///
+ /// Processes one sample.
+ ///
+ /// Input sample
+ public float Process(float sample) => _waveShapingFunction(sample);
+ ///
+ /// Resets wave shaper.
+ ///
public void Reset()
{
}
+ ///
+ /// Processes entire and returns new wave-shaped signal.
+ ///
+ /// Input signal
+ /// Filtering method
public DiscreteSignal ApplyTo(DiscreteSignal signal, FilteringMethod method = FilteringMethod.Auto) => this.FilterOnline(signal);
}
}
diff --git a/NWaves/Transforms/HilbertTransform.cs b/NWaves/Transforms/HilbertTransform.cs
index 5e7382d..dd16bf7 100644
--- a/NWaves/Transforms/HilbertTransform.cs
+++ b/NWaves/Transforms/HilbertTransform.cs
@@ -1,11 +1,12 @@
-using NWaves.Transforms.Base;
+using NWaves.Signals;
+using NWaves.Transforms.Base;
using NWaves.Utils;
using System;
namespace NWaves.Transforms
{
///
- /// Class representing Fast Hilbert Transform.
+ /// Represents Fast Hilbert Transform.
///
public class HilbertTransform : ITransform
{
@@ -30,9 +31,8 @@ public class HilbertTransform : ITransform
private readonly float[] _im;
///
- /// Construct Hilbert transformer. Transform must be a power of 2.
+ /// Constructs Hilbert transformer. Transform must be a power of 2.
///
- /// Size of Hilbert Transform
public HilbertTransform(int size = 512)
{
Size = size;
@@ -42,10 +42,10 @@ public HilbertTransform(int size = 512)
}
///
- /// Compute complex analytic signal (real and imaginary parts) from .
+ /// Computes complex analytic signal (real and imaginary parts) from .
///
/// Input data
- public (float[], float[]) AnalyticSignal(float[] input)
+ public ComplexDiscreteSignal AnalyticSignal(float[] input)
{
Direct(input, _im);
@@ -54,12 +54,12 @@ public HilbertTransform(int size = 512)
_re[i] /= Size;
_im[i] /= Size;
}
-
- return (_re.FastCopy(), _im.FastCopy());
+
+ return new ComplexDiscreteSignal(1, _re.ToDoubles(), _im.ToDoubles(), allocateNew: true);
}
///
- /// Do Fast Hilbert Transform.
+ /// Does Fast Hilbert Transform.
///
/// Input data
/// Output data
@@ -91,7 +91,7 @@ public void Direct(float[] input, float[] output)
}
///
- /// Do normalized Fast Hilbert Transform.
+ /// Does normalized Fast Hilbert Transform.
///
/// Input data
/// Output data
@@ -106,7 +106,7 @@ public void DirectNorm(float[] input, float[] output)
}
///
- /// Do Inverse Fast Hilbert Transform.
+ /// Does Inverse Fast Hilbert Transform.
///
/// Input data
/// Output data
@@ -121,7 +121,7 @@ public void Inverse(float[] input, float[] output)
}
///
- /// Do normalized Inverse Fast Hilbert Transform.
+ /// Does normalized Inverse Fast Hilbert Transform.
///
/// Input data
/// Output data
diff --git a/NWaves/Transforms/HilbertTransform64.cs b/NWaves/Transforms/HilbertTransform64.cs
index 731e50b..e6ca7bb 100644
--- a/NWaves/Transforms/HilbertTransform64.cs
+++ b/NWaves/Transforms/HilbertTransform64.cs
@@ -5,7 +5,7 @@
namespace NWaves.Transforms
{
///
- /// Class representing Fast Hilbert Transform (for 64-bit data).
+ /// Represents Fast Hilbert Transform (for 64-bit data).
///
public class HilbertTransform64
{
@@ -30,9 +30,8 @@ public class HilbertTransform64
private readonly double[] _im;
///
- /// Construct Hilbert transformer. Transform must be a power of 2.
+ /// Constructs Hilbert transformer. Transform must be a power of 2.
///
- /// Size of Hilbert Transform
public HilbertTransform64(int size = 512)
{
Size = size;
@@ -42,7 +41,7 @@ public HilbertTransform64(int size = 512)
}
///
- /// Compute complex analytic signal (real and imaginary parts) from .
+ /// Computes complex analytic signal (real and imaginary parts) from .
///
/// Input data
public ComplexDiscreteSignal AnalyticSignal(double[] input)
@@ -59,7 +58,7 @@ public ComplexDiscreteSignal AnalyticSignal(double[] input)
}
///
- /// Do Fast Hilbert Transform.
+ /// Does Fast Hilbert Transform.
///
/// Input data
/// Output data
@@ -91,7 +90,7 @@ public void Direct(double[] input, double[] output)
}
///
- /// Do normalized Fast Hilbert Transform.
+ /// Does normalized Fast Hilbert Transform.
///
/// Input data
/// Output data
@@ -106,7 +105,7 @@ public void DirectNorm(double[] input, double[] output)
}
///
- /// Do Inverse Fast Hilbert Transform.
+ /// Does Inverse Fast Hilbert Transform.
///
/// Input data
/// Output data
@@ -121,7 +120,7 @@ public void Inverse(double[] input, double[] output)
}
///
- /// Do normalized Inverse Fast Hilbert Transform.
+ /// Does normalized Inverse Fast Hilbert Transform.
///
/// Input data
/// Output data
diff --git a/NWaves/Utils/FractionalDelayLine.cs b/NWaves/Utils/FractionalDelayLine.cs
index 13bb43e..6abc56d 100644
--- a/NWaves/Utils/FractionalDelayLine.cs
+++ b/NWaves/Utils/FractionalDelayLine.cs
@@ -3,44 +3,44 @@
namespace NWaves.Utils
{
///
- /// Fractional delay line
+ /// Represents fractional delay line.
///
public partial class FractionalDelayLine
{
///
- /// Interpolation mode
+ /// Gets or sets interpolation mode.
///
public InterpolationMode InterpolationMode { get; set; }
///
- /// Delay line
+ /// Gets the size of delay line (number of samples).
///
- private float[] _delayLine;
+ public int Size => _delayLineSize;
+ private int _delayLineSize;
///
- /// Delay line size
+ /// Delay line.
///
- private int _delayLineSize;
- public int Size => _delayLineSize;
+ private float[] _delayLine;
///
- /// Current write position
+ /// Current write position.
///
private int _n;
///
- /// Used in InterpolationMode.Thiran
+ /// Previously interpolated sample (used with InterpolationMode.Thiran).
///
private float _prevInterpolated;
///
- /// Constructor
+ /// Constructs and reserves given for its samples.
///
- /// Max delay in samples
+ /// Delay line size (number of samples)
/// Interpolation mode
- public FractionalDelayLine(int maxDelayInSamples, InterpolationMode interpolationMode = InterpolationMode.Linear)
+ public FractionalDelayLine(int size, InterpolationMode interpolationMode = InterpolationMode.Linear)
{
- _delayLineSize = Math.Max(4, maxDelayInSamples);
+ _delayLineSize = Math.Max(4, size);
_delayLine = new float[_delayLineSize];
_n = 0;
@@ -48,10 +48,11 @@ public FractionalDelayLine(int maxDelayInSamples, InterpolationMode interpolatio
}
///
- /// Constructor
+ /// Constructs and reserves the size
+ /// corresponding to seconds.
///
/// Sampling rate
- /// Max delay in seconds
+ /// Max delay (in seconds)
/// Interpolation mode
public FractionalDelayLine(int samplingRate,
double maxDelay,
@@ -61,9 +62,8 @@ public FractionalDelayLine(int samplingRate,
}
///
- /// Write (put) sample in the delay line
+ /// Writes (puts) to the delay line.
///
- ///
public void Write(float sample)
{
_delayLine[_n] = sample;
@@ -75,10 +75,8 @@ public void Write(float sample)
}
///
- /// Read (get) sample from the delay line corresponding to given time delay (in seconds)
+ /// Reads (gets) sample from the delay line corresponding to given time (in seconds).
///
- ///
- ///
public float Read(double delay)
{
var precisePosition = (float)(_n - delay + _delayLineSize) % _delayLineSize;
@@ -153,7 +151,7 @@ public float Read(double delay)
}
///
- /// Reset delay line
+ /// Resets delay line.
///
public void Reset()
{
@@ -163,23 +161,27 @@ public void Reset()
}
///
- /// Resize delay line to ensure new size
+ /// Resizes delay line to ensure new .
+ /// If does not exceed current size of the delay line then nothing happens.
///
- public void Ensure(int maxDelayInSamples)
+ public void Ensure(int size)
{
- if (maxDelayInSamples <= _delayLineSize)
+ if (size <= _delayLineSize)
{
return;
}
- Array.Resize(ref _delayLine, maxDelayInSamples);
+ Array.Resize(ref _delayLine, size);
- _delayLineSize = maxDelayInSamples;
+ _delayLineSize = size;
}
///
- /// Resize delay line to ensure new size
+ /// Resizes delay line to ensure new size corresponding to seconds.
+ /// If the new size does not exceed current size of the delay line then nothing happens.
///
+ /// Sampling rate
+ /// Max delay (in seconds)
public void Ensure(int samplingRate, double maxDelay)
{
Ensure((int)(samplingRate * maxDelay) + 1);
diff --git a/NWaves/Utils/Guard.cs b/NWaves/Utils/Guard.cs
index 35c2f72..c112d56 100644
--- a/NWaves/Utils/Guard.cs
+++ b/NWaves/Utils/Guard.cs
@@ -4,13 +4,13 @@
namespace NWaves.Utils
{
///
- /// Static class containing the most widely used contracts / guard clauses
+ /// Contains the most widely used contracts / guard clauses.
///
[DebuggerStepThrough]
public static class Guard
{
///
- /// Guard against negative number or zero
+ /// Guards against negative number or zero.
///
/// Argument (number)
/// Argument name
@@ -23,7 +23,7 @@ public static void AgainstNonPositive(double arg, string argName = "argument")
}
///
- /// Guard against inequality of two arguments
+ /// Guards against inequality of two arguments.
///
/// The first argument
/// The second argument
@@ -38,7 +38,7 @@ public static void AgainstInequality(double arg1, double arg2, string arg1Name =
}
///
- /// Guard against the number being not in the given range
+ /// Guards against the number being not in the given range.
///
/// Argument (number)
/// Lower boundary of the range
@@ -53,7 +53,7 @@ public static void AgainstInvalidRange(double value, double low, double high, st
}
///
- /// Guard against the case when the first and the second arguments are not valid boundaries of a range
+ /// Guards against the case when the first and the second arguments are not valid boundaries of a range.
///
/// The first argument
/// The second argument
@@ -68,7 +68,7 @@ public static void AgainstInvalidRange(double low, double high, string lowName =
}
///
- /// Guard against the first argument exceeding the second argument
+ /// Guards against the first argument exceeding the second argument.
///
/// The first argument
/// The second argument
@@ -83,7 +83,7 @@ public static void AgainstExceedance(double low, double high, string lowName = "
}
///
- /// Guard against integer number being not power of 2 (e.g. 8, 16, 128, etc.)
+ /// Guards against integer number being not power of 2 (e.g. 8, 16, 128, etc.)
///
/// Argument (number)
/// Argument name
@@ -98,7 +98,7 @@ public static void AgainstNotPowerOfTwo(int n, string argName = "Parameter")
}
///
- /// Guard against even integer number
+ /// Guards against even integer number.
///
/// Argument (number)
/// Argument name
@@ -111,7 +111,7 @@ public static void AgainstEvenNumber(int n, string argName = "Parameter")
}
///
- /// Guard against not ordered and not unique array
+ /// Guards against not ordered and not unique array.
///
/// Argument (array of values)
/// Argument name
@@ -127,7 +127,7 @@ public static void AgainstNotOrdered(double[] values, string argName = "Values")
}
///
- /// Guard against incorrect parameters for (equiripple) filter design
+ /// Guards against incorrect parameters for (equiripple) filter design.
///
/// Frequencies
/// Desired magnitude response (gains)
diff --git a/NWaves/Utils/Lpc.cs b/NWaves/Utils/Lpc.cs
index 5c8de18..cda14bd 100644
--- a/NWaves/Utils/Lpc.cs
+++ b/NWaves/Utils/Lpc.cs
@@ -8,17 +8,17 @@
namespace NWaves.Utils
{
///
- /// Functions related to Linear Predictive Coding
+ /// Provides functions related to Linear Predictive Coding (LPC).
///
public static class Lpc
{
///
- /// Levinson-Durbin algorithm for solving main LPC task
+ /// Evaluates LP coefficients using Levinson-Durbin algorithm and returns prediction error.
///
/// Auto-correlation vector
/// LP coefficients
/// Order of LPC
- /// Prediction error
+ /// Optional offset in auto-correlation vector
public static float LevinsonDurbin(float[] input, float[] a, int order, int offset = 0)
{
var err = input[offset];
@@ -49,11 +49,11 @@ public static float LevinsonDurbin(float[] input, float[] a, int order, int offs
}
///
- /// Convert LPC coefficients to cepstrum (LPCC)
+ /// Converts LPC coefficients to LPC cepstrum (LPCC).
///
- ///
- ///
- ///
+ /// LPC vector
+ /// Gain
+ /// LPC cepstrum
public static void ToCepstrum(float[] lpc, float gain, float[] lpcc)
{
var n = lpcc.Length;
@@ -83,17 +83,14 @@ public static void ToCepstrum(float[] lpc, float gain, float[] lpcc)
}
///
- /// Convert LPCC coefficients to LPC and gain
- ///
- /// Formulae: https://www.mathworks.com/help/dsp/ref/lpctofromcepstralcoefficients.html
- ///
+ /// Converts LPC cepstrum to LPC coefficients and returns gain.
///
- ///
- ///
- ///
+ /// LPC cepstrum
+ /// LPC vector
public static float FromCepstrum(float[] lpcc, float[] lpc)
{
- var n = lpcc.Length;
+ // Formulae: https://www.mathworks.com/help/dsp/ref/lpctofromcepstralcoefficients.html
+
var p = lpc.Length; // must be lpcOrder + 1 (!)
lpc[0] = 1;
@@ -112,21 +109,20 @@ public static float FromCepstrum(float[] lpcc, float[] lpc)
}
///
- /// Method returns LPC order for a given sampling rate
- /// according to the best practices.
+ /// Estimates LPC order for a given according to the best practices.
///
/// Sampling rate
- /// LPC order
public static int EstimateOrder(int samplingRate)
{
return 2 + samplingRate / 1000;
}
///
- /// Convert LPC coefficients to Line Spectral Frequencies
+ /// Converts LPC coefficients to Line Spectral Frequencies .
+ /// The length of must be equal to length. Last element will be PI.
///
- ///
- /// The length must be equal to lpc length. Last element will be PI
+ /// LPC vector
+ /// Line spectral frequencies
public static void ToLsf(float[] lpc, float[] lsf)
{
var first = lpc[0];
@@ -170,10 +166,11 @@ public static void ToLsf(float[] lpc, float[] lsf)
}
///
- /// Convert Line Spectral Frequencies to LPC coefficients
+ /// Converts Line Spectral Frequencies to LPC coefficients.
+ /// The length of must be equal to length. Last element must be PI.
///
- /// The length must be equal to lpc length. Last element must be PI
- ///
+ /// Line spectral frequencies
+ /// LPC vector
public static void FromLsf(float[] lsf, float[] lpc)
{
var n = lsf.Length - 1;
diff --git a/NWaves/Utils/MathUtils.cs b/NWaves/Utils/MathUtils.cs
index 2415dd3..b9c2da9 100644
--- a/NWaves/Utils/MathUtils.cs
+++ b/NWaves/Utils/MathUtils.cs
@@ -4,32 +4,28 @@
namespace NWaves.Utils
{
///
- /// Static class providing some helpful math functions
+ /// Provides helpful math functions.
///
public static class MathUtils
{
///
- /// Sinc-function
+ /// Returns Sinc of .
///
- /// Argument
- /// sinc(x)
public static double Sinc(double x)
{
return Math.Abs(x) > 1e-20 ? Math.Sin(Math.PI * x) / (Math.PI * x) : 1.0;
}
///
- /// Method for computing next power of 2 (closest to the given number)
+ /// Returns next power of 2 closest to the given number .
///
- /// Number
- /// Next power of 2 closest to the number
public static int NextPowerOfTwo(int n)
{
return (int)Math.Pow(2, Math.Ceiling(Math.Log(n, 2)));
}
///
- /// Greatest Common Divisor
+ /// Finds Greatest Common Divisor.
///
public static int Gcd(int n, int m)
{
@@ -41,31 +37,24 @@ public static int Gcd(int n, int m)
}
///
- /// Modulo function that works correctly with negative numbers (as np.mod)
+ /// Modulo function that works correctly with negative numbers (as np.mod).
///
- ///
- ///
- ///
public static double Mod(double a, double b)
{
return ((a % b) + b) % b;
}
///
- /// Inverse sinh
+ /// Computes Inverse Sinh of .
///
- ///
- ///
public static double Asinh(double x)
{
return Math.Log(x + Math.Sqrt(x * x + 1));
}
///
- /// Factorial
+ /// Computes factorial !.
///
- ///
- ///
public static double Factorial(int n)
{
var f = 1.0;
@@ -76,21 +65,16 @@ public static double Factorial(int n)
}
///
- /// Binomial coefficient
+ /// Evaluates Binomial coefficient.
///
- ///
- ///
- ///
public static double BinomialCoefficient(int k, int n)
{
return Factorial(n) / (Factorial(k) * Factorial(n - k));
}
///
- /// Diff signal (1st order derivative)
+ /// Evaluate discrete difference of (array of the 1st order derivatives).
///
- ///
- ///
public static void Diff(float[] samples, float[] diff)
{
diff[0] = samples[0];
@@ -102,13 +86,8 @@ public static void Diff(float[] samples, float[] diff)
}
///
- /// Linear interpolation (as numpy.interp)
+ /// Does linear interpolation (as numpy.interp).
///
- ///
- ///
- ///
- ///
- ///
public static void InterpolateLinear(float[] x, float[] y, float[] arg, float[] interp)
{
var left = 0;
@@ -127,10 +106,10 @@ public static void InterpolateLinear(float[] x, float[] y, float[] arg, float[]
}
///
- /// Bilinear transform (in-place)
+ /// Does bilinear transform (in-place).
///
- ///
- ///
+ /// Real parts of complex values
+ /// Imaginary parts of complex values
public static void BilinearTransform(double[] re, double[] im)
{
for (var k = 0; k < re.Length; k++)
@@ -154,11 +133,10 @@ public static void BilinearTransform(double[] re, double[] im)
}
///
- /// Unwrap (phase)
+ /// Unwraps phase.
///
- ///
+ /// Phase array
/// Jump size
- ///
public static double[] Unwrap(double[] phase, double tolerance = Math.PI)
{
var unwrapped = phase.FastCopy();
@@ -185,11 +163,10 @@ public static double[] Unwrap(double[] phase, double tolerance = Math.PI)
}
///
- /// Wrap (phase)
+ /// Wraps phase.
///
- ///
+ /// Phase array
/// Jump size
- ///
public static double[] Wrap(double[] phase, double tolerance = Math.PI)
{
var wrapped = phase.FastCopy();
@@ -214,13 +191,8 @@ public static double[] Wrap(double[] phase, double tolerance = Math.PI)
}
///
- /// Nth order statistics
+ /// Finds -th order statistics (n-th smallest value in array ).
///
- ///
- ///
- ///
- ///
- ///
public static float FindNth(float[] a, int n, int start, int end)
{
while (true)
@@ -260,21 +232,19 @@ public static float FindNth(float[] a, int n, int start, int end)
}
///
- /// Modified Bessel function of the 1st kind (Taylor series, not very precise method)
+ /// Modified Bessel function I0() of the 1st kind
+ /// (using Taylor series, not very precise method).
///
- /// x
- /// I0(x)
public static double I0(double x)
{
- double y = 1.0;
- double prev = 1.0;
- double summand = 0;
+ var y = 1.0;
+ var prev = 1.0;
var i = 1;
while (Math.Abs(prev) > 1e-20)
{
- summand = prev * x * x / (4 * i * i);
+ var summand = prev * x * x / (4 * i * i);
y += summand;
prev = summand;
i++;
@@ -286,14 +256,17 @@ public static double I0(double x)
#region polynomials
+ ///
+ /// Number of iterations in Durand-Kerner algorithm for evaluating polynomial roots.
+ ///
public const int PolyRootsIterations = 25000;
///
- /// Method implementing Durand-Kerner algorithm for finding complex roots of polynomials.
- /// Works for polynomials of order up to approx. 50.
+ /// Evaluates complex roots of polynomials using Durand-Kerner algorithm.
+ /// Works for polynomials of order up to approx. 50.
///
/// Polynomial coefficients
- ///
+ /// Max number of iterations
public static Complex[] PolynomialRoots(double[] a, int maxIterations = PolyRootsIterations)
{
var n = a.Length;
@@ -345,12 +318,8 @@ public static Complex[] PolynomialRoots(double[] a, int maxIterations = PolyRoot
}
///
- /// Method checks if two arrays of complex numbers are essentially identical
+ /// Checks if two arrays of complex numbers are essentially identical.
///
- /// First array
- /// Second array
- /// Tolerance level
- /// true if arrays are equal
private static bool ArraysAreEqual(Complex[] a, Complex[] b, double tolerance = 1e-16)
{
for (var i = 0; i < a.Length; i++)
@@ -365,11 +334,10 @@ private static bool ArraysAreEqual(Complex[] a, Complex[] b, double tolerance =
}
///
- /// Evaluate polynomial according to Horner scheme
+ /// Evaluates polynomial according to Horner scheme.
///
/// Polynomial coefficients
- /// x
- /// The value of polynomial
+ /// Argument
public static Complex EvaluatePolynomial(double[] a, Complex x)
{
var res = new Complex(a[0], 0);
@@ -384,11 +352,8 @@ public static Complex EvaluatePolynomial(double[] a, Complex x)
}
///
- /// Multiply polynomials
+ /// Multiplies polynomials.
///
- ///
- ///
- ///
public static Complex[] MultiplyPolynomials(Complex[] poly1, Complex[] poly2)
{
var length = poly1.Length + poly2.Length - 1;
@@ -406,11 +371,8 @@ public static Complex[] MultiplyPolynomials(Complex[] poly1, Complex[] poly2)
}
///
- /// Divide polynomials
+ /// Divides polynomials.
///
- /// Dividend
- /// Divisor
- ///
public static Complex[][] DividePolynomial(Complex[] dividend, Complex[] divisor)
{
var output = (Complex[])dividend.Clone();
diff --git a/NWaves/Utils/Matrix.cs b/NWaves/Utils/Matrix.cs
index d3f204f..aae91ab 100644
--- a/NWaves/Utils/Matrix.cs
+++ b/NWaves/Utils/Matrix.cs
@@ -3,20 +3,25 @@
namespace NWaves.Utils
{
///
- /// Class representing 2d matrix
+ /// Represents 2D matrix.
///
public class Matrix
{
private readonly double[][] _matrix;
+ ///
+ /// Gets or sets number of rows.
+ ///
public int Rows { get; set; }
+
+ ///
+ /// Gets or sets number of columns.
+ ///
public int Columns { get; set; }
///
- /// Constructor
+ /// Constructs with given number of and .
///
- ///
- ///
public Matrix(int rows, int columns = 0)
{
if (columns == 0) columns = rows;
@@ -36,13 +41,12 @@ public Matrix(int rows, int columns = 0)
}
///
- /// Get 2d array reference
+ /// Gets reference to underlying 2D array.
///
- ///
public double[][] As2dArray() => _matrix;
///
- /// Transposed matrix
+ /// Gets transposed matrix.
///
public Matrix T
{
@@ -63,10 +67,9 @@ public Matrix T
}
///
- /// Companion matrix
+ /// Returns companion matrix.
///
/// Input array
- /// Companion matrix
public static Matrix Companion(double[] a)
{
if (a.Length < 2)
@@ -97,10 +100,8 @@ public static Matrix Companion(double[] a)
}
///
- /// Identity matrix
+ /// Returns identity matrix of given .
///
- ///
- ///
public static Matrix Eye(int size)
{
var eye = new Matrix(size);
@@ -113,6 +114,9 @@ public static Matrix Eye(int size)
return eye;
}
+ ///
+ /// Returns sum of matrices and .
+ ///
public static Matrix operator +(Matrix m1, Matrix m2)
{
Guard.AgainstInequality(m1.Rows, m2.Rows, "Number of rows in first matrix", "number of rows in second matrix");
@@ -131,6 +135,9 @@ public static Matrix Eye(int size)
return result;
}
+ ///
+ /// Subtracts matrix from matrix .
+ ///
public static Matrix operator -(Matrix m1, Matrix m2)
{
Guard.AgainstInequality(m1.Rows, m2.Rows, "Number of rows in first matrix", "number of rows in second matrix");
@@ -149,6 +156,10 @@ public static Matrix Eye(int size)
return result;
}
+ ///
+ /// Gets row by its index.
+ ///
+ /// Row index
public double[] this[int i] => _matrix[i];
}
}
diff --git a/NWaves/Utils/MemoryOperationExtensions.cs b/NWaves/Utils/MemoryOperationExtensions.cs
index 2ac441f..f564d7c 100644
--- a/NWaves/Utils/MemoryOperationExtensions.cs
+++ b/NWaves/Utils/MemoryOperationExtensions.cs
@@ -4,23 +4,22 @@
namespace NWaves.Utils
{
+ ///
+ /// Provides extension methods implementing fast operations with memory buffers.
+ ///
public static class MemoryOperationExtensions
{
///
- /// Convert array of doubles to array of floats
+ /// Creates array of single-precision values from enumerable of double-precision values.
///
- ///
- ///
public static float[] ToFloats(this IEnumerable values)
{
return values.Select(v => (float)v).ToArray();
}
///
- /// Convert array of floats to array of doubles
+ /// Creates array of double-precision values from enumerable of single-precision values.
///
- ///
- ///
public static double[] ToDoubles(this IEnumerable values)
{
return values.Select(v => (double)v).ToArray();
@@ -31,10 +30,8 @@ public static double[] ToDoubles(this IEnumerable values)
private const byte _32Bits = sizeof(float);
///
- /// Method simply copies source array to desination
+ /// Creates fast copy of array.
///
- /// Source array
- /// Source array copy
public static float[] FastCopy(this float[] source)
{
var destination = new float[source.Length];
@@ -43,26 +40,25 @@ public static float[] FastCopy(this float[] source)
}
///
- /// Method copies an array (or its fragment) to existing array (or its part)
+ /// Makes fast copy of array (or its part) to existing array (or its part).
///
- ///
- ///
- ///
- ///
- ///
+ /// Source array
+ /// Destination array
+ /// Number of elements to copy
+ /// Offset in source array
+ /// Offset in destination array
public static void FastCopyTo(this float[] source, float[] destination, int size, int sourceOffset = 0, int destinationOffset = 0)
{
Buffer.BlockCopy(source, sourceOffset * _32Bits, destination, destinationOffset * _32Bits, size * _32Bits);
}
///
- /// Method copies some fragment of the source array starting at specified offset
+ /// Makes fast copy of array fragment starting at specified offset.
///
- ///
- ///
- ///
- ///
- /// The copy of source array part
+ /// Source array
+ /// Number of elements to copy
+ /// Offset in source array
+ /// Offset in destination array
public static float[] FastCopyFragment(this float[] source, int size, int sourceOffset = 0, int destinationOffset = 0)
{
var totalSize = size + destinationOffset;
@@ -72,31 +68,25 @@ public static float[] FastCopyFragment(this float[] source, int size, int source
}
///
- /// Method does fast in-memory merge of two arrays
+ /// Performs fast merging of array with array.
///
- /// The first array for merging
- /// The second array for merging
- /// Merged array
- public static float[] MergeWithArray(this float[] source1, float[] source2)
+ public static float[] MergeWithArray(this float[] source, float[] another)
{
- var merged = new float[source1.Length + source2.Length];
- Buffer.BlockCopy(source1, 0, merged, 0, source1.Length * _32Bits);
- Buffer.BlockCopy(source2, 0, merged, source1.Length * _32Bits, source2.Length * _32Bits);
+ var merged = new float[source.Length + another.Length];
+ Buffer.BlockCopy(source, 0, merged, 0, source.Length * _32Bits);
+ Buffer.BlockCopy(another, 0, merged, source.Length * _32Bits, another.Length * _32Bits);
return merged;
}
///
- /// Method repeats given array N times
+ /// Creates new array containing given array repeated times.
///
- /// Source array
- /// Number of times to repeat array
- /// Array repeated N times
- public static float[] RepeatArray(this float[] source, int times)
+ public static float[] RepeatArray(this float[] source, int n)
{
- var repeated = new float[source.Length * times];
+ var repeated = new float[source.Length * n];
var offset = 0;
- for (var i = 0; i < times; i++)
+ for (var i = 0; i < n; i++)
{
Buffer.BlockCopy(source, 0, repeated, offset * _32Bits, source.Length * _32Bits);
offset += source.Length;
@@ -106,12 +96,9 @@ public static float[] RepeatArray(this float[] source, int times)
}
///
- /// Method creates new zero-padded array from source array.
+ /// Creates new zero-padded array of given from given array.
///
- /// Source array
- /// The size of a zero-padded array
- /// Zero-padded array
- public static float[] PadZeros(this float[] source, int size = 0)
+ public static float[] PadZeros(this float[] source, int size)
{
var zeroPadded = new float[size];
Buffer.BlockCopy(source, 0, zeroPadded, 0, source.Length * _32Bits);
@@ -123,40 +110,37 @@ public static float[] PadZeros(this float[] source, int size = 0)
#region double precision
private const byte _64Bits = sizeof(double);
-
+
///
- /// Method simply copies source array to desination
+ /// Creates fast copy of array.
///
- /// Source array
- /// Source array copy
public static double[] FastCopy(this double[] source)
{
var destination = new double[source.Length];
Buffer.BlockCopy(source, 0, destination, 0, source.Length * _64Bits);
return destination;
}
-
+
///
- /// Method copies an array (or its fragment) to existing array (or its part)
+ /// Makes fast copy of array (or its part) to existing array (or its part).
///
- ///
- ///
- ///
- ///
- ///
+ /// Source array
+ /// Destination array
+ /// Number of elements to copy
+ /// Offset in source array
+ /// Offset in destination array
public static void FastCopyTo(this double[] source, double[] destination, int size, int sourceOffset = 0, int destinationOffset = 0)
{
Buffer.BlockCopy(source, sourceOffset * _64Bits, destination, destinationOffset * _64Bits, size * _64Bits);
}
-
+
///
- /// Method copies some fragment of the source array starting at specified offset
+ /// Makes fast copy of array fragment starting at specified offset.
///
- ///
- ///
- ///
- ///
- /// The copy of source array part
+ /// Source array
+ /// Number of elements to copy
+ /// Offset in source array
+ /// Offset in destination array
public static double[] FastCopyFragment(this double[] source, int size, int sourceOffset = 0, int destinationOffset = 0)
{
var totalSize = size + destinationOffset;
@@ -164,33 +148,27 @@ public static double[] FastCopyFragment(this double[] source, int size, int sour
Buffer.BlockCopy(source, sourceOffset * _64Bits, destination, destinationOffset * _64Bits, size * _64Bits);
return destination;
}
-
+
///
- /// Method does fast in-memory merge of two arrays
+ /// Performs fast merging of array with array.
///
- /// The first array for merging
- /// The second array for merging
- /// Merged array
- public static double[] MergeWithArray(this double[] source1, double[] source2)
+ public static double[] MergeWithArray(this double[] source, double[] another)
{
- var merged = new double[source1.Length + source2.Length];
- Buffer.BlockCopy(source1, 0, merged, 0, source1.Length * _64Bits);
- Buffer.BlockCopy(source2, 0, merged, source1.Length * _64Bits, source2.Length * _64Bits);
+ var merged = new double[source.Length + another.Length];
+ Buffer.BlockCopy(source, 0, merged, 0, source.Length * _64Bits);
+ Buffer.BlockCopy(another, 0, merged, source.Length * _64Bits, another.Length * _64Bits);
return merged;
}
-
+
///
- /// Method repeats given array N times
+ /// Creates new array containing given array repeated times.
///
- /// Source array
- /// Number of times to repeat array
- /// Array repeated N times
- public static double[] RepeatArray(this double[] source, int times)
+ public static double[] RepeatArray(this double[] source, int n)
{
- var repeated = new double[source.Length * times];
+ var repeated = new double[source.Length * n];
var offset = 0;
- for (var i = 0; i < times; i++)
+ for (var i = 0; i < n; i++)
{
Buffer.BlockCopy(source, 0, repeated, offset * _64Bits, source.Length * _64Bits);
offset += source.Length;
@@ -198,14 +176,11 @@ public static double[] RepeatArray(this double[] source, int times)
return repeated;
}
-
+
///
- /// Method creates new zero-padded array from source array.
+ /// Creates new zero-padded array of given from given array.
///
- /// Source array
- /// The size of a zero-padded array
- /// Zero-padded array
- public static double[] PadZeros(this double[] source, int size = 0)
+ public static double[] PadZeros(this double[] source, int size)
{
var zeroPadded = new double[size];
Buffer.BlockCopy(source, 0, zeroPadded, 0, source.Length * _64Bits);
@@ -214,4 +189,4 @@ public static double[] PadZeros(this double[] source, int size = 0)
#endregion
}
-}
\ No newline at end of file
+}
diff --git a/NWaves/Utils/Scale.cs b/NWaves/Utils/Scale.cs
index d852c9e..4a0ec51 100644
--- a/NWaves/Utils/Scale.cs
+++ b/NWaves/Utils/Scale.cs
@@ -3,120 +3,116 @@
namespace NWaves.Utils
{
///
- /// Static class providing methods for
- ///
+ /// Provides methods for
+ ///
/// 1) converting between different scales:
- /// - decibel
- /// - MIDI pitch
- /// - mel (HTK)
- /// - mel (Slaney)
- /// - bark1 (Traunmueller)
- /// - bark2 (Wang)
- /// - ERB
- ///
+ ///
+ /// - decibel
+ /// - MIDI pitch
+ /// - mel (HTK)
+ /// - mel (Slaney)
+ /// - bark1 (Traunmueller)
+ /// - bark2 (Wang)
+ /// - ERB
+ ///
+ ///
+ ///
/// 2) loudness weighting:
- /// - A-weighting
- /// - B-weighting
- /// - C-weighting
- ///
+ ///
+ /// - A-weighting
+ /// - B-weighting
+ /// - C-weighting
+ ///
+ ///
///
public static class Scale
{
///
- /// Method converts magnitude value to dB level
+ /// Converts magnitude value to dB level.
///
/// Magnitude
/// Reference magnitude
- /// Decibel level
public static double ToDecibel(double value, double valueReference)
{
return 20 * Math.Log10(value / valueReference + double.Epsilon);
}
///
- /// Method converts magnitude value to dB level (simplified version for intermediate calculations)
+ /// Converts magnitude value to dB level (simplified version).
///
/// Magnitude
- /// Decibel level
public static double ToDecibel(double value)
{
return 20 * Math.Log10(value);
}
///
- /// Method converts power to dB level
+ /// Converts power to dB level.
///
/// Power
/// Reference power
- /// Decibel level
public static double ToDecibelPower(double value, double valueReference = 1.0)
{
return 10 * Math.Log10(value / valueReference + double.Epsilon);
}
///
- /// Method converts dB level to magnitude value
+ /// Converts dB level to magnitude value.
///
- /// dB level
+ /// Decibel level
/// Reference magnitude
- /// Magnitude value
public static double FromDecibel(double level, double valueReference)
{
return valueReference * Math.Pow(10, level / 20);
}
///
- /// Method converts dB level to magnitude value (simplified version for intermediate calculations)
+ /// Converts dB level to magnitude value (simplified version).
///
- /// dB level
- /// Magnitude value
+ /// Decibel level
public static double FromDecibel(double level)
{
return Math.Pow(10, level / 20);
}
///
- /// Method converts dB level to power
+ /// Converts dB level to power.
///
- /// dB level
+ /// Decibel level
/// Reference power
- /// Power
public static double FromDecibelPower(double level, double valueReference = 1.0)
{
return valueReference * Math.Pow(10, level / 10);
}
///
- /// Method converts MIDI pitch to frequency
+ /// Converts MIDI pitch to frequency (in Hz).
///
- ///
- ///
+ /// Pitch
public static double PitchToFreq(int pitch)
{
return 440 * Math.Pow(2, (pitch - 69) / 12.0);
}
///
- /// Method converts frequency to MIDI pitch
+ /// Converts frequency to MIDI pitch.
///
- ///
- ///
+ /// Frequency (in Hz)
public static int FreqToPitch(double freq)
{
return (int)Math.Round(69 + 12 * Math.Log(freq / 440, 2), MidpointRounding.AwayFromZero);
}
///
- /// Array of notes
+ /// Array of musical notes.
///
public static string[] Notes = new[] { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" };
///
- /// Method converts note (in format ("G", 3), ("E", 5), etc.) to frequency in Hz
+ /// Converts musical note (in format ("G", 3), ("E", 5), etc.) to frequency in Hz.
///
/// Note (A-G#)
/// Octave (0-8)
- /// Frequency in Hz
public static double NoteToFreq(string note, int octave)
{
var noteIndex = Array.IndexOf(Notes, note);
@@ -135,10 +131,9 @@ public static double NoteToFreq(string note, int octave)
}
///
- /// Method converts frequency in Hz to note (in format ("G", 3), ("E", 5), etc.)
+ /// Converts frequency in Hz to note (in tuple format ("G", 3), ("E", 5), etc.).
///
/// Frequency in Hz
- /// Tuple (note, octave)
public static (string, int) FreqToNote(double freq)
{
var pitch = FreqToPitch(freq);
@@ -150,30 +145,24 @@ public static (string, int) FreqToNote(double freq)
}
///
- /// Method converts herz frequency to corresponding mel frequency
+ /// Converts herz frequency to corresponding mel frequency.
///
- /// Herz frequency
- /// Mel frequency
public static double HerzToMel(double herz)
{
return 1127 * Math.Log(herz / 700 + 1); // actually, should be 1127.01048, but HTK and Kaldi seem to use 1127
}
///
- /// Method converts mel frequency to corresponding herz frequency
+ /// Converts mel frequency to corresponding herz frequency.
///
- /// Mel frequency
- /// Herz frequency
public static double MelToHerz(double mel)
{
return (Math.Exp(mel / 1127) - 1) * 700;
}
///
- /// Method converts herz frequency to mel frequency (suggested by M.Slaney)
+ /// Converts herz frequency to mel frequency (suggested by M.Slaney).
///
- /// Herz frequency
- /// Mel frequency
public static double HerzToMelSlaney(double herz)
{
const double minHerz = 0.0;
@@ -187,10 +176,8 @@ public static double HerzToMelSlaney(double herz)
}
///
- /// Method converts mel frequency to herz frequency (suggested by M.Slaney)
+ /// Converts mel frequency to herz frequency (suggested by M.Slaney).
///
- /// Mel frequency
- /// Herz frequency
public static double MelToHerzSlaney(double mel)
{
const double minHerz = 0.0;
@@ -204,76 +191,58 @@ public static double MelToHerzSlaney(double mel)
}
///
- /// Method #1 converts herz frequency to corresponding bark frequency
- /// (according to Traunmüller (1990))
+ /// Converts herz frequency to corresponding bark frequency (according to Traunmüller (1990)).
///
- /// Herz frequency
- /// Bark frequency
public static double HerzToBark(double herz)
{
return (26.81 * herz) / (1960 + herz) - 0.53;
}
///
- /// Method #1 converts bark frequency to corresponding herz frequency
- /// (according to Traunmüller (1990))
+ /// Converts bark frequency to corresponding herz frequency (according to Traunmüller (1990)).
///
- /// Bark frequency
- /// Herz frequency
public static double BarkToHerz(double bark)
{
return 1960 / (26.81 / (bark + 0.53) - 1);
}
///
- /// Method #2 converts herz frequency to corresponding bark frequency
- /// (according to Wang (1992)); used in M.Slaney's auditory toolbox
+ /// Converts herz frequency to corresponding bark frequency (according to Wang (1992));
+ /// used in M.Slaney's auditory toolbox.
///
- /// Herz frequency
- /// Bark frequency
public static double HerzToBarkSlaney(double herz)
{
return 6 * MathUtils.Asinh(herz / 600);
}
///
- /// Method #2 converts bark frequency to corresponding herz frequency
- /// (according to Wang (1992)); used in M.Slaney's auditory toolbox
+ /// Converts bark frequency to corresponding herz frequency (according to Wang (1992));
+ /// used in M.Slaney's auditory toolbox.
///
- /// Bark frequency
- /// Herz frequency
public static double BarkToHerzSlaney(double bark)
{
return 600 * Math.Sinh(bark / 6);
}
///
- /// Method converts herz frequency to corresponding ERB frequency
+ /// Converts herz frequency to corresponding ERB frequency.
///
- /// Herz frequency
- /// ERB frequency
public static double HerzToErb(double herz)
{
return 9.26449 * Math.Log(1.0 + herz) / (24.7 * 9.26449);
}
///
- /// Method converts ERB frequency to corresponding herz frequency
+ /// Converts ERB frequency to corresponding herz frequency.
///
- /// ERB frequency
- /// Herz frequency
public static double ErbToHerz(double erb)
{
return (Math.Exp(erb / 9.26449) - 1.0) * (24.7 * 9.26449);
}
///
- /// Method converts Hz frequency to octave (used for constructing librosa-like Chroma filterbanks)
+ /// Converts Hz frequency to octave (used for constructing librosa-like Chroma filterbanks).
///
- ///
- ///
- ///
- ///
public static double HerzToOctave(double herz, double tuning = 0, int binsPerOctave = 12)
{
var a440 = 440.0 * Math.Pow(2.0, tuning / binsPerOctave);
@@ -282,20 +251,19 @@ public static double HerzToOctave(double herz, double tuning = 0, int binsPerOct
}
///
- /// Method for obtaining a perceptual loudness weight
+ /// Returns perceptual loudness weight (in dB).
///
- /// Frequency
+ /// Frequency
/// Weighting type (A, B, C)
- /// Weight value in dB
- public static double LoudnessWeighting(double freq, string weightingType = "A")
+ public static double LoudnessWeighting(double frequency, string weightingType = "A")
{
- var level2 = freq * freq;
+ var level2 = frequency * frequency;
switch (weightingType.ToUpper())
{
case "B":
{
- var r = (level2 * freq * 148693636) /
+ var r = (level2 * frequency * 148693636) /
(
(level2 + 424.36) *
Math.Sqrt(level2 + 25122.25) *