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

Go to the source code of this file.

Functions

asciichat_error_t audio_route_capture (const float *input, size_t frames, unsigned channels, int first_channel, unsigned selected_channels, float *output)
asciichat_error_t audio_convert_channels (const float *input, size_t frames, unsigned input_channels, float *output, unsigned output_channels)
size_t audio_resample_stereo (audio_resampler_t *state, const float *input, size_t frames, double input_rate, float *output, size_t capacity, double output_rate)

Function Documentation

◆ audio_convert_channels()

asciichat_error_t audio_convert_channels ( const float * input,
size_t frames,
unsigned input_channels,
float * output,
unsigned output_channels )

Convert interleaved mono/stereo PCM. In-place conversion is supported in both directions.

Definition at line 28 of file audio/format.c.

29 {
30 if (!input || !output || (input_channels != 1 && input_channels != 2) ||
31 (output_channels != 1 && output_channels != 2))
32 return SET_ERRNO(ERROR_INVALID_PARAM, "Only mono and stereo PCM are supported");
33 // Backwards iteration also permits in-place mono expansion.
34 if (input_channels == 1 && output_channels == 2) {
35 for (size_t frame = frames; frame > 0; frame--)
36 output[(frame - 1) * 2] = output[(frame - 1) * 2 + 1] = input[frame - 1];
37 } else {
38 for (size_t frame = 0; frame < frames; frame++) {
39 float left = input[frame * input_channels];
40 float right = input_channels == 2 ? input[frame * input_channels + 1] : left;
41 if (output_channels == 1)
42 output[frame] = left * 0.5f + right * 0.5f;
43 else {
44 output[frame * 2] = left;
45 output[frame * 2 + 1] = right;
46 }
47 }
48 }
49 return ASCIICHAT_OK;
50}
#define SET_ERRNO(code,...)
@ ASCIICHAT_OK
Definition error_codes.h:46
@ ERROR_INVALID_PARAM

References ASCIICHAT_OK, ERROR_INVALID_PARAM, and SET_ERRNO.

Referenced by client_audio_pipeline_capture(), handle_audio_batch_packet(), and handle_audio_packet().

◆ audio_resample_stereo()

size_t audio_resample_stereo ( audio_resampler_t * state,
const float * input,
size_t frames,
double input_rate,
float * output,
size_t capacity,
double output_rate )

Stateful interleaved resampling; capacities and return value are frames. Invalid arguments return zero and set ERROR_INVALID_PARAM. On insufficient capacity the state and output are left unchanged.

Definition at line 52 of file audio/format.c.

53 {
54 if (!state || !input || !output || !frames || !isfinite(input_rate) || !isfinite(output_rate) || input_rate < 8000 ||
55 input_rate > 192000 || output_rate < 8000 || output_rate > 192000) {
56 SET_ERRNO(ERROR_INVALID_PARAM, "Invalid stereo resampling buffers, frame count, or sample rates");
57 return 0;
58 }
59 const double step = input_rate / output_rate;
60 double position = state->phase;
61 if (!state->has_previous && position < 0)
62 position += ceil(-position / step) * step;
63 double limit = (double)frames - 1;
64 size_t needed = position < limit ? (size_t)ceil((limit - position) / step) : 0;
65 if (needed > capacity)
66 return 0;
67 size_t produced = 0;
68 while (position < limit) {
69 size_t first = position < 0 ? 0 : (size_t)position;
70 double fraction = position < 0 ? position + 1 : position - (double)first;
71 for (unsigned channel = 0; channel < 2; channel++) {
72 float a = position < 0 ? state->previous[channel] : input[first * 2 + channel];
73 float b = position < 0 ? input[channel] : input[(first + 1) * 2 + channel];
74 output[produced * 2 + channel] = (float)(a + fraction * (b - a));
75 }
76 produced++;
77 position += step;
78 }
79 state->phase = position - (double)frames;
80 state->previous[0] = input[(frames - 1) * 2];
81 state->previous[1] = input[(frames - 1) * 2 + 1];
82 state->has_previous = true;
83 return produced;
84}

References ERROR_INVALID_PARAM, and SET_ERRNO.

◆ audio_route_capture()

asciichat_error_t audio_route_capture ( const float * input,
size_t frames,
unsigned channels,
int first_channel,
unsigned selected_channels,
float * output )

Internal PCM is interleaved stereo. PCM sample counts include both channels. Route a zero-based mono input or adjacent stereo pair to internal PCM. A negative first_channel downmixes all input channels to centered mono. Input and output must not overlap. No allocation or locking is performed.

Definition at line 4 of file audio/format.c.

5 {
6 if (!input || !output || channels == 0 || channels > AUDIO_DEVICE_MAX_CHANNELS ||
7 (selected_channels != 1 && selected_channels != 2) || first_channel < -1 ||
8 (first_channel >= 0 &&
9 ((unsigned)first_channel >= channels || selected_channels > channels - (unsigned)first_channel)))
10 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid microphone channel routing");
11 for (size_t frame = 0; frame < frames; frame++) {
12 float left, right;
13 if (first_channel < 0) {
14 double sum = 0;
15 for (unsigned channel = 0; channel < channels; channel++)
16 sum += input[frame * channels + channel];
17 left = right = (float)(sum / channels);
18 } else {
19 left = input[frame * channels + (unsigned)first_channel];
20 right = selected_channels == 2 ? input[frame * channels + (unsigned)first_channel + 1] : left;
21 }
22 output[frame * 2] = left;
23 output[frame * 2 + 1] = right;
24 }
25 return ASCIICHAT_OK;
26}
#define AUDIO_DEVICE_MAX_CHANNELS
Definition audio/limits.h:7

References ASCIICHAT_OK, AUDIO_DEVICE_MAX_CHANNELS, ERROR_INVALID_PARAM, and SET_ERRNO.