ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
include/ascii-chat/audio/audio.h
Go to the documentation of this file.
1#pragma once
2
59
61#include <stdbool.h>
62#include <libplatform/atomic.h>
63#include <portaudio.h>
64#ifdef __linux__
65#include <sched.h>
66#include <sys/resource.h>
67#elif defined(__APPLE__)
68#include <mach/mach.h>
69#include <mach/thread_policy.h>
70#include <mach/kern_return.h>
71#endif
72
73#include "../common.h"
74#include <libplatform/thread.h>
75#include <libplatform/mutex.h>
76#include <libplatform/cond.h>
77#include "../ringbuffer.h"
78#include "../options/options.h"
79
80/* ============================================================================
81 * Data Structures
82 * ============================================================================
83 */
84
117typedef struct {
118 // PortAudio streams
119 PaStream *duplex_stream;
120 PaStream *input_stream;
121 PaStream *output_stream;
122
123 // New architecture: 5 ring buffers for lock-free callback → worker → network
127
128 // Legacy ring buffers (will be migrated to new architecture)
132
133 // Worker thread for heavy processing (AEC3, filters)
134 platform_thread_t worker_thread;
139
140 // Pre-allocated worker buffers (avoid malloc in worker loop)
144
145 // State flags
147 bool running;
150 atomic_t shutting_down;
151 mutex_t state_mutex;
152
153 // Audio pipeline and device info
158 double sample_rate;
174
175/* ============================================================================
176 * Audio Context Lifecycle
177 * @{
178 */
179
198
213
225
240void audio_set_pipeline(audio_context_t *ctx, void *pipeline);
241
243
244/* ============================================================================
245 * Full-Duplex Audio Control
246 * @{
247 */
248
276
290
292
293/* ============================================================================
294 * Audio I/O Operations
295 * @{
296 */
297
318asciichat_error_t audio_read_samples(audio_context_t *ctx, float *buffer, int num_samples);
319
340asciichat_error_t audio_write_samples(audio_context_t *ctx, const float *buffer, int num_samples);
341
343
344/* ============================================================================
345 * Real-Time Priority Scheduling
346 * @{
347 */
348
376
378
379/* ============================================================================
380 * Audio Device Enumeration
381 * @{
382 */
383
385#define AUDIO_DEVICE_NAME_MAX 256
386
407
424asciichat_error_t audio_list_input_devices(audio_device_info_t **out_devices, unsigned int *out_count);
425
442asciichat_error_t audio_list_output_devices(audio_device_info_t **out_devices, unsigned int *out_count);
443
454
456
457/* ============================================================================
458 * Protocol Helper Functions - Audio Format Conversion
459 * @{
460 */
461
482asciichat_error_t audio_dequantize_samples(const uint8_t *samples_ptr, uint32_t total_samples, float *out_samples);
483
485
486/* ============================================================================
487 * Audio Ring Buffer Management
488 * @{
489 */
490
510audio_ring_buffer_t *audio_ring_buffer_create_format(unsigned channels, bool capture);
513
531
544
555void audio_ring_buffer_register_atomics(audio_ring_buffer_t *rb, const char *context_name);
556
566
578
598asciichat_error_t audio_ring_buffer_write(audio_ring_buffer_t *rb, const float *data, int samples);
599
620size_t audio_ring_buffer_read(audio_ring_buffer_t *rb, float *data, size_t samples);
621
635size_t audio_ring_buffer_peek(audio_ring_buffer_t *rb, float *data, size_t samples);
636
652
668
670
671/* ============================================================================
672 * Audio Resampling Utilities
673 * @{
674 */
675
702void resample_linear(const float *src, size_t src_samples, float *dst, size_t dst_samples, double src_rate,
703 double dst_rate);
704
706
707/* ============================================================================
708 * Audio Batch Packet Format
709 * @{
710 */
711
736
770asciichat_error_t audio_parse_batch_header(const void *data, size_t len, audio_batch_info_t *out_batch);
771
801
821
833
867
⚙️ Common definitions, error codes, macros, and types shared throughout the application
audio_visualization_source_t source
Definition fft.c:24
bool audio_should_enable_microphone(audio_capture_source_t source, bool has_media_audio)
Determine if microphone should be enabled based on audio source setting and media state.
size_t audio_ring_buffer_read(audio_ring_buffer_t *rb, float *data, size_t samples)
Read audio samples from ring buffer.
void audio_free_device_list(audio_device_info_t *devices)
Free device list allocated by audio_list_input_devices/audio_list_output_devices.
asciichat_error_t audio_ring_buffer_write(audio_ring_buffer_t *rb, const float *data, int samples)
Write audio samples to ring buffer.
void audio_ring_buffer_destroy(audio_ring_buffer_t *rb)
Destroy an audio ring buffer.
asciichat_error_t audio_init(audio_context_t *ctx)
Initialize audio context and PortAudio.
asciichat_error_t audio_set_realtime_priority(void)
Request real-time priority for current thread.
audio_ring_buffer_t * audio_ring_buffer_create(void)
Create a new audio ring buffer (for playback with jitter buffering).
bool audio_is_supported_sample_rate(uint32_t sample_rate)
Check if a sample rate is a standard/supported rate.
size_t audio_ring_buffer_available_read(audio_ring_buffer_t *rb)
Get number of samples available for reading.
asciichat_error_t audio_start_duplex(audio_context_t *ctx)
Start full-duplex audio (simultaneous capture and playback).
void audio_ring_buffer_register_atomics(audio_ring_buffer_t *rb, const char *context_name)
Register audio ring buffer atomic fields for debug tracking.
asciichat_error_t audio_parse_batch_header(const void *data, size_t len, audio_batch_info_t *out_batch)
Parse an audio batch packet header from raw packet data.
void audio_destroy(audio_context_t *ctx)
Destroy audio context and clean up resources.
asciichat_error_t audio_stop_duplex(audio_context_t *ctx)
Stop full-duplex audio.
void audio_ring_buffer_unregister_atomics(audio_ring_buffer_t *rb)
Unregister audio ring buffer atomic fields.
asciichat_error_t audio_write_samples(audio_context_t *ctx, const float *buffer, int num_samples)
Write audio samples to playback buffer.
void audio_terminate_portaudio_final(void)
Terminate PortAudio and free all device resources.
void audio_flush_playback_buffers(audio_context_t *ctx)
Flush all audio buffers to synchronize with seek operations.
void audio_set_pipeline(audio_context_t *ctx, void *pipeline)
Set audio pipeline for echo cancellation.
audio_ring_buffer_t * audio_ring_buffer_create_for_capture(void)
Create a new audio ring buffer for capture (without jitter buffering).
size_t audio_ring_buffer_peek(audio_ring_buffer_t *rb, float *data, size_t samples)
Peek at available samples without consuming them (for AEC3 render signal).
asciichat_error_t audio_validate_batch_params(const audio_batch_info_t *batch)
Validate audio batch parameters for sanity.
asciichat_error_t audio_list_input_devices(audio_device_info_t **out_devices, unsigned int *out_count)
List available audio input devices (microphones).
asciichat_error_t audio_dequantize_samples(const uint8_t *samples_ptr, uint32_t total_samples, float *out_samples)
Dequantize network audio samples from int32 to float.
asciichat_error_t audio_list_output_devices(audio_device_info_t **out_devices, unsigned int *out_count)
List available audio output devices (speakers).
void audio_ring_buffer_clear(audio_ring_buffer_t *rb)
Clear all audio samples from ring buffer.
asciichat_error_t audio_read_samples(audio_context_t *ctx, float *buffer, int num_samples)
Read captured audio samples from capture buffer.
void resample_linear(const float *src, size_t src_samples, float *dst, size_t dst_samples, double src_rate, double dst_rate)
Resample audio using linear interpolation.
size_t audio_ring_buffer_available_write(audio_ring_buffer_t *rb)
Get number of sample slots available for writing.
unsigned int uint32_t
Definition common.h:62
unsigned long long uint64_t
Definition common.h:63
unsigned char uint8_t
Definition common.h:60
asciichat_error_t
Error and exit codes - unified status values (0-255).
Definition error_codes.h:44
audio_capture_source_t
Definition options.h:290
#define ASCIICHAT_API
Export symbols on Unix platforms (Linux, macOS).
Definition api.h:82
struct audio_ring_buffer audio_ring_buffer_t
Audio ring buffer for real-time audio streaming.
void audio_ring_buffer_discard_pending(audio_ring_buffer_t *rb)
void audio_ring_buffer_set_jitter_target(audio_ring_buffer_t *rb, uint32_t samples)
#define AUDIO_DEVICE_NAME_MAX
Maximum length of audio device name.
audio_ring_buffer_t * audio_ring_buffer_create_format(unsigned channels, bool capture)
⚙️ Unified options parsing system for ascii-chat with builder pattern and lock-free access
Lock-Free Ring Buffer and Frame Buffer Management.
Parsed audio batch packet header information.
uint32_t batch_count
Number of audio frames in this batch.
uint32_t channels
Number of channels (1=mono, 2=stereo).
uint32_t sample_rate
Sample rate in Hz (e.g., 48000).
uint32_t total_samples
Total number of samples across all frames.
When code needs to work with audio device info, it keeps index, max_input_channels,...
bool initialized
True if context has been initialized.
platform_thread_t worker_thread
Worker thread for audio processing.
audio_ring_buffer_t * raw_render_rb
Callback → Worker: Raw speaker samples (AEC3 reference).
double input_device_rate
Native sample rate of input device.
audio_ring_buffer_t * playback_buffer
OLD: Network → Worker (will become network_playback_rb).
float * worker_render_batch
Pre-allocated buffer for batch render processing.
float input_resample_previous
Last input sample used at a block boundary.
PaStream * input_stream
Separate input stream (when full-duplex unavailable).
bool worker_running
True if worker thread is running.
atomic_t shutting_down
True when shutdown started - callback outputs silence.
bool monitor_local_media
Play local file audio in solo sessions.
atomic_t worker_should_stop
Signal worker thread to exit.
bool input_resample_has_previous
Whether a prior input block has been processed.
void * capture_media_source
Borrowed local media audio; configure before starting duplex.
bool separate_streams
True if using separate input/output streams.
double sample_rate
Actual sample rate of streams (48kHz).
audio_ring_buffer_t * capture_buffer
OLD: Worker → Network (will become processed_capture_rb).
void * audio_pipeline
Client audio pipeline for AEC3 echo cancellation (opaque pointer).
bool running
True if duplex stream is active.
float output_resample_previous
Last source sample used at an output boundary.
audio_ring_buffer_t * render_buffer
Ring buffer for render reference (separate streams mode).
audio_ring_buffer_t * raw_capture_rb
Callback → Worker: Raw mic samples (no processing).
mutex_t audio_processing_wait_guard
Coordinates device-worker sleep with shutdown.
double output_device_rate
Native sample rate of output device.
float * worker_playback_batch
Pre-allocated buffer for batch playback processing.
double output_resample_phase
48 kHz source position carried between output callbacks
mutex_t state_mutex
Mutex protecting context state.
float * worker_capture_batch
Pre-allocated buffer for batch capture processing.
bool playback_only
True for playback-only mode (mirror), skip microphone capture.
audio_ring_buffer_t * processed_playback_rb
Worker → Callback: Ready for speakers.
PaStream * duplex_stream
PortAudio full-duplex stream (simultaneous input+output).
double input_resample_phase
Source position carried between native-rate input blocks.
PaStream * output_stream
Separate output stream (when full-duplex unavailable).
uint64_t test_audio_playback_position
Output callback's synthesized monitor sample clock.
cond_t audio_processing_wakeup
Capture/AEC work, monitor refill, or shutdown notification.
bool output_resample_has_previous
Whether a prior output block has been processed.
Audio device information structure.
int max_output_channels
Maximum output channels (0 if input only).
int max_input_channels
Maximum input channels (0 if output only).
char name[256]
Human-readable device name.
int index
PortAudio device index.
double default_sample_rate
Default sample rate in Hz.
bool is_default_output
True if this is the default output device.
bool is_default_input
True if this is the default input device.
When code needs to work with audio resampler, it keeps phase, has_previous here instead of scattering...