miniDSP
A small C library for audio DSP
Loading...
Searching...
No Matches
minidsp_core.c File Reference

Stateless signal math: dot product, energy, power, entropy, scaling, AGC, time-domain pitch estimation, simple effects, and window function generation. More...

#include "minidsp.h"
Include dependency graph for minidsp_core.c:

Go to the source code of this file.

Macros

#define MD_F0_ACF_PEAK_THRESHOLD   0.15
 Minimum normalised autocorrelation peak height accepted as voiced F0.
 

Functions

double MD_dot (const double *a, const double *b, unsigned N)
 Dot product of two vectors a and b, each of length N.
 
double MD_energy (const double *a, unsigned N)
 Signal energy: the sum of squared samples.
 
double MD_power (const double *a, unsigned N)
 Signal power: energy divided by the number of samples.
 
double MD_power_db (const double *a, unsigned N)
 Signal power expressed in decibels (dB).
 
double MD_scale (double in, double oldmin, double oldmax, double newmin, double newmax)
 Linearly map a value from one range to another.
 
void MD_scale_vec (double *in, double *out, unsigned N, double oldmin, double oldmax, double newmin, double newmax)
 Apply MD_scale() to every element of a vector.
 
void MD_fit_within_range (double *in, double *out, unsigned N, double newmin, double newmax)
 Squeeze values into [newmin, newmax] only if they don't already fit.
 
void MD_adjust_dblevel (const double *in, double *out, unsigned N, double dblevel)
 Automatic Gain Control (AGC): adjust a signal to a target dB level.
 
double MD_entropy (const double *a, unsigned N, bool clip)
 Compute the normalised entropy of a distribution.
 
static double md_parabolic_offset (double y_left, double y_mid, double y_right)
 Three-point parabolic refinement around a discrete peak index.
 
double MD_rms (const double *a, unsigned N)
 Root mean square: the standard measure of signal "loudness".
 
double MD_zero_crossing_rate (const double *a, unsigned N)
 Zero-crossing rate: fraction of adjacent sample pairs that differ in sign.
 
void MD_autocorrelation (const double *a, unsigned N, double *out, unsigned max_lag)
 Normalised autocorrelation for lags 0..max_lag-1.
 
void MD_peak_detect (const double *a, unsigned N, double threshold, unsigned min_distance, unsigned *peaks_out, unsigned *num_peaks_out)
 Peak detection: find local maxima above a threshold.
 
double MD_f0_autocorrelation (const double *signal, unsigned N, double sample_rate, double min_freq_hz, double max_freq_hz)
 Estimate the fundamental frequency (F0) using autocorrelation.
 
void MD_mix (const double *a, const double *b, double *out, unsigned N, double w_a, double w_b)
 Signal mixing: weighted sum of two signals.
 
void MD_delay_echo (const double *in, double *out, unsigned N, unsigned delay_samples, double feedback, double dry, double wet)
 Delay line / echo effect using a circular buffer with feedback.
 
void MD_tremolo (const double *in, double *out, unsigned N, double rate_hz, double depth, double sample_rate)
 Tremolo effect (amplitude modulation by a sinusoidal LFO).
 
void MD_comb_reverb (const double *in, double *out, unsigned N, unsigned delay_samples, double feedback, double dry, double wet)
 Comb-filter reverb (feedback comb filter with dry/wet mix).
 
void MD_Gen_Hann_Win (double *out, unsigned n)
 Generate a Hanning (raised cosine) window.
 
void MD_Gen_Hamming_Win (double *out, unsigned n)
 Generate a Hamming window.
 
void MD_Gen_Blackman_Win (double *out, unsigned n)
 Generate a Blackman window.
 
void MD_Gen_Rect_Win (double *out, unsigned n)
 Generate a rectangular window (all ones).
 

Detailed Description

Stateless signal math: dot product, energy, power, entropy, scaling, AGC, time-domain pitch estimation, simple effects, and window function generation.

Author
Chuck Wooters woote.nosp@m.rs@h.nosp@m.ey.co.nosp@m.m

Definition in file minidsp_core.c.

Macro Definition Documentation

◆ MD_F0_ACF_PEAK_THRESHOLD

#define MD_F0_ACF_PEAK_THRESHOLD   0.15

