ascii-chat 0.11.33
Video chat in your terminal
Loading...
Searching...
No Matches
mixer.h
Go to the documentation of this file.
1#pragma once
2
78#include <stdbool.h>
79#include <stdint.h>
80
81// Include ringbuffer.h to get the audio_ring_buffer_t type
82#include "../ringbuffer.h"
83#include "../platform/rwlock.h"
84#include "../asciichat_errno.h"
85
86#ifdef __cplusplus
87extern "C" {
88#endif
89
104#define MIXER_MAX_SOURCES 32 // Increased to match MAX_CLIENTS
105
114#define MIXER_FRAME_SIZE 256
115
162
201
218typedef struct {
223
225 float alpha;
231
241typedef struct {
246
248 float alpha;
252
292
325typedef struct {
332
335 // Each listener owns its unread samples from each remote source.
338 const char **source_ids;
341
345 uint8_t source_id_to_index[256];
347 const char *source_id_at_hash[256];
348
351
356
361
364} mixer_t;
365
385mixer_t *mixer_create(int max_sources, int sample_rate);
386
398void mixer_destroy(mixer_t *mixer);
399
424int mixer_add_source(mixer_t *mixer, const char *client_id, audio_ring_buffer_t *buffer);
425
440void mixer_remove_source(mixer_t *mixer, const char *client_id);
441
457void mixer_set_source_active(mixer_t *mixer, const char *client_id, bool active);
458
459/* ============================================================================
460 * Mixer Hash Table Helpers (Internal API)
461 * ============================================================================ */
462
464#define MIXER_HASH_INVALID 0xFF
465
472static inline uint8_t mixer_hash_client_id(uint32_t client_id) {
473 return (uint8_t)(client_id & 0xFF);
474}
475
482static inline void mixer_hash_mark_invalid(mixer_t *mixer, uint32_t client_id) {
483 if (mixer) {
484 mixer->source_id_to_index[mixer_hash_client_id(client_id)] = MIXER_HASH_INVALID;
485 }
486}
487
495static inline void mixer_hash_set_slot(mixer_t *mixer, uint32_t client_id, uint8_t slot) {
496 if (mixer) {
497 mixer->source_id_to_index[mixer_hash_client_id(client_id)] = slot;
498 }
499}
500
508static inline bool mixer_hash_is_invalid(mixer_t *mixer, uint32_t client_id) {
509 if (!mixer)
510 return true;
511 return mixer->source_id_to_index[mixer_hash_client_id(client_id)] == MIXER_HASH_INVALID;
512}
513
521static inline uint8_t mixer_hash_get_slot(mixer_t *mixer, uint32_t client_id) {
522 if (!mixer)
523 return MIXER_HASH_INVALID;
524 return mixer->source_id_to_index[mixer_hash_client_id(client_id)];
525}
526
555int mixer_process(mixer_t *mixer, float *output, int num_samples);
556
575int mixer_process_excluding_source(mixer_t *mixer, float *output, int num_samples, uint32_t exclude_client_id);
576
594float db_to_linear(float db);
595
605float linear_to_db(float linear);
606
619float clamp_float(float value, float min, float max);
620
639void compressor_init(compressor_t *comp, float sample_rate);
640
655void compressor_set_params(compressor_t *comp, float threshold_dB, float ratio, uint64_t attack_ns, uint64_t release_ns,
656 float makeup_dB);
657
672float compressor_process_sample(compressor_t *comp, float sidechain);
673
696int ducking_init(ducking_t *duck, int num_sources, float sample_rate);
697
706void ducking_destroy(ducking_t *duck);
707
722void ducking_set_params(ducking_t *duck, float threshold_dB, float leader_margin_dB, float atten_dB, uint64_t attack_ns,
723 uint64_t release_ns);
724
740void ducking_process_frame(ducking_t *duck, float *envelopes, float *gains, int num_sources);
741
760void noise_gate_init(noise_gate_t *gate, float sample_rate);
761
775void noise_gate_set_params(noise_gate_t *gate, float threshold, uint64_t attack_ns, uint64_t release_ns,
776 float hysteresis);
777
792float noise_gate_process_sample(noise_gate_t *gate, float input, float peak_amplitude);
793
806void noise_gate_process_buffer(noise_gate_t *gate, float *buffer, int num_samples);
807
817bool noise_gate_is_open(const noise_gate_t *gate);
818
838void highpass_filter_init(highpass_filter_t *filter, float cutoff_hz, float sample_rate);
839
850
862float highpass_filter_process_sample(highpass_filter_t *filter, float input);
863
874void highpass_filter_process_buffer(highpass_filter_t *filter, float *buffer, int num_samples);
875
895void lowpass_filter_init(lowpass_filter_t *filter, float cutoff_hz, float sample_rate);
896
906
918float lowpass_filter_process_sample(lowpass_filter_t *filter, float input);
919
930void lowpass_filter_process_buffer(lowpass_filter_t *filter, float *buffer, int num_samples);
931
950float smoothstep(float t);
951
962int16_t float_to_int16(float sample);
963
973float int16_to_float(int16_t sample);
974
985void buffer_float_to_int16(const float *src, int16_t *dst, int count);
986
997void buffer_int16_to_float(const int16_t *src, float *dst, int count);
998
1010float buffer_peak(const float *buffer, int count);
1011
1022void apply_gain_buffer(float *buffer, int count, float gain);
1023
1036void fade_buffer(float *buffer, int count, float start_gain, float end_gain);
1037
1048void fade_buffer_smooth(float *buffer, int count, bool fade_in);
1049
1062void copy_buffer_with_gain(const float *src, float *dst, int count, float gain);
1063
1092float soft_clip(float sample, float threshold, float steepness);
1093
1105void soft_clip_buffer(float *buffer, int num_samples, float threshold, float steepness);
1106
1109#ifdef __cplusplus
1110}
1111#endif
float hysteresis
Hysteresis factor (0-1, prevents gate chatter)
Definition mixer.h:188
float release_coeff
Release coefficient (converted from release_ms)
Definition mixer.h:197
bool noise_gate_is_open(const noise_gate_t *gate)
Check if noise gate is currently open.
Definition mixer.c:1001
uint8_t source_id_to_index[256]
Hash table mapping client_id → mixer source index (uses hash function for strings)
Definition mixer.h:345
float base_gain
Base gain before crowd scaling is applied.
Definition mixer.h:355
void copy_buffer_with_gain(const float *src, float *dst, int count, float gain)
Copy buffer with gain scaling.
Definition mixer.c:1218
float leader_margin_dB
Leader margin in dB (sources within this of loudest are leaders)
Definition mixer.h:275
void noise_gate_process_buffer(noise_gate_t *gate, float *buffer, int num_samples)
Process a buffer of samples through noise gate.
Definition mixer.c:982
void buffer_float_to_int16(const float *src, int16_t *dst, int count)
Convert float buffer to int16 buffer.
Definition mixer.c:1157
float alpha
Filter coefficient alpha (calculated from cutoff_hz)
Definition mixer.h:225
float release_coeff
Release coefficient (converted from release_ms)
Definition mixer.h:286
float clamp_float(float value, float min, float max)
Clamp a float value to a range.
Definition mixer.c:75
const char ** source_ids
Array of client ID strings (one per source slot)
Definition mixer.h:338
float ratio
Compression ratio (e.g., 4.0 for 4:1 compression)
Definition mixer.h:143
void highpass_filter_reset(highpass_filter_t *filter)
Reset high-pass filter state.
Definition mixer.c:1024
float sample_rate
Sample rate in Hz (set during initialization)
Definition mixer.h:222
void soft_clip_buffer(float *buffer, int num_samples, float threshold, float steepness)
Apply soft clipping to a buffer.
Definition mixer.c:1122
float prev_input
Previous input sample (filter state)
Definition mixer.h:227
float prev_output
Previous output sample (filter state)
Definition mixer.h:250
#define MIXER_MAX_SOURCES
Maximum number of simultaneous audio sources.
Definition mixer.h:104
float highpass_filter_process_sample(highpass_filter_t *filter, float input)
Process a single sample through high-pass filter.
Definition mixer.c:1032
float envelope
Current envelope follower state (linear, 0-1)
Definition mixer.h:154
bool * source_active
Array of active flags (true if source is active)
Definition mixer.h:340
float cutoff_hz
Cutoff frequency in Hz (frequencies above this are attenuated)
Definition mixer.h:243
void apply_gain_buffer(float *buffer, int count, float gain)
Apply gain to buffer in-place.
Definition mixer.c:1186
float atten_dB
Attenuation in dB for non-leader sources.
Definition mixer.h:277
rwlock_t source_lock
Reader-writer lock protecting source arrays and bitset.
Definition mixer.h:350
float * gain
Per-source ducking gain (linear, calculated from envelope)
Definition mixer.h:290
float attack_coeff
Attack coefficient (converted from attack_ms)
Definition mixer.h:284
uint64_t release_ns
Ducking release time in nanoseconds.
Definition mixer.h:281
float threshold_dB
Speaking threshold in dB (sources below this are not "speaking")
Definition mixer.h:273
void ducking_process_frame(ducking_t *duck, float *envelopes, float *gains, int num_sources)
Process a frame of audio through ducking system.
Definition mixer.c:228
void noise_gate_init(noise_gate_t *gate, float sample_rate)
Initialize a noise gate.
Definition mixer.c:925
float crowd_alpha
Crowd scaling exponent (typically 0.5 for sqrt scaling)
Definition mixer.h:353
void ducking_destroy(ducking_t *duck)
Free ducking system resources.
Definition mixer.c:210
float buffer_peak(const float *buffer, int count)
Find peak absolute value in buffer.
Definition mixer.c:1173
ducking_t ducking
Ducking system (active speaker detection and attenuation)
Definition mixer.h:358
float cutoff_hz
Cutoff frequency in Hz (frequencies below this are attenuated)
Definition mixer.h:220
int num_sources
Current number of active audio sources.
Definition mixer.h:327
float soft_clip(float sample, float threshold, float steepness)
Apply soft clipping to a sample.
Definition mixer.c:1109
float sample_rate
Sample rate in Hz (set during initialization)
Definition mixer.h:191
float knee_dB
Knee width in dB for soft knee (e.g., 2.0)
Definition mixer.h:141
void mixer_remove_source(mixer_t *mixer, const char *client_id)
Remove an audio source from the mixer.
Definition mixer.c:477
void fade_buffer(float *buffer, int count, float start_gain, float end_gain)
Apply linear fade to buffer in-place.
Definition mixer.c:1195
void compressor_init(compressor_t *comp, float sample_rate)
Initialize a compressor.
Definition mixer.c:86
float alpha
Filter coefficient alpha (calculated from cutoff_hz)
Definition mixer.h:248
void compressor_set_params(compressor_t *comp, float threshold_dB, float ratio, uint64_t attack_ns, uint64_t release_ns, float makeup_dB)
Set compressor parameters.
Definition mixer.c:97
uint64_t attack_ns
Attack time in nanoseconds (how fast gate opens)
Definition mixer.h:184
int ducking_init(ducking_t *duck, int num_sources, float sample_rate)
Initialize ducking system.
Definition mixer.c:155
void highpass_filter_init(highpass_filter_t *filter, float cutoff_hz, float sample_rate)
Initialize a high-pass filter.
Definition mixer.c:1010
uint64_t active_sources_mask
Bitset of active sources (bit i = source i is active, O(1) iteration)
Definition mixer.h:343
float int16_to_float(int16_t sample)
Convert int16 sample to float.
Definition mixer.c:1153
uint64_t attack_ns
Ducking attack time in nanoseconds.
Definition mixer.h:279
float * envelope
Per-source envelope follower state (linear, allocated per source)
Definition mixer.h:288
float threshold_dB
Compression threshold in dB (e.g., -10.0)
Definition mixer.h:139
int max_sources
Maximum number of sources (allocated array sizes)
Definition mixer.h:329
float * mix_buffer
Temporary buffer for mixing operations (pre-allocated)
Definition mixer.h:363
float envelope
Current envelope follower state (linear, 0-1)
Definition mixer.h:193
float sample_rate
Sample rate in Hz (set during initialization)
Definition mixer.h:152
bool gate_open
True if gate is currently open (allowing audio through)
Definition mixer.h:199
float smoothstep(float t)
Compute smoothstep interpolation.
Definition mixer.c:1136
void fade_buffer_smooth(float *buffer, int count, bool fade_in)
Apply smoothstep fade to buffer in-place.
Definition mixer.c:1207
int16_t float_to_int16(float sample)
Convert float sample to int16 (WebRTC format)
Definition mixer.c:1144
compressor_t compressor
Compressor (dynamic range compression)
Definition mixer.h:360
float sample_rate
Sample rate in Hz (set during initialization)
Definition mixer.h:245
void lowpass_filter_init(lowpass_filter_t *filter, float cutoff_hz, float sample_rate)
Initialize a low-pass filter.
Definition mixer.c:1060
mixer_t * mixer_create(int max_sources, int sample_rate)
Create a new audio mixer.
Definition mixer.c:262
int mixer_process_excluding_source(mixer_t *mixer, float *output, int num_samples, uint32_t exclude_client_id)
Process audio from all sources except one (for per-client output)
Definition mixer.c:687
float db_to_linear(float db)
Convert decibels to linear gain.
Definition mixer.c:67
void lowpass_filter_process_buffer(lowpass_filter_t *filter, float *buffer, int num_samples)
Process a buffer of samples through low-pass filter.
Definition mixer.c:1095
uint64_t release_ns
Release time in nanoseconds (how fast gate closes)
Definition mixer.h:186
#define MIXER_HASH_INVALID
Invalid index sentinel value for mixer hash table.
Definition mixer.h:464
void highpass_filter_process_buffer(highpass_filter_t *filter, float *buffer, int num_samples)
Process a buffer of samples through high-pass filter.
Definition mixer.c:1046
void ducking_set_params(ducking_t *duck, float threshold_dB, float leader_margin_dB, float atten_dB, uint64_t attack_ns, uint64_t release_ns)
Set ducking parameters.
Definition mixer.c:219
void mixer_set_source_active(mixer_t *mixer, const char *client_id, bool active)
Set whether a source is active (receiving audio)
Definition mixer.c:515
audio_ring_buffer_t ** source_buffers
Array of pointers to client audio ring buffers.
Definition mixer.h:334
float makeup_dB
Makeup gain in dB (compensates for gain reduction)
Definition mixer.h:149
float compressor_process_sample(compressor_t *comp, float sidechain)
Process a single sample through compressor.
Definition mixer.c:131
void mixer_destroy(mixer_t *mixer)
Destroy a mixer and free all resources.
Definition mixer.c:396
int sample_rate
Sample rate in Hz (e.g., 44100)
Definition mixer.h:331
uint64_t attack_ns
Attack time in nanoseconds (how fast compression kicks in)
Definition mixer.h:145
float lowpass_filter_process_sample(lowpass_filter_t *filter, float input)
Process a single sample through low-pass filter.
Definition mixer.c:1083
void noise_gate_set_params(noise_gate_t *gate, float threshold, uint64_t attack_ns, uint64_t release_ns, float hysteresis)
Set noise gate parameters.
Definition mixer.c:939
float linear_to_db(float linear)
Convert linear gain to decibels.
Definition mixer.c:71
int mixer_add_source(mixer_t *mixer, const char *client_id, audio_ring_buffer_t *buffer)
Add an audio source to the mixer.
Definition mixer.c:424
uint64_t release_ns
Release time in nanoseconds (how fast compression releases)
Definition mixer.h:147
void lowpass_filter_reset(lowpass_filter_t *filter)
Reset low-pass filter state.
Definition mixer.c:1076
float attack_coeff
Attack coefficient (converted from attack_ms)
Definition mixer.h:158
int mixer_process(mixer_t *mixer, float *output, int num_samples)
Process audio from all active sources.
Definition mixer.c:542
void buffer_int16_to_float(const int16_t *src, float *dst, int count)
Convert int16 buffer to float buffer.
Definition mixer.c:1165
float threshold
Gate threshold in linear units (e.g., 0.01f for -40dB)
Definition mixer.h:182
float prev_output
Previous output sample (filter state)
Definition mixer.h:229
float release_coeff
Release coefficient (converted from release_ms)
Definition mixer.h:160
float gain_lin
Current gain multiplier (linear, calculated from envelope)
Definition mixer.h:156
float attack_coeff
Attack coefficient (converted from attack_ms)
Definition mixer.h:195
float noise_gate_process_sample(noise_gate_t *gate, float input, float peak_amplitude)
Process a single sample through noise gate.
Definition mixer.c:957
unsigned int uint32_t
Definition common.h:58
unsigned long long uint64_t
Definition common.h:59
unsigned char uint8_t
Definition common.h:56
ClangTool/LibTooling compatibility shim for stdbool.h.
Audio ring buffer for real-time audio streaming.
Definition ringbuffer.h:205
Dynamic range compressor settings and state.
Definition mixer.h:137
Ducking system settings and state.
Definition mixer.h:271
High-pass filter settings and state.
Definition mixer.h:218
Low-pass filter state.
Definition mixer.h:241
Main mixer structure for multi-source audio processing.
Definition mixer.h:325
Noise gate settings and state.
Definition mixer.h:180
Read-write lock type (POSIX: pthread_rwlock_t with debug tracking)
Definition rwlock.h:61