← Back to C-Kernel-Engine Docs Doxygen Source Documentation
 
Loading...
Searching...
No Matches
audio_duration_logits.c
Go to the documentation of this file.
1#include "ckernel_tts.h"
2
3#include <limits.h>
4#include <math.h>
5#include <stdint.h>
6
7static float sigmoid_f32(float x) {
8 if (x >= 0.0f) return 1.0f / (1.0f + expf(-x));
9 const float e = expf(x);
10 return e / (1.0f + e);
11}
12
13static int token_frames(const float *logits, size_t bins, float speed,
14 size_t max_duration_per_token, int32_t *frames) {
15 float sum = 0.0f;
16 for (size_t bin = 0; bin < bins; ++bin) {
17 const float value = logits[bin];
18 if (!isfinite(value)) return CK_AUDIO_EXTENT_INVALID;
19 sum += sigmoid_f32(value);
20 }
21 const float scaled = sum / speed;
22 if (!isfinite(scaled) || scaled >= 2147483648.0f)
24
25 /* Nonnegative scaled values only. Implement nearest-even independently of
26 * the process floating-point rounding mode. */
27 const float lower = floorf(scaled);
28 const float fraction = scaled - lower;
29 float rounded = lower;
30 if (fraction > 0.5f ||
31 (fraction == 0.5f && fmodf(lower, 2.0f) != 0.0f))
32 rounded += 1.0f;
33 if (rounded < 1.0f) rounded = 1.0f;
34 /* rounded is below 2^31, so the integer conversion is exact and safe.
35 * Compare integers: converting a large limit to float can round it up. */
36 const int32_t candidate = (int32_t)rounded;
37 if ((size_t)candidate > max_duration_per_token)
39 *frames = candidate;
40 return CK_AUDIO_EXTENT_OK;
41}
42
44 const float *logits, size_t input_elements, size_t tokens, size_t bins,
45 size_t input_stride, float speed, int32_t *durations,
46 size_t duration_capacity, size_t max_duration_per_token,
47 size_t max_expanded_frames, int32_t *expanded_frames) {
48 if (!logits || !durations || !expanded_frames || !tokens || !bins ||
49 input_stride < bins || !isfinite(speed) || speed <= 0.0f ||
50 !max_duration_per_token || max_duration_per_token > INT32_MAX ||
51 !max_expanded_frames || max_expanded_frames > INT32_MAX)
53 if (tokens - 1 > (SIZE_MAX - bins) / input_stride ||
54 tokens > SIZE_MAX / sizeof(int32_t))
56 const size_t required_input = (tokens - 1) * input_stride + bins;
57 if (required_input > SIZE_MAX / sizeof(float))
59 if (input_elements < required_input || duration_capacity < tokens)
61
62 size_t total = 0;
63 for (size_t token = 0; token < tokens; ++token) {
64 int32_t frames = 0;
65 const int rc = token_frames(logits + token * input_stride, bins, speed,
66 max_duration_per_token, &frames);
67 if (rc != CK_AUDIO_EXTENT_OK) return rc;
68 if ((size_t)frames > max_expanded_frames - total)
70 total += (size_t)frames;
71 }
72
73 for (size_t token = 0; token < tokens; ++token) {
74 int32_t frames = 0;
75 /* The first pass validated all inputs and capacities. */
76 (void)token_frames(logits + token * input_stride, bins, speed,
77 max_duration_per_token, &frames);
78 durations[token] = frames;
79 }
80 *expanded_frames = (int32_t)total;
81 return CK_AUDIO_EXTENT_OK;
82}
int audio_duration_logits_to_frames_f32(const float *logits, size_t input_elements, size_t tokens, size_t bins, size_t input_stride, float speed, int32_t *durations, size_t duration_capacity, size_t max_duration_per_token, size_t max_expanded_frames, int32_t *expanded_frames)
static int token_frames(const float *logits, size_t bins, float speed, size_t max_duration_per_token, int32_t *frames)
static float sigmoid_f32(float x)
@ CK_AUDIO_EXTENT_INVALID
Definition ckernel_tts.h:42
@ CK_AUDIO_EXTENT_LIMIT
Definition ckernel_tts.h:43
@ CK_AUDIO_EXTENT_OVERFLOW
Definition ckernel_tts.h:44
@ CK_AUDIO_EXTENT_OK
Definition ckernel_tts.h:41
const char * token
Definition tokenizer.h:307