Minimum normalised autocorrelation peak height accepted as voiced F0.

Definition at line 260 of file minidsp_core.c.

Function Documentation

◆ MD_adjust_dblevel()

void MD_adjust_dblevel ( const double *  in,
double *  out,
unsigned  N,
double  dblevel 
)

Automatic Gain Control (AGC): adjust a signal to a target dB level.

Automatic Gain Control: scale a signal so its power matches the requested dB level, then clip to [-1, 1].

The input signal is assumed to be in the range [-1.0, 1.0]. The function computes a gain factor so that the output signal has the desired power level (in dB), then clips to [-1.0, 1.0] if any sample exceeds that range.

Based on Jaydeep Dhole's AGC implementation for MATLAB.

Definition at line 165 of file minidsp_core.c.

◆ MD_autocorrelation()

void MD_autocorrelation ( const double *  a,
unsigned  N,
double *  out,
unsigned  max_lag 
)

Normalised autocorrelation for lags 0..max_lag-1.

Compute the normalised autocorrelation of a signal.

out[tau] = (1/R[0]) * sum_{n=0}^{N-1-tau} x[n] * x[n+tau]

Reuses MD_dot() for the inner product. Silent signals (R[0]=0) produce all-zero output.

Definition at line 313 of file minidsp_core.c.

◆ MD_comb_reverb()

void MD_comb_reverb ( const double *  in,
double *  out,
unsigned  N,
unsigned  delay_samples,
double  feedback,
double  dry,
double  wet 
)

Comb-filter reverb (feedback comb filter with dry/wet mix).

Internal comb section:

\[ c[n] = x[n] + feedback \cdot c[n-D] \]

Final output:

\[ y[n] = dry \cdot x[n] + wet \cdot c[n] \]

where \(D\) is delay_samples. In-place safe: out may alias in.

Parameters
inInput signal of length N.
outOutput signal of length N (caller-allocated).
NNumber of samples.
delay_samplesComb delay in samples (must be > 0).
feedbackFeedback gain (must satisfy |feedback| < 1).
dryDry (original) mix weight.
wetWet (comb output) mix weight.

Definition at line 487 of file minidsp_core.c.

◆ MD_delay_echo()

void MD_delay_echo ( const double *  in,
double *  out,
unsigned  N,
unsigned  delay_samples,
double  feedback,
double  dry,
double  wet 
)

Delay line / echo effect using a circular buffer with feedback.

Let D = delay_samples. The internal delay state follows:

\[ s[n] = x[n] + feedback \cdot s[n-D] \]

and output is:

\[ y[n] = dry \cdot x[n] + wet \cdot s[n-D] \]

This creates repeating echoes decaying geometrically when \(|feedback| < 1\). In-place safe: out may alias in.

Parameters
inInput signal of length N.
outOutput signal of length N (caller-allocated).
NNumber of samples.
delay_samplesDelay length in samples (must be > 0).
feedbackEcho feedback gain (must satisfy |feedback| < 1).
dryDry (original) mix weight.
wetWet (delayed) mix weight.

Definition at line 443 of file minidsp_core.c.

◆ MD_dot()

double MD_dot ( const double *  a,
const double *  b,
unsigned  N 
)

Dot product of two vectors a and b, each of length N.

Compute the dot product of two vectors.

dot = a[0]*b[0] + a[1]*b[1] + ... + a[N-1]*b[N-1]

This is one of the most fundamental operations in DSP. The dot product measures how "similar" two signals are – if they are identical the result is large; if they are unrelated it is near zero.

Definition at line 25 of file minidsp_core.c.

◆ MD_energy()

double MD_energy ( const double *  a,
unsigned  N 
)

Signal energy: the sum of squared samples.

Compute signal energy: sum of squared samples.

     N-1

E = SUM a[n]^2 n=0

Energy tells you "how loud" a signal is overall. A silent signal has zero energy; a loud one has high energy. Notice that squaring makes all values positive, so negative samples contribute too.

Definition at line 45 of file minidsp_core.c.

◆ MD_entropy()

double MD_entropy ( const double *  a,
unsigned  N,
bool  clip 
)

Compute the normalised entropy of a distribution.

Compute the normalized entropy of a distribution.

