ascii-chat 0.11.33
Video chat in your terminal
Loading...
Searching...
No Matches
recording.c
Go to the documentation of this file.
4#include <math.h>
5#include <string.h>
6
7#define RECORDING_RATE 48000ULL
8#define RECORDING_CAPACITY (RECORDING_RATE * 30)
9
18
19static static_mutex_t recording_mutex = STATIC_MUTEX_INIT;
20static audio_recording_t *active_recording;
21
23 if (!out)
24 return SET_ERRNO(ERROR_INVALID_PARAM, "Missing recording output");
25 *out = NULL;
26 static_mutex_lock(&recording_mutex);
27 if (active_recording) {
28 static_mutex_unlock(&recording_mutex);
29 return SET_ERRNO(ERROR_INVALID_STATE, "A session recording is already active");
30 }
31 audio_recording_t *recording = SAFE_CALLOC(1, sizeof(*recording), audio_recording_t *);
32 recording->mix = SAFE_CALLOC(RECORDING_CAPACITY, sizeof(float), float *);
33 active_recording = recording;
34 *out = recording;
35 static_mutex_unlock(&recording_mutex);
36 return ASCIICHAT_OK;
37}
38
40 if (!recording)
41 return;
42 static_mutex_lock(&recording_mutex);
43 if (active_recording == recording)
44 active_recording = NULL;
45 SAFE_FREE(recording->mix);
46 SAFE_FREE(recording);
47 static_mutex_unlock(&recording_mutex);
48}
49
51 if (!recording)
52 return;
53 static_mutex_lock(&recording_mutex);
54 if (!recording->started) {
55 recording->epoch_ns = epoch_ns;
56 recording->started = true;
57 }
58 static_mutex_unlock(&recording_mutex);
59}
60
61void audio_recording_submit(audio_recording_source_t source, const float *samples, size_t count, uint64_t start_ns) {
62 if (!samples || source < 0 || source >= AUDIO_RECORDING_SOURCE_COUNT)
63 return;
64 static_mutex_lock(&recording_mutex);
65 audio_recording_t *recording = active_recording;
66 if (!recording || !recording->started) {
67 static_mutex_unlock(&recording_mutex);
68 return;
69 }
70 uint64_t delta = start_ns > recording->epoch_ns ? start_ns - recording->epoch_ns : 0;
71 uint64_t position = delta / 1000000000ULL * RECORDING_RATE + delta % 1000000000ULL * RECORDING_RATE / 1000000000ULL;
72 /* Smooth callback jitter while preserving gaps longer than 100 ms. */
73 if (recording->source_started[source] && position < recording->source_position[source] + RECORDING_RATE / 10)
74 position = recording->source_position[source];
75 if (position < recording->read_position)
76 position = recording->read_position;
77 recording->source_started[source] = true;
78 recording->source_position[source] = position + count;
79 for (size_t i = 0; i < count; i++, position++) {
80 if (position >= recording->read_position && position - recording->read_position < RECORDING_CAPACITY &&
81 isfinite(samples[i]))
82 recording->mix[position % RECORDING_CAPACITY] += samples[i];
83 }
84 static_mutex_unlock(&recording_mutex);
85}
86
87void audio_recording_read(audio_recording_t *recording, float *samples, size_t count) {
88 if (!recording || !samples)
89 return;
90 static_mutex_lock(&recording_mutex);
91 for (size_t i = 0; i < count; i++) {
92 size_t slot = recording->read_position++ % RECORDING_CAPACITY;
93 float sample = recording->mix[slot];
94 samples[i] = fmaxf(-1.0f, fminf(1.0f, sample));
95 recording->mix[slot] = 0;
96 }
97 static_mutex_unlock(&recording_mutex);
98}
#define SAFE_FREE(ptr)
Definition common.h:376
#define SAFE_CALLOC(count, size, cast)
Definition common.h:274
unsigned long long uint64_t
Definition common.h:59
#define SET_ERRNO(code, context_msg,...)
Set error code with custom context message and log it, returning the error code.
asciichat_error_t
Error and exit codes - unified status values (0-255)
Definition error_codes.h:49
@ ERROR_INVALID_STATE
@ ASCIICHAT_OK
Definition error_codes.h:51
@ ERROR_INVALID_PARAM
Platform initialization and static synchronization helpers.
🔢 Mathematical Utility Functions
Cross-platform memory allocation utilities.
void audio_recording_submit(audio_recording_source_t source, const float *samples, size_t count, uint64_t start_ns)
Definition recording.c:61
#define RECORDING_CAPACITY
Definition recording.c:8
void audio_recording_read(audio_recording_t *recording, float *samples, size_t count)
Definition recording.c:87
void audio_recording_destroy(audio_recording_t *recording)
Definition recording.c:39
void audio_recording_start(audio_recording_t *recording, uint64_t epoch_ns)
Definition recording.c:50
asciichat_error_t audio_recording_create(audio_recording_t **out)
Definition recording.c:22
#define RECORDING_RATE
Definition recording.c:7
audio_recording_source_t
Definition recording.h:9
@ AUDIO_RECORDING_SOURCE_COUNT
Definition recording.h:13
bool source_started[AUDIO_RECORDING_SOURCE_COUNT]
Definition recording.c:16
uint64_t epoch_ns
Definition recording.c:12
uint64_t source_position[AUDIO_RECORDING_SOURCE_COUNT]
Definition recording.c:14
uint64_t read_position
Definition recording.c:13
Static mutex structure for global mutexes requiring static initialization.