esp32-audio-player 0.1.0
Audio player engine for ESP32
Loading...
Searching...
No Matches
dsp.h File Reference

Sound processing chain, float32 inside, Q31 in and out: ReplayGain -> preamp -> parametric EQ (<=10 bands, RBJ biquads, AutoEQ import) -> crossfeed (Bauer-style, bs2b-like) -> software volume -> limiter -> dither. More...

Include dependency graph for dsp.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  peq_band_t
 
struct  eq_preset_t
 
struct  dsp_config_t
 
struct  biquad_coef_t
 Low-level building blocks, exported for tests and for the Bluetooth path. More...
 

Macros

#define DSP_MAX_BANDS   10
 
#define DSP_PRESET_NAME_MAX   48
 
#define DSP_DRAIN_MAX   128u
 Most frames dsp_process_out() adds to a chunk: the limiter delay line (about 1 ms).
 

Typedefs

typedef struct dsp dsp_t
 

Enumerations

enum  peq_type_t {
  PEQ_PEAK = 0 , PEQ_LOW_SHELF , PEQ_HIGH_SHELF , PEQ_LOW_PASS ,
  PEQ_HIGH_PASS
}
 
enum  rg_mode_t { RG_OFF = 0 , RG_TRACK , RG_ALBUM , RG_AUTO }
 
enum  {
  DSP_FLAG_RG = 1u << 0 , DSP_FLAG_EQ = 1u << 1 , DSP_FLAG_CROSSFEED = 1u << 2 , DSP_FLAG_SW_VOLUME = 1u << 3 ,
  DSP_FLAG_LIMITER = 1u << 4 , DSP_FLAG_DITHER = 1u << 5 , DSP_FLAG_RESAMPLE = 1u << 6
}
 Active processing flags (for a "signal path" display). More...
 

Functions

int eq_preset_parse_autoeq (const char *text, eq_preset_t *out)
 Parse AutoEQ "ParametricEQ.txt" (lines like "Preamp: -6.3 dB" and "Filter 1: ON PK Fc 105 Hz Gain -2.9 dB Q 0.70", types PK, LSC, HSC, LS, HS, LP, HP).
 
int eq_preset_format_autoeq (const eq_preset_t *p, char *out, size_t out_size)
 Write the same text format (so presets round-trip). Returns bytes written or <0.
 
uint32_t eq_builtin_count (void)
 Built-in presets: "Flat", "Bass", "Treble", "Vocal", "Loudness". Index 0 is Flat.
 
const eq_preset_t * eq_builtin_get (uint32_t index)
 
void dsp_config_defaults (dsp_config_t *c)
 
dsp_t * dsp_create (void)
 
void dsp_destroy (dsp_t *d)
 
void dsp_configure (dsp_t *d, const dsp_config_t *cfg, uint32_t sample_rate, uint8_t channels)
 (Re)configure for a format. Keeps filter state when only gains change.
 
void dsp_set_replaygain (dsp_t *d, float track_gain_db, float track_peak, float album_gain_db, float album_peak, bool album_context)
 ReplayGain values of the current track (NAN when absent). Call on track change.
 
void dsp_process (dsp_t *d, int32_t *pcm, uint32_t frames)
 in place
 
uint32_t dsp_process_out (dsp_t *d, int32_t *pcm, uint32_t frames, uint32_t cap_frames)
 dsp_process() with room for more output.
 
void dsp_reset (dsp_t *d)
 clear filter state (seek, track change)
 
bool dsp_is_bypass (const dsp_t *d)
 
uint32_t dsp_active_flags (const dsp_t *d)
 
void biquad_design (biquad_coef_t *c, peq_type_t type, float fs, float f0, float gain_db, float q)
 RBJ Audio EQ Cookbook designs.
 
float biquad_response_db (const biquad_coef_t *c, float fs, float f)
 Magnitude response in dB at frequency f (for EQ curve drawing and tests).
 
void pcm_q31_to_f32 (const int32_t *in, float *out, size_t samples)
 Q31 <-> float.
 
void pcm_f32_to_q31 (const float *in, int32_t *out, size_t samples)
 saturating
 
void pcm_q31_to_s16_dither (const int32_t *in, int16_t *out, size_t samples, uint32_t *state)
 Reduce to 16 bits with TPDF dither (state = LCG seed, keep per stream).
 
void pcm_mono_to_stereo (const int32_t *in, int32_t *out, size_t frames)
 Upmix mono Q31 to stereo. in == out is allowed (the buffer must hold 2*frames samples).
 
float db_to_lin (float db)
 
float lin_to_db (float lin)
 

Detailed Description

Sound processing chain, float32 inside, Q31 in and out: ReplayGain -> preamp -> parametric EQ (<=10 bands, RBJ biquads, AutoEQ import) -> crossfeed (Bauer-style, bs2b-like) -> software volume -> limiter -> dither.

When every stage is off and volume is unity, dsp_process() leaves samples untouched (bit-perfect path) and dsp_is_bypass() returns true.

Macro Definition Documentation

◆ DSP_DRAIN_MAX

#define DSP_DRAIN_MAX   128u

Most frames dsp_process_out() adds to a chunk: the limiter delay line (about 1 ms).

◆ DSP_MAX_BANDS

#define DSP_MAX_BANDS   10

◆ DSP_PRESET_NAME_MAX