Entropy measures how "spread out" a distribution is:

  • 0.0 means all the energy is in a single bin (very peaky).
  • 1.0 means the energy is spread equally (completely flat).

The Shannon entropy formula is: H = -SUM( p_i * log2(p_i) ) We normalise by dividing by log2(N) so the result is always in [0, 1].

Parameters
aArray of values representing the distribution.
NLength of the array.
clipIf true, ignore negative values (treat them as 0). If false, use a[i]^2 so all values become non-negative.
Returns
Normalised entropy in [0.0, 1.0].

Definition at line 210 of file minidsp_core.c.

◆ MD_f0_autocorrelation()

double MD_f0_autocorrelation ( const double *  signal,
unsigned  N,
double  sample_rate,
double  min_freq_hz,
double  max_freq_hz 
)

Estimate the fundamental frequency (F0) using autocorrelation.

This method searches for the strongest local peak in the normalised autocorrelation sequence over lags corresponding to the requested frequency range:

\[ f_0 = \frac{f_s}{\tau_\text{peak}} \]

where \(\tau_\text{peak}\) is the selected lag and \(f_s\) is the sample rate.

Parameters
signalInput signal of length N.
NNumber of samples (must be >= 2).
sample_rateSampling rate in Hz (must be > 0).
min_freq_hzMinimum search frequency in Hz (must be > 0).
max_freq_hzMaximum search frequency in Hz (must be > min_freq_hz).
Returns
Estimated F0 in Hz, or 0.0 if no reliable F0 is found.
Note
Invalid API usage is guarded by assertions. A return value of 0.0 means the call was valid but no usable pitch peak was found (for example, silence or an unvoiced/noisy frame).
double f0 = MD_f0_autocorrelation(frame, frame_len, 16000.0, 80.0, 400.0);
double MD_f0_autocorrelation(const double *signal, unsigned N, double sample_rate, double min_freq_hz, double max_freq_hz)
Estimate the fundamental frequency (F0) using autocorrelation.

Definition at line 364 of file minidsp_core.c.

◆ MD_fit_within_range()

void MD_fit_within_range ( double *  in,
double *  out,
unsigned  N,
double  newmin,
double  newmax 
)

Squeeze values into [newmin, newmax] only if they don't already fit.

Fit values within [newmin, newmax].

If the input range already lies inside [newmin, newmax], the values are copied as-is (no stretching). Otherwise, the full input range is mapped onto the new range.

Definition at line 129 of file minidsp_core.c.

◆ MD_Gen_Blackman_Win()

void MD_Gen_Blackman_Win ( double *  out,
unsigned  n 
)

Generate a Blackman window.

Generate a Blackman window of length n.

The formula is: w[i] = 0.42

  • 0.5 * cos(2*pi*i / (n-1))
  • 0.08 * cos(4*pi*i / (n-1))

Definition at line 574 of file minidsp_core.c.

◆ MD_Gen_Hamming_Win()

void MD_Gen_Hamming_Win ( double *  out,
unsigned  n 
)

Generate a Hamming window.

Generate a Hamming window of length n.

The formula is: w[i] = 0.54 - 0.46 * cos(2*pi*i / (n-1))

Definition at line 550 of file minidsp_core.c.

◆ MD_Gen_Hann_Win()

void MD_Gen_Hann_Win ( double *  out,
unsigned  n 
)

Generate a Hanning (raised cosine) window.

Generate a Hanning (Hann) window of length n.

The formula is: w[i] = 0.5 * (1 - cos(2*pi*i / (n-1)))

Windowing is essential before taking an FFT because real-world signals don't start and end at exactly zero. Without a window, the abrupt edges create false high-frequency content ("spectral leakage"). The Hanning window smoothly tapers the signal to zero at both ends, reducing this artefact.

Definition at line 529 of file minidsp_core.c.

◆ MD_Gen_Rect_Win()

void MD_Gen_Rect_Win ( double *  out,
unsigned  n 
)

Generate a rectangular window (all ones).

Generate a rectangular window of length n (all ones).

Definition at line 594 of file minidsp_core.c.

◆ MD_mix()

void MD_mix ( const double *  a,
const double *  b,
double *  out,
unsigned  N,
double  w_a,
double  w_b 
)

Signal mixing: weighted sum of two signals.

Mix (weighted sum) two signals.

