ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
spectral.c File Reference

Go to the source code of this file.

Data Structures

struct  spectral_processor
 spectral processor keeps the values that move through the subsystem: config, forward, inverse, pitch_hz. Some members are pointers into caller- or subsystem-owned memory, so lifetime follows the API that populated them rather than the struct copy itself. More...

Macros

#define SPECTRAL_MAX_SIZE   2048
#define SPECTRAL_MAX_BINS   (SPECTRAL_MAX_SIZE / 2 + 1)

Functions

spectral_config_t spectral_default_config (int sample_rate)
void spectral_reset (spectral_processor_t *p)
asciichat_error_t spectral_create (const spectral_config_t *c, spectral_processor_t **out)
void spectral_destroy (spectral_processor_t *p)
asciichat_error_t spectral_process (spectral_processor_t *p, const float *input, float *output, size_t count)
const float * spectral_spectrum (const spectral_processor_t *p, size_t *bins)
float spectral_pitch_hz (const spectral_processor_t *p)

Variables

static_mutex_t audio_fftw_planner_lock = STATIC_MUTEX_INIT

Macro Definition Documentation

◆ SPECTRAL_MAX_BINS

#define SPECTRAL_MAX_BINS   (SPECTRAL_MAX_SIZE / 2 + 1)

Definition at line 10 of file spectral.c.

Referenced by spectral_reset().

◆ SPECTRAL_MAX_SIZE

#define SPECTRAL_MAX_SIZE   2048

Definition at line 9 of file spectral.c.

Function Documentation

◆ spectral_create()

asciichat_error_t spectral_create ( const spectral_config_t * c,
spectral_processor_t ** out )

Definition at line 68 of file spectral.c.

68 {
69 if (!out)
70 return SET_ERRNO(ERROR_INVALID_PARAM, "Missing spectral output pointer");
71 *out = NULL;
72 if (!c || c->sample_rate < 16000 || c->sample_rate > 192000 ||
73 (c->fft_size != 512 && c->fft_size != 1024 && c->fft_size != 2048) || !isfinite(c->reduction_db) ||
74 c->reduction_db < 0 || c->reduction_db > 60)
75 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid spectral configuration");
76 for (int b = 0; b < 4; ++b) {
77 if (!isfinite(c->ratios[b]) || c->ratios[b] < 1 || c->ratios[b] > 20 || !isfinite(c->thresholds_db[b]) ||
78 c->thresholds_db[b] > 0 || c->thresholds_db[b] < -90)
79 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid spectral compressor band");
80 if (b < 3 && (!isfinite(c->crossovers[b]) || c->crossovers[b] <= 0 || c->crossovers[b] > c->sample_rate / 2.0f ||
81 (b && c->crossovers[b] <= c->crossovers[b - 1])))
82 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid spectral crossover");
83 }
85 if (!p)
86 return SET_ERRNO(ERROR_MEMORY, "Cannot allocate spectral processor");
87 p->config = *c;
88 (void)NAMED_REGISTER_MUTEX(&audio_fftw_planner_lock, "audio.fftw_planner", NULL);
89 static_mutex_lock(&audio_fftw_planner_lock);
90 p->forward = fftw_plan_dft_r2c_1d(c->fft_size, p->time, p->frequency, FFTW_ESTIMATE);
91 p->inverse = fftw_plan_dft_c2r_1d(c->fft_size, p->frequency, p->restored, FFTW_ESTIMATE);
92 static_mutex_unlock(&audio_fftw_planner_lock);
93 if (!p->forward || !p->inverse) {
95 return SET_ERRNO(ERROR_MEMORY, "Cannot create FFTW plans");
96 }
97 for (int i = 0; i < c->fft_size; ++i)
98 p->window[i] = (float)(0.5 - 0.5 * cos(6.283185307179586 * i / c->fft_size));
100 *out = p;
101 return ASCIICHAT_OK;
102}
#define SET_ERRNO(code,...)
#define SAFE_CALLOC(count, size, cast)
Definition common.h:275
#define NAMED_REGISTER_MUTEX(mutex, name, parent_ptr)
Register a mutex with automatic format specifier.
@ ERROR_MEMORY
Definition error_codes.h:51
@ ASCIICHAT_OK
Definition error_codes.h:46
@ ERROR_INVALID_PARAM
static bool size_t gotel_query_t * out
Definition queries.h:8
static_mutex_t audio_fftw_planner_lock
Definition spectral.c:34
void spectral_destroy(spectral_processor_t *p)
Definition spectral.c:104
void spectral_reset(spectral_processor_t *p)
Definition spectral.c:46
struct spectral_processor spectral_processor_t
Definition spectral.h:15
float ratios[4]
Definition spectral.h:30
float crossovers[4 - 1]
Definition spectral.h:28
float thresholds_db[4]
Definition spectral.h:29
fftw_plan forward
Definition spectral.c:19
spectral_config_t config
Definition spectral.c:18
double time[2048]
Definition spectral.c:20
float window[2048]
Definition spectral.c:23
fftw_complex frequency[(2048/2+1)]
Definition spectral.c:21
double restored[2048]
Definition spectral.c:20
fftw_plan inverse
Definition spectral.c:19