#define DSP_PRESET_NAME_MAX   48

Typedef Documentation

◆ dsp_t

typedef struct dsp dsp_t

Enumeration Type Documentation

◆ anonymous enum

anonymous enum

Active processing flags (for a "signal path" display).

Enumerator
DSP_FLAG_RG 
DSP_FLAG_EQ 
DSP_FLAG_CROSSFEED 
DSP_FLAG_SW_VOLUME 
DSP_FLAG_LIMITER 
DSP_FLAG_DITHER 
DSP_FLAG_RESAMPLE 

set by the player, not by dsp

◆ peq_type_t

enum peq_type_t
Enumerator
PEQ_PEAK 
PEQ_LOW_SHELF 
PEQ_HIGH_SHELF 
PEQ_LOW_PASS 
PEQ_HIGH_PASS 

◆ rg_mode_t

enum rg_mode_t
Enumerator
RG_OFF 
RG_TRACK 
RG_ALBUM 
RG_AUTO 

Function Documentation

◆ biquad_design()

void biquad_design ( biquad_coef_t *  c,
peq_type_t  type,
float  fs,
float  f0,
float  gain_db,
float  q 
)

RBJ Audio EQ Cookbook designs.

◆ biquad_response_db()

float biquad_response_db ( const biquad_coef_t *  c,
float  fs,
float  f 
)

Magnitude response in dB at frequency f (for EQ curve drawing and tests).

◆ db_to_lin()

float db_to_lin ( float  db)

◆ dsp_active_flags()

uint32_t dsp_active_flags ( const dsp_t *  d)

◆ dsp_config_defaults()

void dsp_config_defaults ( dsp_config_t *  c)

◆ dsp_configure()

void dsp_configure ( dsp_t *  d,
const dsp_config_t *  cfg,
uint32_t  sample_rate,
uint8_t  channels 
)

(Re)configure for a format. Keeps filter state when only gains change.

◆ dsp_create()

dsp_t * dsp_create ( void  )

◆ dsp_destroy()

void dsp_destroy ( dsp_t *  d)

◆ dsp_is_bypass()

bool dsp_is_bypass ( const dsp_t *  d)

◆ dsp_process()

void dsp_process ( dsp_t *  d,
int32_t *  pcm,
uint32_t  frames 
)

in place

◆ dsp_process_out()

uint32_t dsp_process_out ( dsp_t *  d,
int32_t *  pcm,
uint32_t  frames,
uint32_t  cap_frames 
)

dsp_process() with room for more output.

While active the chain delays the audio by the limiter lookahead. When it goes to bypass (a gain ramp ended at unity, or dsp_configure() switched every stage off), that delayed audio is played out instead of dropped: after the chunk when the switch happened inside this call, before it when it happened earlier. Later chunks pass bit-exact. pcm holds frames frames and has room for cap_frames; returns the frames now in pcm. frames may be 0 (only the delayed audio, e.g. at the end of the stream). Without room for DSP_DRAIN_MAX more frames the delayed audio is dropped, as dsp_process() does.

◆ dsp_reset()

void dsp_reset ( dsp_t *  d)

clear filter state (seek, track change)

◆ dsp_set_replaygain()

void dsp_set_replaygain ( dsp_t *  d,
float  track_gain_db,
float  track_peak,
float  album_gain_db,
float  album_peak,
bool  album_context 
)

ReplayGain values of the current track (NAN when absent). Call on track change.

◆ eq_builtin_count()

uint32_t eq_builtin_count ( void  )

Built-in presets: "Flat", "Bass", "Treble", "Vocal", "Loudness". Index 0 is Flat.

◆ eq_builtin_get()

const eq_preset_t * eq_builtin_get ( uint32_t  index)

◆ eq_preset_format_autoeq()

int eq_preset_format_autoeq ( const eq_preset_t *  p,
char *  out,
size_t  out_size 
)

Write the same text format (so presets round-trip). Returns bytes written or <0.

◆ eq_preset_parse_autoeq()

int eq_preset_parse_autoeq ( const char *  text,
eq_preset_t *  out 
)

Parse AutoEQ "ParametricEQ.txt" (lines like "Preamp: -6.3 dB" and "Filter 1: ON PK Fc 105 Hz Gain -2.9 dB Q 0.70", types PK, LSC, HSC, LS, HS, LP, HP).

Returns CORE_OK or CORE_ECORRUPT. Extra bands beyond DSP_MAX_BANDS are dropped with a warning.

◆ lin_to_db()

float lin_to_db ( float  lin)

◆ pcm_f32_to_q31()

void pcm_f32_to_q31 ( const float *  in,
int32_t *  out,
size_t  samples 
)

saturating

◆ pcm_mono_to_stereo()

void pcm_mono_to_stereo ( const int32_t *  in,
int32_t *  out,
size_t  frames 
)

Upmix mono Q31 to stereo. in == out is allowed (the buffer must hold 2*frames samples).

◆ pcm_q31_to_f32()

void pcm_q31_to_f32 ( const int32_t *  in,
float *  out,
size_t  samples 
)

Q31 <-> float.

◆ pcm_q31_to_s16_dither()

void pcm_q31_to_s16_dither ( const int32_t *  in,
int16_t *  out,
size_t  samples,
uint32_t *  state 
)

Reduce to 16 bits with TPDF dither (state = LCG seed, keep per stream).