out[n] = w_a * a[n] + w_b * b[n]

In-place safe (out may alias a or b).

Definition at line 428 of file minidsp_core.c.

◆ md_parabolic_offset()

static double md_parabolic_offset ( double  y_left,
double  y_mid,
double  y_right 
)
static

Three-point parabolic refinement around a discrete peak index.

Returns a fractional offset in [-0.5, 0.5].

Definition at line 264 of file minidsp_core.c.

◆ MD_peak_detect()

void MD_peak_detect ( const double *  a,
unsigned  N,
double  threshold,
unsigned  min_distance,
unsigned *  peaks_out,
unsigned *  num_peaks_out 
)

Peak detection: find local maxima above a threshold.

Detect peaks (local maxima) in a signal.

A sample a[i] is a peak if:

  • a[i] > a[i-1] AND a[i] > a[i+1] (strictly greater than neighbours)
  • a[i] >= threshold
  • distance from the last accepted peak >= min_distance

Endpoints (i=0, i=N-1) are never peaks.

Definition at line 341 of file minidsp_core.c.

◆ MD_power()

double MD_power ( const double *  a,
unsigned  N 
)

Signal power: energy divided by the number of samples.

Compute signal power: energy divided by the number of samples.

P = E / N

Power is the "average energy per sample". It lets you compare signals of different lengths on an equal footing.

Definition at line 60 of file minidsp_core.c.

◆ MD_power_db()

double MD_power_db ( const double *  a,
unsigned  N 
)

Signal power expressed in decibels (dB).

Compute signal power in decibels: 10 * log10(power).

P_dB = 10 * log10(P)

Decibels are a logarithmic scale commonly used in audio engineering. Every +10 dB means the power is 10x larger. A floor of 1e-10 is used to avoid log(0), which would be negative infinity.

Definition at line 76 of file minidsp_core.c.

◆ MD_rms()

double MD_rms ( const double *  a,
unsigned  N 
)

Root mean square: the standard measure of signal "loudness".

Compute the root mean square (RMS) of a signal.

RMS = sqrt(1/N * sum(x[n]^2)) = sqrt(power)

Definition at line 280 of file minidsp_core.c.

◆ MD_scale()

double MD_scale ( double  in,
double  oldmin,
double  oldmax,
double  newmin,
double  newmax 
)

Linearly map a value from one range to another.

Map a single value from one range to another.

Formula: out = (in - oldmin) * (newmax - newmin) / (oldmax - oldmin) + newmin

For example, mapping a value of 5 from the range [0, 10] into [0, 100] gives 50. This is sometimes called "lerp" (linear interpolation).

Definition at line 96 of file minidsp_core.c.

◆ MD_scale_vec()

void MD_scale_vec ( double *  in,
double *  out,
unsigned  N,
double  oldmin,
double  oldmax,
double  newmin,
double  newmax 
)

Apply MD_scale() to every element of a vector.

Map every element of a vector from one range to another.

Definition at line 106 of file minidsp_core.c.

◆ MD_tremolo()

void MD_tremolo ( const double *  in,
double *  out,
unsigned  N,
double  rate_hz,
double  depth,
double  sample_rate 
)

Tremolo effect (amplitude modulation by a sinusoidal LFO).

The modulation gain is:

\[ g[n] = (1 - depth) + depth \cdot \frac{1 + \sin(2\pi f_{LFO} n / f_s)}{2} \]

so \(g[n]\) ranges from \(1-depth\) to \(1\).

Output:

\[ y[n] = g[n] \cdot x[n] \]

In-place safe: out may alias in.

Parameters
inInput signal of length N.
outOutput signal of length N (caller-allocated).
NNumber of samples.
rate_hzLFO rate in Hz (must be >= 0).
depthModulation depth in [0, 1].
sample_rateSampling rate in Hz (must be > 0).

Definition at line 469 of file minidsp_core.c.

◆ MD_zero_crossing_rate()

double MD_zero_crossing_rate ( const double *  a,
unsigned  N 
)

Zero-crossing rate: fraction of adjacent sample pairs that differ in sign.

Compute the zero-crossing rate of a signal.

Returns a value in [0.0, 1.0].

Zero is treated as non-negative (standard convention).

Definition at line 293 of file minidsp_core.c.