ascii-chat 0.11.33
Video chat in your terminal
Loading...
Searching...
No Matches
audio.h File Reference

ascii-chat Client Audio Processing Management Interface More...

Go to the source code of this file.

Functions

void audio_process_received_samples (const float *samples, int num_samples)
 Process received audio samples from server.
 
int audio_client_init (void)
 Initialize audio subsystem.
 
void audio_sender_init (void)
 Initialize audio sender thread.
 
void audio_sender_cleanup (void)
 Cleanup async audio sender.
 
void audio_sender_finalize (void)
 
int audio_start_thread (void)
 Start audio capture thread.
 
void audio_stop_thread (void)
 Stop audio capture thread.
 
bool audio_thread_exited (void)
 Check if audio capture thread has exited.
 
void audio_cleanup (void)
 Cleanup audio subsystem.
 
client_audio_pipeline_t * audio_get_pipeline (void)
 Get the audio pipeline (for advanced usage)
 
int audio_decode_opus (const uint8_t *opus_data, size_t opus_len, float *output, int max_samples)
 Decode Opus packet using the audio pipeline.
 
audio_context_t * audio_get_context (void)
 Get the global audio context for use by other subsystems.
 

Detailed Description

ascii-chat Client Audio Processing Management Interface

Defines the interface for audio system initialization, capture thread management, and audio sample processing in the ascii-chat client.

The audio subsystem handles bidirectional audio streaming using Opus encoding and PortAudio for platform-independent audio capture and playback.

Audio Pipeline

  • Capture: Microphone → PortAudio → Opus encoder → Send to server
  • Playback: Server packet → Opus decoder → Ring buffer → PortAudio → Speaker

Configuration

Options:

  • --audio: Enable audio (disabled by default)
  • --audio-device <index>: Select audio input/output device

Parameters:

  • Sample rate: 44100 Hz
  • Channels: 1 (mono)
  • Format: 32-bit float samples
  • Opus bitrate: Variable (16-48 kbps)
  • Batch size: 256 samples (~5.8ms at 44.1kHz)
  • Ring buffer: 8192 samples (~185ms jitter buffer)
Author
Zachary Fogg me@zf.nosp@m.o.gg
Date
2025
See also
topic_client_audio "Audio Architecture"

Definition in file src/client/audio.h.

Function Documentation

◆ audio_sender_cleanup()

void audio_sender_cleanup ( void  )

Cleanup async audio sender.

Signal the asynchronous audio sender to stop before worker threads are joined.

Definition at line 387 of file src/client/audio.c.

387 {
388 // Signal thread to exit
389 if (lifecycle_is_initialized(&g_audio_send_queue_lc)) {
390 atomic_store_bool(&g_audio_sender_should_exit, true);
391 mutex_lock(&g_audio_send_queue_mutex);
392 cond_signal(&g_audio_send_queue_cond);
393 mutex_unlock(&g_audio_send_queue_mutex);
394 }
395
396 // The worker is joined by thread_pool_stop_all() in protocol_stop_connection().
397 // Keep the queue synchronization objects alive until that join completes.
398 if (THREAD_IS_CREATED(g_audio_sender_thread_created)) {
399 log_debug("Audio sender thread will be joined by thread pool");
400 }
401}
void atomic_store_bool(atomic_t *a, bool value)
Atomically store a boolean value.
Definition atomic.c:177
#define log_debug(...)
Log a DEBUG message.
Definition log/log.h:548
#define mutex_lock(mutex)
Lock a mutex (with debug tracking in debug builds)
int cond_signal(cond_t *cond)
Signal a condition variable (wake one waiting thread)
#define mutex_unlock(mutex)
Unlock a mutex (with debug tracking in debug builds)
#define THREAD_IS_CREATED(created_flag)
bool lifecycle_is_initialized(const lifecycle_t *lc)
Definition lifecycle.c:155

References atomic_store_bool(), cond_signal(), lifecycle_is_initialized(), log_debug, mutex_lock, mutex_unlock, and THREAD_IS_CREATED.

Referenced by audio_cleanup(), and protocol_stop_connection().

◆ audio_sender_finalize()

void audio_sender_finalize ( void  )

Release asynchronous audio sender resources after its worker has been joined.

Definition at line 403 of file src/client/audio.c.

403 {
404 if (!lifecycle_is_initialized(&g_audio_send_queue_lc)) {
405 return;
406 }
407
408 // thread_pool_stop_all() normally joins this worker. If the sender was
409 // blocked in transport I/O when the pool timeout elapsed, wait for the
410 // shutdown signal to be observed before destroying its queue mutex.
411 for (int i = 0; i < 200 && !atomic_load_bool(&g_audio_sender_exited); i++) {
413 }
414 if (!atomic_load_bool(&g_audio_sender_exited)) {
415 log_warn("Audio sender thread did not exit before queue cleanup");
416 return;
417 }
418
419 mutex_destroy(&g_audio_send_queue_mutex);
420 cond_destroy(&g_audio_send_queue_cond);
421 lifecycle_shutdown(&g_audio_send_queue_lc);
422 g_audio_sender_thread_created = false;
423}
bool atomic_load_bool(atomic_t *a)
Atomically load a boolean value.
Definition atomic.c:169
#define log_warn(...)
Log a WARN message.
Definition log/log.h:574
#define US_PER_MS_INT
Definition time.h:160
void platform_sleep_us(unsigned int us)
High-precision sleep function with microsecond precision.
int cond_destroy(cond_t *cond)
Destroy a condition variable.
int mutex_destroy(mutex_t *mutex)
Destroy a mutex.
Definition threading.c:22
bool lifecycle_shutdown(lifecycle_t *lc)
Definition lifecycle.c:108

References atomic_load_bool(), cond_destroy(), lifecycle_is_initialized(), lifecycle_shutdown(), log_warn, mutex_destroy(), platform_sleep_us(), and US_PER_MS_INT.

Referenced by protocol_stop_connection().