References ASCIICHAT_OK, audio_fftw_planner_lock, spectral_processor::config, spectral_config_t::crossovers, ERROR_INVALID_PARAM, ERROR_MEMORY, spectral_config_t::fft_size, spectral_processor::forward, spectral_processor::frequency, spectral_processor::inverse, NAMED_REGISTER_MUTEX, out, spectral_config_t::ratios, spectral_config_t::reduction_db, spectral_processor::restored, SAFE_CALLOC, spectral_config_t::sample_rate, SET_ERRNO, spectral_destroy(), spectral_reset(), spectral_config_t::thresholds_db, spectral_processor::time, and spectral_processor::window.

Referenced by audio_processor_create(), and mixer_create_channels().

◆ spectral_default_config()

spectral_config_t spectral_default_config ( int sample_rate)

Definition at line 36 of file spectral.c.

36 {
37 return (spectral_config_t){.sample_rate = sample_rate,
38 .fft_size = 1024,
39 .noise_gate = true,
40 .reduction_db = 18.0f,
41 .crossovers = {250, 2000, 8000},
42 .thresholds_db = {-18, -18, -18, -18},
43 .ratios = {2, 3, 3, 2}};
44}
For spectral config, this is the live record that ties sample_rate, fft_size, noise_gate,...
Definition spectral.h:19

Referenced by audio_processor_default_config(), and mixer_create_channels().

◆ spectral_destroy()

void spectral_destroy ( spectral_processor_t * p)

Definition at line 104 of file spectral.c.

104 {
105 if (!p)
106 return;
107 static_mutex_lock(&audio_fftw_planner_lock);
108 if (p->forward)
109 fftw_destroy_plan(p->forward);
110 if (p->inverse)
111 fftw_destroy_plan(p->inverse);
112 static_mutex_unlock(&audio_fftw_planner_lock);
113 SAFE_FREE(p);
114}
#define SAFE_FREE(ptr)
Definition common.h:377

References audio_fftw_planner_lock, spectral_processor::forward, spectral_processor::inverse, and SAFE_FREE.

Referenced by audio_processor_create(), audio_processor_destroy(), mixer_destroy(), and spectral_create().

◆ spectral_pitch_hz()

float spectral_pitch_hz ( const spectral_processor_t * processor)

Latest input spectrum, normalized to sinusoidal peak amplitude; owner thread only.

Definition at line 301 of file spectral.c.

301 {
302 return p ? p->pitch_hz : 0;
303}

References spectral_processor::pitch_hz.

◆ spectral_process()

asciichat_error_t spectral_process ( spectral_processor_t * processor,
const float * input,
float * output,
size_t count )

Arbitrary block sizes and in-place operation; no allocation or locks.

Definition at line 279 of file spectral.c.

279 {
280 if (!p || (!input && count) || (!output && count))
281 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid spectral buffer");
282 int n = p->config.fft_size, hop = n / 4;
283 for (size_t i = 0; i < count; ++i) {
284 float sample = input[i];
285 output[i] = p->ready[p->cursor++];
286 p->input[n - hop + p->pending++] = isfinite(sample) ? sample : 0;
287 if (p->pending == hop) {
288 process_frame(p);
289 p->pending = p->cursor = 0;
290 }
291 }
292 return ASCIICHAT_OK;
293}
float input[2048]
Definition spectral.c:22
float ready[2048/4]
Definition spectral.c:22

References ASCIICHAT_OK, spectral_processor::config, spectral_processor::cursor, ERROR_INVALID_PARAM, spectral_config_t::fft_size, spectral_processor::input, spectral_processor::pending, spectral_processor::ready, and SET_ERRNO.

Referenced by audio_processor_process().

◆ spectral_reset()

void spectral_reset ( spectral_processor_t * p)

Definition at line 46 of file spectral.c.

46 {
47 if (!p)
48 return;
49 memset(p->input, 0, sizeof(p->input));
50 memset(p->overlap, 0, sizeof(p->overlap));
51 memset(p->ready, 0, sizeof(p->ready));
52 memset(p->noise, 0, sizeof(p->noise));
53 memset(p->smoothed, 0, sizeof(p->smoothed));
54 memset(p->magnitude, 0, sizeof(p->magnitude));
55 memset(p->band_average, 0, sizeof(p->band_average));
56 for (int i = 0; i < SPECTRAL_MAX_BINS; ++i)
57 p->gains[i] = 1;
58 for (int i = 0; i < 4; ++i)
59 p->band_gain[i] = p->eq_gain[i] = 1;
60 p->pending = p->cursor = 0;
61 memset(p->previous_phase, 0, sizeof(p->previous_phase));
62 memset(p->synthesis_phase, 0, sizeof(p->synthesis_phase));
63 p->pitch_hz = 0;
64 p->auto_gain = 1;
65 p->frames = 0;
66}
#define SPECTRAL_MAX_BINS
Definition spectral.c:10
float band_gain[SPECTRAL_BAND_COUNT]
Definition spectral.c:25
double previous_phase[(2048/2+1)]
Definition spectral.c:26
float band_average[4]
Definition spectral.c:25
float overlap[2048]
Definition spectral.c:22
float eq_gain[4]
Definition spectral.c:25
float smoothed[(2048/2+1)]
Definition spectral.c:24
double synthesis_phase[(2048/2+1)]
Definition spectral.c:26
float gains[(2048/2+1)]
Definition spectral.c:24
float magnitude[(2048/2+1)]
Definition spectral.c:23
float noise[(2048/2+1)]
Definition spectral.c:24

References spectral_processor::auto_gain, spectral_processor::band_average, spectral_processor::band_gain, spectral_processor::cursor, spectral_processor::eq_gain, spectral_processor::frames, spectral_processor::gains, spectral_processor::input, spectral_processor::magnitude, spectral_processor::noise, spectral_processor::overlap, spectral_processor::pending, spectral_processor::pitch_hz, spectral_processor::previous_phase, spectral_processor::ready, spectral_processor::smoothed, SPECTRAL_MAX_BINS, and spectral_processor::synthesis_phase.

Referenced by audio_processor_reset(), mixer_remove_source(), and spectral_create().

◆ spectral_spectrum()

const float * spectral_spectrum ( const spectral_processor_t * p,
size_t * bins )

Definition at line 295 of file spectral.c.

295 {
296 if (bins)
297 *bins = p ? (size_t)p->config.fft_size / 2 + 1 : 0;
298 return p ? p->magnitude : NULL;
299}

References spectral_processor::config, spectral_config_t::fft_size, and spectral_processor::magnitude.

Variable Documentation

◆ audio_fftw_planner_lock

static_mutex_t audio_fftw_planner_lock = STATIC_MUTEX_INIT

Definition at line 34 of file spectral.c.

Referenced by audio_visualization_fft_init(), spectral_create(), and spectral_destroy().