← Back to C-Kernel-Engine Docs Doxygen Source Documentation
 
Loading...
Searching...
No Matches
ckernel_audio.h File Reference
#include <stdint.h>
#include <stddef.h>

Go to the source code of this file.

Data Structures

struct  CKAudioWavInfo
 

Macros

#define CK_AUDIO_WHISPER_HOP_LENGTH   160
 
#define CK_AUDIO_WHISPER_N_FFT   400
 
#define CK_AUDIO_WHISPER_POWER_BINS   201
 
#define CK_AUDIO_WHISPER_SAMPLE_RATE   16000
 

Functions

int audio_adain_instance_norm_f32 (const float *input, size_t input_elements, size_t input_stride, const float *norm_weight, size_t norm_weight_elements, const float *norm_bias, size_t norm_bias_elements, const float *style_affine, size_t style_affine_elements, float *output, size_t output_elements, size_t output_stride, size_t channels, size_t frames, float epsilon)
 
int audio_adaptive_layer_norm_f32 (const float *input, size_t input_elements, const float *style, size_t style_elements, const float *projection_weight, size_t projection_weight_elements, const float *projection_bias, size_t projection_bias_elements, float *output, size_t output_elements, float *projection_scratch, size_t projection_scratch_bytes, int tokens, int channels, int style_dim, size_t input_stride, size_t output_stride, float epsilon)
 
int audio_argmax_first_f32 (const float *values, int elements, int *selected)
 
int audio_batch_norm_inference_channel_major_f32 (const float *input, const float *running_mean, const float *running_variance, const float *weight, const float *bias, float *output, int channels, int frames, float epsilon)
 
int audio_conformer_relative_attention_f32 (const float *query, const float *key, const float *value, const float *relative_key, const float *bias_u, const float *bias_v, float *output, int frames, int heads, int head_dim, float scale, float *scores_scratch, size_t scores_scratch_bytes)
 
int audio_conv1d_channel_major_f32 (const float *input, const float *weight, const float *bias, float *output, int input_channels, int output_channels, int input_frames, int kernel_size, int stride, int padding, int output_frames)
 
int audio_conv1d_channel_major_grouped_f32 (const float *input, const float *weight, const float *bias, float *output, int input_channels, int output_channels, int input_frames, int kernel_size, int stride, int padding, int groups, int output_frames)
 
int audio_conv2d_whc_grouped_f32 (const float *input, const float *weight, const float *bias, float *output, int input_width, int input_height, int input_channels, int output_channels, int kernel_width, int kernel_height, int stride_width, int stride_height, int padding_width, int padding_height, int groups, int output_width, int output_height)
 
int audio_fastconformer_block_f32 (const float *input, const float *relative_positions, const float *ff1_norm_weight, const float *ff1_norm_bias, const float *ff1_up_weight, const float *ff1_up_bias, const float *ff1_down_weight, const float *ff1_down_bias, const float *attn_norm_weight, const float *attn_norm_bias, const float *q_weight, const float *q_bias, const float *k_weight, const float *k_bias, const float *v_weight, const float *v_bias, const float *relative_weight, const float *attn_bias_u, const float *attn_bias_v, const float *attn_out_weight, const float *attn_out_bias, const float *conv_norm_weight, const float *conv_norm_bias, const float *conv_pw1_weight, const float *conv_pw1_bias, const float *conv_dw_weight, const float *conv_dw_bias, const float *conv_bn_mean, const float *conv_bn_variance, const float *conv_bn_weight, const float *conv_bn_bias, const float *conv_pw2_weight, const float *conv_pw2_bias, const float *ff2_norm_weight, const float *ff2_norm_bias, const float *ff2_up_weight, const float *ff2_up_bias, const float *ff2_down_weight, const float *ff2_down_bias, const float *out_norm_weight, const float *out_norm_bias, float *output, void *workspace, size_t workspace_bytes, int frames, int hidden_size, int intermediate_size, int heads, int head_dim, int conv_kernel_size, float layer_norm_epsilon, float batch_norm_epsilon)
 
size_t audio_fastconformer_block_workspace_bytes (int frames, int hidden_size, int intermediate_size, int heads)
 
int audio_fastconformer_subsampling_f32 (const float *features, const float *conv0_weight, const float *conv0_bias, const float *depthwise1_weight, const float *depthwise1_bias, const float *pointwise1_weight, const float *pointwise1_bias, const float *depthwise2_weight, const float *depthwise2_bias, const float *pointwise2_weight, const float *pointwise2_bias, const float *linear_weight, const float *linear_bias, float *output, void *workspace, size_t workspace_bytes, int feature_frames, int live_frames, int feature_channels, int conv_channels, int hidden_size, int kernel_size, int stride, int output_capacity_frames, int *output_frames)
 
size_t audio_fastconformer_subsampling_workspace_bytes (int feature_frames, int feature_channels, int conv_channels, int kernel_size, int stride)
 
int audio_feature_normalize_per_feature_f32 (const float *input, float *output, int channels, int frames, float epsilon)
 
int audio_glu_split_channel_major_f32 (const float *input, float *output, int channels, int frames)
 
int audio_hann_window_f32 (float *output, int frames, int periodic)
 
int audio_log_mel_time_major_f32 (const float *power, const float *mel_filters, float *log_mel, int frames, int bins, int channels, float epsilon)
 
int audio_lstm_bidirectional_scan_f32 (const float *input, size_t input_elements, const float *weight_ih, size_t weight_ih_elements, const float *weight_hh, size_t weight_hh_elements, const float *bias_ih, size_t bias_ih_elements, const float *bias_hh, size_t bias_hh_elements, float *output, size_t output_elements, float *hidden_state, size_t hidden_state_elements, float *cell_state, size_t cell_state_elements, float *gates_scratch, size_t gates_scratch_bytes, int tokens, int input_size, int hidden_size, size_t input_stride, size_t output_stride)
 
int audio_lstm_step_f32 (const float *input, const float *weight_ih, const float *weight_hh, const float *bias_ih, const float *bias_hh, float *hidden_state, float *cell_state, float *output, float *gates_scratch, size_t gates_scratch_bytes, int input_size, int hidden_size)
 
int audio_pad_or_truncate_f32 (const float *input, int input_frames, float *output, int output_frames)
 
int audio_pcm_s16_to_mono_f32 (const int16_t *interleaved, int n_frames, int n_channels, float *mono)
 
int audio_preemphasis_f32 (const float *input, float *output, int frames, float coefficient)
 
int audio_relative_shift_f32 (const float *raw_scores, float *scores, int heads, int query_frames)
 
int audio_relative_sinusoidal_position_f32 (float *output, int frames, int channels)
 
int audio_resample_linear_f32 (const float *input, int input_frames, int input_rate, float *output, int output_frames, int output_rate)
 
int audio_resample_windowed_sinc_f32 (const float *input, int input_frames, int input_rate, float *output, int output_frames, int output_rate, int radius)
 
int audio_resampled_frame_count (int input_frames, int input_rate, int output_rate)
 
int audio_scaled_residual_add_f32 (const float *residual, const float *branch, float scale, float *output, size_t elements)
 
int audio_stft_power_centered_window_f32 (const float *samples, int n_samples, const float *window, int window_length, const float *cos_table, const float *sin_table, int n_fft, int hop_length, int reflect_padding, float *power, int n_frames)
 
int audio_stft_power_fft400_f32 (const float *samples, int n_samples, const float *window, const float *cos_table, const float *sin_table, int hop_length, float *power, int n_frames, float *fft_scratch)
 
int audio_stft_power_precomputed_f32 (const float *samples, int n_samples, const float *window, const float *cos_table, const float *sin_table, int n_fft, int hop_length, float *power, int n_frames)
 
int audio_stft_precompute_tables_f32 (int n_fft, float *window, float *cos_table, float *sin_table)
 
int audio_transpose_channel_to_token_f32 (const float *input, float *output, int channels, int frames)
 
int audio_wav_decode_memory_pcm16_mono_f32 (const uint8_t *bytes, size_t byte_count, float *mono, int mono_capacity, CKAudioWavInfo *info)
 
int audio_wav_decode_memory_pcm16_mono_window_f32 (const uint8_t *bytes, size_t byte_count, int start_frame, float *mono, int mono_capacity, CKAudioWavInfo *info)
 
int audio_wav_decode_pcm16_mono_f32 (const uint8_t *bytes, size_t byte_count, const CKAudioWavInfo *info, float *mono, int mono_capacity)
 
int audio_wav_parse_memory (const uint8_t *bytes, size_t byte_count, CKAudioWavInfo *info)
 
int audio_whisper_log_mel_from_power_reference_f32 (const float *power, const float *mel_filters, int n_mels, int n_frames, float *log_mel)
 
int audio_whisper_log_mel_reference_f32 (const float *samples, int n_samples, const float *mel_filters, int n_mels, float *power_scratch, float *log_mel, int n_frames)
 
int audio_whisper_log_mel_window_wav_pcm16_f32 (const uint8_t *bytes, size_t byte_count, int start_frame, int target_sample_rate, const float *window, const float *cos_table, const float *sin_table, const float *mel_filters, int n_mels, int output_frames, float *log_mel)
 
int audio_whisper_mel_filters_slaney_f32 (int sample_rate, int n_fft, int n_mels, float *mel_filters)
 
int audio_whisper_stft_power_reference_f32 (const float *samples, int n_samples, float *power, int n_frames)
 

Macro Definition Documentation

◆ CK_AUDIO_WHISPER_HOP_LENGTH

#define CK_AUDIO_WHISPER_HOP_LENGTH   160

Definition at line 13 of file ckernel_audio.h.

◆ CK_AUDIO_WHISPER_N_FFT

#define CK_AUDIO_WHISPER_N_FFT   400

Definition at line 12 of file ckernel_audio.h.

◆ CK_AUDIO_WHISPER_POWER_BINS

#define CK_AUDIO_WHISPER_POWER_BINS   201

Definition at line 14 of file ckernel_audio.h.

◆ CK_AUDIO_WHISPER_SAMPLE_RATE

#define CK_AUDIO_WHISPER_SAMPLE_RATE   16000

Definition at line 11 of file ckernel_audio.h.

Function Documentation

◆ audio_adain_instance_norm_f32()

int audio_adain_instance_norm_f32 ( const float *  input,
size_t  input_elements,
size_t  input_stride,
const float *  norm_weight,
size_t  norm_weight_elements,
const float *  norm_bias,
size_t  norm_bias_elements,
const float *  style_affine,
size_t  style_affine_elements,
float *  output,
size_t  output_elements,
size_t  output_stride,
size_t  channels,
size_t  frames,
float  epsilon 
)

Definition at line 38 of file audio_adain_instance_norm.c.

45{
46 if (input == NULL || norm_weight == NULL || norm_bias == NULL ||
47 style_affine == NULL || output == NULL ||
48 !isfinite(epsilon) || epsilon <= 0.0f ||
49 channels == 0u || channels > SIZE_MAX / 2u) return -1;
50 size_t input_required, output_required;
51 if (!checked_span(channels, input_stride, frames, &input_required) ||
52 !checked_span(channels, output_stride, frames, &output_required))
53 return -1;
54 if (input_elements < input_required || output_elements < output_required ||
55 norm_weight_elements < channels || norm_bias_elements < channels ||
56 style_affine_elements < 2u * channels) return -2;
57
58 for (size_t channel = 0u; channel < channels; ++channel) {
59 if (!isfinite(norm_weight[channel]) || !isfinite(norm_bias[channel]) ||
60 !isfinite(style_affine[channel]) ||
61 !isfinite(style_affine[channels + channel])) return -3;
62 const float *row = input + channel * input_stride;
63 for (size_t frame = 0u; frame < frames; ++frame)
64 if (!isfinite(row[frame])) return -3;
65 }
66
67 /* Dry-run every result before the first output write. The repeated scalar
68 * pass trades throughput for a small, allocation-free reference kernel. */
69 for (int pass = 0; pass < 2; ++pass) {
70 for (size_t channel = 0u; channel < channels; ++channel) {
71 const float *row = input + channel * input_stride;
72 float *output_row = output + channel * output_stride;
73 double mean, inverse_std;
74 if (!channel_stats(row, frames, epsilon, &mean, &inverse_std))
75 return -3;
76 const float weight = norm_weight[channel];
77 const float bias = norm_bias[channel];
78 const float gamma = style_affine[channel];
79 const float beta = style_affine[channels + channel];
80 for (size_t frame = 0u; frame < frames; ++frame) {
81 const float normalized = (float)(
82 ((double)row[frame] - mean) * inverse_std);
83 const float affine = normalized * weight + bias;
84 const float value = (1.0f + gamma) * affine + beta;
85 if (!isfinite(value)) return -3;
86 if (pass != 0) output_row[frame] = value;
87 }
88 }
89 }
90 return 0;
91}
static int checked_span(size_t channels, size_t stride, size_t frames, size_t *result)
static int channel_stats(const float *row, size_t frames, float epsilon, double *mean, double *inverse_std)

References channel_stats(), and checked_span().

◆ audio_adaptive_layer_norm_f32()

int audio_adaptive_layer_norm_f32 ( const float *  input,
size_t  input_elements,
const float *  style,
size_t  style_elements,
const float *  projection_weight,
size_t  projection_weight_elements,
const float *  projection_bias,
size_t  projection_bias_elements,
float *  output,
size_t  output_elements,
float *  projection_scratch,
size_t  projection_scratch_bytes,
int  tokens,
int  channels,
int  style_dim,
size_t  input_stride,
size_t  output_stride,
float  epsilon 
)

Definition at line 57 of file audio_adaptive_layer_norm.c.

66{
67 if (input == NULL || style == NULL || projection_weight == NULL ||
68 projection_bias == NULL || output == NULL ||
69 projection_scratch == NULL) return -1;
70 if (tokens <= 0 || channels <= 0 || style_dim <= 0 ||
71 !isfinite(epsilon) || epsilon <= 0.0f) return -2;
72
73 const size_t rows = (size_t)tokens;
74 const size_t width = (size_t)channels;
75 const size_t style_width = (size_t)style_dim;
76 size_t input_required, output_required, projection_width;
77 size_t weight_required, scratch_required;
78 if (input_stride < width || output_stride < width ||
79 !checked_span(rows, input_stride, width, &input_required) ||
80 !checked_span(rows, output_stride, width, &output_required) ||
81 !checked_product(width, 2u, &projection_width) ||
82 !checked_product(projection_width, style_width, &weight_required) ||
83 !checked_product(projection_width, sizeof(float), &scratch_required) ||
84 !checked_float_extent(input_required) ||
85 !checked_float_extent(output_required) ||
86 !checked_float_extent(style_width) ||
87 !checked_float_extent(weight_required) ||
88 !checked_float_extent(projection_width))
89 return -2;
90 if (input_elements < input_required || output_elements < output_required ||
91 style_elements < style_width ||
92 projection_weight_elements < weight_required ||
93 projection_bias_elements < projection_width ||
94 projection_scratch_bytes < scratch_required) return -3;
95
96 /* Validate all external values before changing output or scratch. Padding
97 * is deliberately not read; only the declared logical columns are valid.
98 */
99 for (size_t index = 0u; index < style_width; ++index)
100 if (!isfinite(style[index])) return -4;
101 for (size_t index = 0u; index < weight_required; ++index)
102 if (!isfinite(projection_weight[index])) return -4;
103 for (size_t index = 0u; index < projection_width; ++index)
104 if (!isfinite(projection_bias[index])) return -4;
105 for (size_t row = 0u; row < rows; ++row)
106 for (size_t channel = 0u; channel < width; ++channel)
107 if (!isfinite(input[row * input_stride + channel])) return -4;
108
109 for (size_t channel = 0u; channel < projection_width; ++channel) {
110 float value = projection_bias[channel];
111 const float *weight = projection_weight + channel * style_width;
112 for (size_t index = 0u; index < style_width; ++index)
113 value += weight[index] * style[index];
114 if (!isfinite(value)) return -4;
115 projection_scratch[channel] = value;
116 }
117
118 /* Validate every produced value before the first output write. The second
119 * pass repeats cheap normalization arithmetic without a hidden T*C buffer.
120 */
121 for (int pass = 0; pass < 2; ++pass) {
122 for (size_t row = 0u; row < rows; ++row) {
123 const float *input_row = input + row * input_stride;
124 float *output_row = output + row * output_stride;
125 double mean, inverse_std;
126 if (!row_stats(input_row, width, epsilon, &mean, &inverse_std))
127 return -4;
128 for (size_t channel = 0u; channel < width; ++channel) {
129 const float normalized = (float)(
130 ((double)input_row[channel] - mean) * inverse_std);
131 const float gamma = projection_scratch[channel];
132 const float beta = projection_scratch[width + channel];
133 const float value = (1.0f + gamma) * normalized + beta;
134 if (!isfinite(value)) return -4;
135 if (pass != 0) output_row[channel] = value;
136 }
137 }
138 }
139 return 0;
140}
static int checked_product(size_t left, size_t right, size_t *result)
static int row_stats(const float *row, size_t channels, float epsilon, double *mean, double *inverse_std)
static int checked_span(size_t rows, size_t stride, size_t width, size_t *result)
static int checked_float_extent(size_t elements)
CKSpacePrefixStyle style
Definition tokenizer.h:288

References checked_float_extent(), checked_product(), checked_span(), row_stats(), and style.

◆ audio_argmax_first_f32()

int audio_argmax_first_f32 ( const float *  values,
int  elements,
int *  selected 
)

Definition at line 2147 of file audio_kernels.c.

2148{
2149 if (values == NULL || selected == NULL) {
2150 return -1;
2151 }
2152 if (elements <= 0) {
2153 return -2;
2154 }
2155 if (!isfinite(values[0])) {
2156 return -3;
2157 }
2158 int best = 0;
2159 float maximum = values[0];
2160 for (int index = 1; index < elements; ++index) {
2161 if (!isfinite(values[index])) {
2162 return -3;
2163 }
2164 if (values[index] > maximum) {
2165 maximum = values[index];
2166 best = index;
2167 }
2168 }
2169 *selected = best;
2170 return 0;
2171}

◆ audio_batch_norm_inference_channel_major_f32()

int audio_batch_norm_inference_channel_major_f32 ( const float *  input,
const float *  running_mean,
const float *  running_variance,
const float *  weight,
const float *  bias,
float *  output,
int  channels,
int  frames,
float  epsilon 
)

Definition at line 469 of file audio_kernels.c.

479{
480 if (input == NULL || running_mean == NULL || running_variance == NULL ||
481 weight == NULL || bias == NULL || output == NULL) {
482 return -1;
483 }
484 if (channels <= 0 || frames <= 0 || !isfinite(epsilon) || epsilon < 0.0f) {
485 return -2;
486 }
487 for (int channel = 0; channel < channels; ++channel) {
488 const float variance = running_variance[channel];
489 if (!isfinite(variance) || variance + epsilon <= 0.0f) {
490 return -3;
491 }
492 }
493 for (int channel = 0; channel < channels; ++channel) {
494 const float variance = running_variance[channel];
495 const float scale = weight[channel] / sqrtf(variance + epsilon);
496 const float offset = bias[channel] - running_mean[channel] * scale;
497 for (int frame = 0; frame < frames; ++frame) {
498 const size_t index = (size_t)channel * frames + frame;
499 output[index] = input[index] * scale + offset;
500 }
501 }
502 return 0;
503}

Referenced by audio_fastconformer_block_f32().

◆ audio_conformer_relative_attention_f32()

int audio_conformer_relative_attention_f32 ( const float *  query,
const float *  key,
const float *  value,
const float *  relative_key,
const float *  bias_u,
const float *  bias_v,
float *  output,
int  frames,
int  heads,
int  head_dim,
float  scale,
float *  scores_scratch,
size_t  scores_scratch_bytes 
)

Definition at line 1766 of file audio_kernels.c.

1780{
1781 if (query == NULL || key == NULL || value == NULL || relative_key == NULL ||
1782 bias_u == NULL || bias_v == NULL || output == NULL ||
1783 scores_scratch == NULL) {
1784 return -1;
1785 }
1786 if (frames <= 0 || frames > (INT_MAX / 2) + 1 || heads <= 0 ||
1787 head_dim <= 0 || heads > INT_MAX / head_dim ||
1788 heads > INT_MAX / frames || !isfinite(scale) || scale <= 0.0f) {
1789 return -2;
1790 }
1791 if ((size_t)frames > SIZE_MAX / (size_t)heads ||
1792 (size_t)frames * (size_t)heads > SIZE_MAX / sizeof(float) ||
1793 scores_scratch_bytes <
1794 (size_t)frames * (size_t)heads * sizeof(float)) {
1795 return -3;
1796 }
1797 const int channels = heads * head_dim;
1798 ck_threadpool_t *pool = ck_threadpool_global();
1799 ck_audio_conformer_relative_attention_f32_args_t args = {
1800 .query = query,
1801 .key = key,
1802 .value = value,
1803 .relative_key = relative_key,
1804 .bias_u = bias_u,
1805 .bias_v = bias_v,
1806 .output = output,
1807 .scores_scratch = scores_scratch,
1808 .pool = pool,
1809 .frames = frames,
1810 .heads = heads,
1811 .head_dim = head_dim,
1812 .channels = channels,
1813 .scale = scale,
1814 };
1815 int active = pool ? ck_threadpool_n_threads(pool) : 1;
1816 const size_t scratch_slots = scores_scratch_bytes /
1817 ((size_t)frames * sizeof(float));
1818 const int rows = heads * frames;
1819 if ((size_t)active > scratch_slots) active = (int)scratch_slots;
1820 if (active > rows) active = rows;
1821 if (pool != NULL && active > 1) {
1823 pool, active, 0, rows, 1,
1825 } else {
1827 }
1828 return 0;
1829}
static void ck_audio_conformer_relative_attention_f32_row_range(int begin, int end, void *opaque)
void ck_threadpool_parallel_for_n(ck_threadpool_t *pool, int active_threads, int begin, int end, int grain_size, ck_range_fn_t fn, void *args)
ck_threadpool_t * ck_threadpool_global(void)
int ck_threadpool_n_threads(const ck_threadpool_t *pool)

References ck_audio_conformer_relative_attention_f32_row_range(), ck_threadpool_global(), ck_threadpool_n_threads(), and ck_threadpool_parallel_for_n().

Referenced by audio_fastconformer_block_f32().

◆ audio_conv1d_channel_major_f32()

int audio_conv1d_channel_major_f32 ( const float *  input,
const float *  weight,
const float *  bias,
float *  output,
int  input_channels,
int  output_channels,
int  input_frames,
int  kernel_size,
int  stride,
int  padding,
int  output_frames 
)

Definition at line 1309 of file audio_kernels.c.

1321{
1323 input, weight, bias, output, input_channels, output_channels,
1324 input_frames, kernel_size, stride, padding, 1, output_frames);
1325}
int audio_conv1d_channel_major_grouped_f32(const float *input, const float *weight, const float *bias, float *output, int input_channels, int output_channels, int input_frames, int kernel_size, int stride, int padding, int groups, int output_frames)

References audio_conv1d_channel_major_grouped_f32().

◆ audio_conv1d_channel_major_grouped_f32()

int audio_conv1d_channel_major_grouped_f32 ( const float *  input,
const float *  weight,
const float *  bias,
float *  output,
int  input_channels,
int  output_channels,
int  input_frames,
int  kernel_size,
int  stride,
int  padding,
int  groups,
int  output_frames 
)

Definition at line 1327 of file audio_kernels.c.

1340{
1341 if (input == NULL || weight == NULL || output == NULL) {
1342 return -1;
1343 }
1344 if (input_channels <= 0 || output_channels <= 0 || input_frames <= 0 ||
1345 kernel_size <= 0 || stride <= 0 || padding < 0 || groups <= 0 ||
1346 output_frames <= 0 || input_channels % groups != 0 ||
1347 output_channels % groups != 0) {
1348 return -2;
1349 }
1350 const int64_t padded_frames =
1351 (int64_t)input_frames + 2 * (int64_t)padding - kernel_size;
1352 if (padded_frames < 0 || padded_frames / stride + 1 > INT_MAX ||
1353 output_frames != (int)(padded_frames / stride + 1)) {
1354 return -3;
1355 }
1356 const char *disable_stride2 =
1357 getenv("CK_DISABLE_AUDIO_CONV_STRIDE2_CONTIGUOUS");
1358 ck_audio_conv1d_f32_args_t args = {
1359 .input = input,
1360 .weight = weight,
1361 .bias = bias,
1362 .output = output,
1363 .input_channels = input_channels,
1364 .output_channels = output_channels,
1365 .input_frames = input_frames,
1366 .kernel_size = kernel_size,
1367 .stride = stride,
1368 .padding = padding,
1369 .output_frames = output_frames,
1370 .groups = groups,
1371 .input_channels_per_group = input_channels / groups,
1372 .output_channels_per_group = output_channels / groups,
1373 .use_stride2_contiguous = !(
1374 disable_stride2 && disable_stride2[0] &&
1375 strcmp(disable_stride2, "0") != 0),
1376 };
1377 ck_threadpool_t *pool = ck_threadpool_global();
1378 int active = pool ? ck_threadpool_n_threads(pool) : 1;
1379 if (active > output_channels) active = output_channels;
1380 if (pool != NULL && active > 1) {
1382 pool, active, ck_audio_conv1d_channel_major_f32_work, &args);
1383 } else {
1385 }
1386 return 0;
1387}
static void ck_audio_conv1d_channel_major_f32_work(int ith, int nth, void *opaque)
void ck_threadpool_dispatch_n(ck_threadpool_t *pool, int active_threads, ck_work_fn_t fn, void *args)

References ck_audio_conv1d_channel_major_f32_work(), ck_threadpool_dispatch_n(), ck_threadpool_global(), and ck_threadpool_n_threads().

Referenced by audio_conv1d_channel_major_f32(), and audio_fastconformer_block_f32().

◆ audio_conv2d_whc_grouped_f32()

int audio_conv2d_whc_grouped_f32 ( const float *  input,
const float *  weight,
const float *  bias,
float *  output,
int  input_width,
int  input_height,
int  input_channels,
int  output_channels,
int  kernel_width,
int  kernel_height,
int  stride_width,
int  stride_height,
int  padding_width,
int  padding_height,
int  groups,
int  output_width,
int  output_height 
)

Definition at line 1500 of file audio_kernels.c.

1518{
1519 if (input == NULL || weight == NULL || output == NULL) {
1520 return -1;
1521 }
1522 if (input_width <= 0 || input_height <= 0 || input_channels <= 0 ||
1523 output_channels <= 0 || kernel_width <= 0 || kernel_height <= 0 ||
1524 stride_width <= 0 || stride_height <= 0 || padding_width < 0 ||
1525 padding_height < 0 || groups <= 0 || output_width <= 0 ||
1526 output_height <= 0 || input_channels % groups != 0 ||
1527 output_channels % groups != 0) {
1528 return -2;
1529 }
1530 const int expected_width =
1531 (input_width + 2 * padding_width - kernel_width) / stride_width + 1;
1532 const int expected_height =
1533 (input_height + 2 * padding_height - kernel_height) / stride_height + 1;
1534 if (output_width != expected_width || output_height != expected_height) {
1535 return -3;
1536 }
1537 ck_audio_conv2d_whc_f32_args_t args = {
1538 .input = input,
1539 .weight = weight,
1540 .bias = bias,
1541 .output = output,
1542 .input_width = input_width,
1543 .input_height = input_height,
1544 .input_channels = input_channels,
1545 .output_channels = output_channels,
1546 .kernel_width = kernel_width,
1547 .kernel_height = kernel_height,
1548 .stride_width = stride_width,
1549 .stride_height = stride_height,
1550 .padding_width = padding_width,
1551 .padding_height = padding_height,
1552 .groups = groups,
1553 .output_width = output_width,
1554 .output_height = output_height,
1555 .use_width_simd = 1,
1556 };
1557 const char *disable_width_simd = getenv("CK_AUDIO_DISABLE_CONV2D_WIDTH_SIMD");
1558 if (disable_width_simd != NULL && disable_width_simd[0] != '\0' &&
1559 strcmp(disable_width_simd, "0") != 0) {
1560 args.use_width_simd = 0;
1561 }
1562 const int output_elements = output_channels * output_height * output_width;
1563 ck_threadpool_t *pool = ck_threadpool_global();
1564 int active = pool ? ck_threadpool_n_threads(pool) : 1;
1565 if (active > output_elements) {
1566 active = output_elements;
1567 }
1568 if (pool != NULL && active > 1) {
1569 const int grain = output_width > 0 ? output_width : 1;
1571 pool, active, 0, output_elements, grain,
1573 } else {
1574 ck_audio_conv2d_whc_grouped_f32_range(0, output_elements, &args);
1575 }
1576 return 0;
1577}
static void ck_audio_conv2d_whc_grouped_f32_range(int begin, int end, void *opaque)

References ck_audio_conv2d_whc_grouped_f32_range(), ck_threadpool_global(), ck_threadpool_n_threads(), and ck_threadpool_parallel_for_n().

Referenced by audio_fastconformer_subsampling_f32().

◆ audio_fastconformer_block_f32()

int audio_fastconformer_block_f32 ( const float *  input,
const float *  relative_positions,
const float *  ff1_norm_weight,
const float *  ff1_norm_bias,
const float *  ff1_up_weight,
const float *  ff1_up_bias,
const float *  ff1_down_weight,
const float *  ff1_down_bias,
const float *  attn_norm_weight,
const float *  attn_norm_bias,
const float *  q_weight,
const float *  q_bias,
const float *  k_weight,
const float *  k_bias,
const float *  v_weight,
const float *  v_bias,
const float *  relative_weight,
const float *  attn_bias_u,
const float *  attn_bias_v,
const float *  attn_out_weight,
const float *  attn_out_bias,
const float *  conv_norm_weight,
const float *  conv_norm_bias,
const float *  conv_pw1_weight,
const float *  conv_pw1_bias,
const float *  conv_dw_weight,
const float *  conv_dw_bias,
const float *  conv_bn_mean,
const float *  conv_bn_variance,
const float *  conv_bn_weight,
const float *  conv_bn_bias,
const float *  conv_pw2_weight,
const float *  conv_pw2_bias,
const float *  ff2_norm_weight,
const float *  ff2_norm_bias,
const float *  ff2_up_weight,
const float *  ff2_up_bias,
const float *  ff2_down_weight,
const float *  ff2_down_bias,
const float *  out_norm_weight,
const float *  out_norm_bias,
float *  output,
void *  workspace,
size_t  workspace_bytes,
int  frames,
int  hidden_size,
int  intermediate_size,
int  heads,
int  head_dim,
int  conv_kernel_size,
float  layer_norm_epsilon,
float  batch_norm_epsilon 
)

Definition at line 1928 of file audio_kernels.c.

1981{
1982 if (input == NULL || relative_positions == NULL ||
1983 ff1_norm_weight == NULL || ff1_norm_bias == NULL ||
1984 ff1_up_weight == NULL || ff1_down_weight == NULL ||
1985 attn_norm_weight == NULL || attn_norm_bias == NULL ||
1986 q_weight == NULL || k_weight == NULL || v_weight == NULL ||
1987 relative_weight == NULL || attn_bias_u == NULL || attn_bias_v == NULL ||
1988 attn_out_weight == NULL || conv_norm_weight == NULL ||
1989 conv_norm_bias == NULL || conv_pw1_weight == NULL ||
1990 conv_dw_weight == NULL || conv_bn_mean == NULL ||
1991 conv_bn_variance == NULL || conv_bn_weight == NULL ||
1992 conv_bn_bias == NULL || conv_pw2_weight == NULL ||
1993 ff2_norm_weight == NULL || ff2_norm_bias == NULL ||
1994 ff2_up_weight == NULL || ff2_down_weight == NULL ||
1995 out_norm_weight == NULL || out_norm_bias == NULL || output == NULL ||
1996 workspace == NULL) {
1997 return -1;
1998 }
1999 if (frames <= 0 || hidden_size <= 0 || intermediate_size <= 0 ||
2000 heads <= 0 || head_dim <= 0 || heads > INT_MAX / head_dim ||
2001 heads * head_dim != hidden_size || conv_kernel_size <= 0 ||
2002 (conv_kernel_size & 1) == 0 || !isfinite(layer_norm_epsilon) ||
2003 layer_norm_epsilon <= 0.0f || !isfinite(batch_norm_epsilon) ||
2004 batch_norm_epsilon <= 0.0f) {
2005 return -2;
2006 }
2007 const size_t minimum_workspace =
2009 frames, hidden_size, intermediate_size, heads, (size_t)heads);
2010 if (minimum_workspace == 0 || workspace_bytes < minimum_workspace) {
2011 return -3;
2012 }
2013
2014 const size_t token_elements = (size_t)frames * (size_t)hidden_size;
2015 const size_t ff_elements = (size_t)frames * (size_t)intermediate_size;
2016 const size_t relative_elements =
2017 (size_t)(2 * frames - 1) * (size_t)hidden_size;
2018 const size_t doubled_token_elements = 2u * token_elements;
2019 size_t large_elements = ff_elements;
2020 if (relative_elements > large_elements) large_elements = relative_elements;
2021 if (doubled_token_elements > large_elements) {
2022 large_elements = doubled_token_elements;
2023 }
2024
2025 float *cursor = (float *)workspace;
2026 float *norm = cursor;
2027 cursor += token_elements;
2028 float *large = cursor;
2029 cursor += large_elements;
2030 float *buffer2 = cursor;
2031 cursor += token_elements;
2032 float *buffer3 = cursor;
2033 cursor += token_elements;
2034 float *buffer4 = cursor;
2035 cursor += token_elements;
2036 float *buffer5 = cursor;
2037 cursor += token_elements;
2038 float *scores = cursor;
2039 const size_t scores_offset = (size_t)(
2040 (unsigned char *)scores - (unsigned char *)workspace);
2041
2042 memcpy(output, input, token_elements * sizeof(float));
2043
2045 output, ff1_norm_weight, ff1_norm_bias, norm, NULL, NULL,
2046 frames, hidden_size, layer_norm_epsilon);
2048 norm, ff1_up_weight, ff1_up_bias, large,
2049 frames, intermediate_size, hidden_size);
2050 recurrent_silu_forward(large, large, frames, intermediate_size);
2052 large, ff1_down_weight, ff1_down_bias, buffer2,
2053 frames, hidden_size, intermediate_size);
2055 output, buffer2, 0.5f, output, token_elements) != 0) {
2056 return -10;
2057 }
2058
2060 output, attn_norm_weight, attn_norm_bias, norm, NULL, NULL,
2061 frames, hidden_size, layer_norm_epsilon);
2063 norm, q_weight, q_bias, buffer2, frames, hidden_size, hidden_size);
2065 norm, k_weight, k_bias, buffer3, frames, hidden_size, hidden_size);
2067 norm, v_weight, v_bias, buffer4, frames, hidden_size, hidden_size);
2069 relative_positions, relative_weight, NULL, large,
2070 2 * frames - 1, hidden_size, hidden_size);
2072 buffer2, buffer3, buffer4, large, attn_bias_u, attn_bias_v,
2073 buffer5, frames, heads, head_dim, 1.0f / sqrtf((float)head_dim),
2074 scores, workspace_bytes - scores_offset) != 0) {
2075 return -11;
2076 }
2078 buffer5, attn_out_weight, attn_out_bias, norm,
2079 frames, hidden_size, hidden_size);
2081 output, norm, 1.0f, output, token_elements) != 0) {
2082 return -12;
2083 }
2084
2086 output, conv_norm_weight, conv_norm_bias, norm, NULL, NULL,
2087 frames, hidden_size, layer_norm_epsilon);
2088 for (int frame = 0; frame < frames; ++frame) {
2089 for (int channel = 0; channel < hidden_size; ++channel) {
2090 buffer2[(size_t)channel * (size_t)frames + (size_t)frame] =
2091 norm[(size_t)frame * (size_t)hidden_size + (size_t)channel];
2092 }
2093 }
2095 buffer2, conv_pw1_weight, conv_pw1_bias, large,
2096 hidden_size, 2 * hidden_size, frames, 1, 1, 0, 1, frames) != 0 ||
2098 large, buffer3, hidden_size, frames) != 0 ||
2100 buffer3, conv_dw_weight, conv_dw_bias, buffer4,
2101 hidden_size, hidden_size, frames, conv_kernel_size, 1,
2102 conv_kernel_size / 2, hidden_size, frames) != 0 ||
2104 buffer4, conv_bn_mean, conv_bn_variance, conv_bn_weight,
2105 conv_bn_bias, buffer5, hidden_size, frames,
2106 batch_norm_epsilon) != 0) {
2107 return -13;
2108 }
2109 recurrent_silu_forward(buffer5, buffer5, hidden_size, frames);
2111 buffer5, conv_pw2_weight, conv_pw2_bias, buffer3,
2112 hidden_size, hidden_size, frames, 1, 1, 0, 1, frames) != 0) {
2113 return -14;
2114 }
2115 for (int frame = 0; frame < frames; ++frame) {
2116 for (int channel = 0; channel < hidden_size; ++channel) {
2117 norm[(size_t)frame * (size_t)hidden_size + (size_t)channel] =
2118 buffer3[(size_t)channel * (size_t)frames + (size_t)frame];
2119 }
2120 }
2122 output, norm, 1.0f, output, token_elements) != 0) {
2123 return -15;
2124 }
2125
2127 output, ff2_norm_weight, ff2_norm_bias, norm, NULL, NULL,
2128 frames, hidden_size, layer_norm_epsilon);
2130 norm, ff2_up_weight, ff2_up_bias, large,
2131 frames, intermediate_size, hidden_size);
2132 recurrent_silu_forward(large, large, frames, intermediate_size);
2134 large, ff2_down_weight, ff2_down_bias, buffer2,
2135 frames, hidden_size, intermediate_size);
2137 output, buffer2, 0.5f, output, token_elements) != 0) {
2138 return -16;
2139 }
2141 output, out_norm_weight, out_norm_bias, norm, NULL, NULL,
2142 frames, hidden_size, layer_norm_epsilon);
2143 memcpy(output, norm, token_elements * sizeof(float));
2144 return 0;
2145}
void recurrent_silu_forward(const float *input, float *output, int rows, int dim)
void layernorm_naive_serial_matched_precision(const float *input, const float *gamma, const float *beta, float *output, float *mean_cache, float *rstd_cache, int tokens, int d_model, float eps)
int audio_batch_norm_inference_channel_major_f32(const float *input, const float *running_mean, const float *running_variance, const float *weight, const float *bias, float *output, int channels, int frames, float epsilon)
static size_t audio_fastconformer_block_workspace_bytes_for_score_slots(int frames, int hidden_size, int intermediate_size, int heads, size_t score_slots)
int audio_scaled_residual_add_f32(const float *residual, const float *branch, float scale, float *output, size_t elements)
int audio_glu_split_channel_major_f32(const float *input, float *output, int channels, int frames)
int audio_conformer_relative_attention_f32(const float *query, const float *key, const float *value, const float *relative_key, const float *bias_u, const float *bias_v, float *output, int frames, int heads, int head_dim, float scale, float *scores_scratch, size_t scores_scratch_bytes)
void gemm_nt_f32_llama_production_parallel_dispatch(const float *A, const float *B, const float *bias, float *C, int M, int N, int K)

References audio_batch_norm_inference_channel_major_f32(), audio_conformer_relative_attention_f32(), audio_conv1d_channel_major_grouped_f32(), audio_fastconformer_block_workspace_bytes_for_score_slots(), audio_glu_split_channel_major_f32(), audio_scaled_residual_add_f32(), gemm_nt_f32_llama_production_parallel_dispatch(), layernorm_naive_serial_matched_precision(), and recurrent_silu_forward().

◆ audio_fastconformer_block_workspace_bytes()

size_t audio_fastconformer_block_workspace_bytes ( int  frames,
int  hidden_size,
int  intermediate_size,
int  heads 
)

Definition at line 1914 of file audio_kernels.c.

1919{
1920 ck_threadpool_t *pool = ck_threadpool_global();
1921 const int requested_threads = pool ? ck_threadpool_n_threads(pool) : 1;
1922 const size_t score_slots = (size_t)(requested_threads > heads
1923 ? requested_threads : heads);
1925 frames, hidden_size, intermediate_size, heads, score_slots);
1926}

References audio_fastconformer_block_workspace_bytes_for_score_slots(), ck_threadpool_global(), and ck_threadpool_n_threads().

◆ audio_fastconformer_subsampling_f32()

int audio_fastconformer_subsampling_f32 ( const float *  features,
const float *  conv0_weight,
const float *  conv0_bias,
const float *  depthwise1_weight,
const float *  depthwise1_bias,
const float *  pointwise1_weight,
const float *  pointwise1_bias,
const float *  depthwise2_weight,
const float *  depthwise2_bias,
const float *  pointwise2_weight,
const float *  pointwise2_bias,
const float *  linear_weight,
const float *  linear_bias,
float *  output,
void *  workspace,
size_t  workspace_bytes,
int  feature_frames,
int  live_frames,
int  feature_channels,
int  conv_channels,
int  hidden_size,
int  kernel_size,
int  stride,
int  output_capacity_frames,
int *  output_frames 
)

Definition at line 1024 of file audio_kernels.c.

1050{
1051 if (features == NULL || conv0_weight == NULL || conv0_bias == NULL ||
1052 depthwise1_weight == NULL || depthwise1_bias == NULL ||
1053 pointwise1_weight == NULL || pointwise1_bias == NULL ||
1054 depthwise2_weight == NULL || depthwise2_bias == NULL ||
1055 pointwise2_weight == NULL || pointwise2_bias == NULL ||
1056 linear_weight == NULL || linear_bias == NULL || output == NULL ||
1057 workspace == NULL || output_frames == NULL || feature_frames <= 0 ||
1058 live_frames <= 0 || live_frames > feature_frames || feature_channels <= 0 ||
1059 conv_channels <= 0 || hidden_size <= 0 || kernel_size != 3 || stride != 2 ||
1060 output_capacity_frames <= 0) {
1061 return -1;
1062 }
1063
1064 const size_t required_workspace = audio_fastconformer_subsampling_workspace_bytes(
1065 feature_frames, feature_channels, conv_channels, kernel_size, stride);
1066 if (required_workspace == 0 || workspace_bytes < required_workspace) {
1067 return -2;
1068 }
1069
1070 const int padding = kernel_size / 2;
1071 int heights[3];
1072 int widths[3];
1073 int live_heights[3];
1074 heights[0] = conv_output_extent(feature_frames, kernel_size, stride, padding);
1075 widths[0] = conv_output_extent(feature_channels, kernel_size, stride, padding);
1076 live_heights[0] = conv_output_extent(live_frames, kernel_size, stride, padding);
1077 for (int stage = 1; stage < 3; ++stage) {
1078 heights[stage] = conv_output_extent(heights[stage - 1], kernel_size, stride, padding);
1079 widths[stage] = conv_output_extent(widths[stage - 1], kernel_size, stride, padding);
1080 live_heights[stage] = conv_output_extent(
1081 live_heights[stage - 1], kernel_size, stride, padding);
1082 }
1083 if (heights[2] <= 0 || widths[2] <= 0 || live_heights[2] <= 0 ||
1084 output_capacity_frames < heights[2]) {
1085 return -3;
1086 }
1087
1088 size_t stage0_elements = 0;
1089 if (checked_mul_size((size_t)conv_channels, (size_t)heights[0], &stage0_elements) != 0 ||
1090 checked_mul_size(stage0_elements, (size_t)widths[0], &stage0_elements) != 0) {
1091 return -4;
1092 }
1093 float *ping = (float *)workspace;
1094 float *pong = ping + stage0_elements;
1095
1096 int status = audio_conv2d_whc_grouped_f32(
1097 features, conv0_weight, conv0_bias, ping,
1098 feature_channels, feature_frames, 1, conv_channels,
1099 kernel_size, kernel_size, stride, stride, padding, padding, 1,
1100 widths[0], heights[0]);
1101 if (status != 0) return -10;
1102 zero_subsampling_padding(ping, conv_channels, heights[0], widths[0], live_heights[0]);
1103 relu_subsampling_inplace(ping, stage0_elements);
1104
1106 ping, depthwise1_weight, depthwise1_bias, pong,
1107 widths[0], heights[0], conv_channels, conv_channels,
1108 kernel_size, kernel_size, stride, stride, padding, padding, conv_channels,
1109 widths[1], heights[1]);
1110 if (status != 0) return -11;
1111 zero_subsampling_padding(pong, conv_channels, heights[1], widths[1], live_heights[1]);
1112
1114 pong, pointwise1_weight, pointwise1_bias, ping,
1115 widths[1], heights[1], conv_channels, conv_channels,
1116 1, 1, 1, 1, 0, 0, 1, widths[1], heights[1]);
1117 if (status != 0) return -12;
1118 size_t stage1_elements = 0;
1119 if (checked_mul_size((size_t)conv_channels, (size_t)heights[1], &stage1_elements) != 0 ||
1120 checked_mul_size(stage1_elements, (size_t)widths[1], &stage1_elements) != 0) {
1121 return -4;
1122 }
1123 zero_subsampling_padding(ping, conv_channels, heights[1], widths[1], live_heights[1]);
1124 relu_subsampling_inplace(ping, stage1_elements);
1125
1127 ping, depthwise2_weight, depthwise2_bias, pong,
1128 widths[1], heights[1], conv_channels, conv_channels,
1129 kernel_size, kernel_size, stride, stride, padding, padding, conv_channels,
1130 widths[2], heights[2]);
1131 if (status != 0) return -13;
1132 zero_subsampling_padding(pong, conv_channels, heights[2], widths[2], live_heights[2]);
1133
1135 pong, pointwise2_weight, pointwise2_bias, ping,
1136 widths[2], heights[2], conv_channels, conv_channels,
1137 1, 1, 1, 1, 0, 0, 1, widths[2], heights[2]);
1138 if (status != 0) return -14;
1139 size_t final_elements = 0;
1140 if (checked_mul_size((size_t)conv_channels, (size_t)heights[2], &final_elements) != 0 ||
1141 checked_mul_size(final_elements, (size_t)widths[2], &final_elements) != 0) {
1142 return -4;
1143 }
1144 zero_subsampling_padding(ping, conv_channels, heights[2], widths[2], live_heights[2]);
1145 relu_subsampling_inplace(ping, final_elements);
1146
1147 if (widths[2] > INT_MAX / conv_channels) return -4;
1148 const int flattened_width = conv_channels * widths[2];
1149 for (int frame = 0; frame < heights[2]; ++frame) {
1150 float *row = pong + (size_t)frame * (size_t)flattened_width;
1151 for (int channel = 0; channel < conv_channels; ++channel) {
1152 const float *source = ping +
1153 ((size_t)channel * (size_t)heights[2] + (size_t)frame) * (size_t)widths[2];
1154 memcpy(row + (size_t)channel * (size_t)widths[2], source,
1155 (size_t)widths[2] * sizeof(float));
1156 }
1157 }
1158
1160 pong, linear_weight, linear_bias, output,
1161 heights[2], hidden_size, flattened_width);
1162 *output_frames = heights[2];
1163 return 0;
1164}
int audio_conv2d_whc_grouped_f32(const float *input, const float *weight, const float *bias, float *output, int input_width, int input_height, int input_channels, int output_channels, int kernel_width, int kernel_height, int stride_width, int stride_height, int padding_width, int padding_height, int groups, int output_width, int output_height)
size_t audio_fastconformer_subsampling_workspace_bytes(int feature_frames, int feature_channels, int conv_channels, int kernel_size, int stride)
static void relu_subsampling_inplace(float *value, size_t elements)
static int conv_output_extent(int input, int kernel, int stride, int padding)
static void zero_subsampling_padding(float *value, int channels, int frames, int width, int live_frames)
static int checked_mul_size(size_t left, size_t right, size_t *result)

References audio_conv2d_whc_grouped_f32(), audio_fastconformer_subsampling_workspace_bytes(), checked_mul_size(), conv_output_extent(), gemm_nt_f32_llama_production_parallel_dispatch(), relu_subsampling_inplace(), and zero_subsampling_padding().

◆ audio_fastconformer_subsampling_workspace_bytes()

size_t audio_fastconformer_subsampling_workspace_bytes ( int  feature_frames,
int  feature_channels,
int  conv_channels,
int  kernel_size,
int  stride 
)

Definition at line 967 of file audio_kernels.c.

973{
974 if (feature_frames <= 0 || feature_channels <= 0 || conv_channels <= 0 ||
975 kernel_size != 3 || stride != 2) {
976 return 0;
977 }
978 const int padding = kernel_size / 2;
979 const int stage_frames = conv_output_extent(
980 feature_frames, kernel_size, stride, padding);
981 const int stage_width = conv_output_extent(
982 feature_channels, kernel_size, stride, padding);
983 if (stage_frames <= 0 || stage_width <= 0) {
984 return 0;
985 }
986 size_t elements = 0;
987 size_t bytes = 0;
988 if (checked_mul_size((size_t)stage_frames, (size_t)stage_width, &elements) != 0 ||
989 checked_mul_size(elements, (size_t)conv_channels, &elements) != 0 ||
990 checked_mul_size(elements, 2u * sizeof(float), &bytes) != 0) {
991 return 0;
992 }
993 return bytes;
994}

References checked_mul_size(), and conv_output_extent().

Referenced by audio_fastconformer_subsampling_f32().

◆ audio_feature_normalize_per_feature_f32()

int audio_feature_normalize_per_feature_f32 ( const float *  input,
float *  output,
int  channels,
int  frames,
float  epsilon 
)

Definition at line 398 of file audio_kernels.c.

404{
405 if (input == NULL || output == NULL) {
406 return -1;
407 }
408 if (channels <= 0 || frames <= 0 || !isfinite(epsilon) || epsilon < 0.0f) {
409 return -2;
410 }
411 const int denominator = frames > 1 ? frames - 1 : 1;
412 for (int channel = 0; channel < channels; ++channel) {
413 double sum = 0.0;
414 double sum_squared_difference = 0.0;
415 for (int frame = 0; frame < frames; ++frame) {
416 sum += (double)input[(size_t)frame * channels + channel];
417 }
418 const double mean = sum / (double)frames;
419 for (int frame = 0; frame < frames; ++frame) {
420 const double difference =
421 (double)input[(size_t)frame * channels + channel] - mean;
422 sum_squared_difference += difference * difference;
423 }
424 float standard_deviation = sqrtf(
425 (float)(sum_squared_difference / (double)denominator));
426 if (isnan(standard_deviation)) {
427 standard_deviation = 0.0f;
428 }
429 const float inverse_standard_deviation =
430 1.0f / (standard_deviation + epsilon);
431 for (int frame = 0; frame < frames; ++frame) {
432 const size_t index = (size_t)frame * channels + channel;
433 output[index] = (float)((double)input[index] - mean) *
434 inverse_standard_deviation;
435 }
436 }
437 return 0;
438}

◆ audio_glu_split_channel_major_f32()

int audio_glu_split_channel_major_f32 ( const float *  input,
float *  output,
int  channels,
int  frames 
)

Definition at line 1596 of file audio_kernels.c.

1601{
1602 if (input == NULL || output == NULL) {
1603 return -1;
1604 }
1605 if (channels <= 0 || frames <= 0) {
1606 return -2;
1607 }
1608 const int elements = channels * frames;
1609 ck_audio_glu_split_f32_args_t args = {
1610 .value = input,
1611 .gate = input + elements,
1612 .output = output,
1613 };
1614 ck_threadpool_t *pool = ck_threadpool_global();
1615 int active = pool ? ck_threadpool_n_threads(pool) : 1;
1616 if (active > elements) {
1617 active = elements;
1618 }
1619 if (pool != NULL && active > 1) {
1621 pool, active, 0, elements, 256,
1623 } else {
1624 ck_audio_glu_split_f32_range(0, elements, &args);
1625 }
1626 return 0;
1627}
static void ck_audio_glu_split_f32_range(int begin, int end, void *opaque)

References ck_audio_glu_split_f32_range(), ck_threadpool_global(), ck_threadpool_n_threads(), and ck_threadpool_parallel_for_n().

Referenced by audio_fastconformer_block_f32().

◆ audio_hann_window_f32()

int audio_hann_window_f32 ( float *  output,
int  frames,
int  periodic 
)

Definition at line 357 of file audio_kernels.c.

358{
359 if (output == NULL) {
360 return -1;
361 }
362 if (frames <= 1 || (periodic != 0 && periodic != 1)) {
363 return -2;
364 }
365 const double denominator = (double)(periodic ? frames : frames - 1);
366 for (int frame = 0; frame < frames; ++frame) {
367 const double phase = 2.0 * CK_AUDIO_PI_D * (double)frame / denominator;
368 output[frame] = (float)(0.5 - 0.5 * cos(phase));
369 }
370 return 0;
371}
#define CK_AUDIO_PI_D

References CK_AUDIO_PI_D.

◆ audio_log_mel_time_major_f32()

int audio_log_mel_time_major_f32 ( const float *  power,
const float *  mel_filters,
float *  log_mel,
int  frames,
int  bins,
int  channels,
float  epsilon 
)

Definition at line 750 of file audio_kernels.c.

758{
759 if (power == NULL || mel_filters == NULL || log_mel == NULL) {
760 return -1;
761 }
762 if (frames <= 0 || bins <= 0 || channels <= 0 || epsilon <= 0.0f) {
763 return -2;
764 }
765 for (int frame = 0; frame < frames; ++frame) {
766 const float *spectrum = power + (size_t)frame * bins;
767 float *output = log_mel + (size_t)frame * channels;
768 for (int channel = 0; channel < channels; ++channel) {
769 const float *filter = mel_filters + (size_t)channel * bins;
770 float sum = 0.0f;
771 for (int bin = 0; bin < bins; ++bin) {
772 sum = fmaf(spectrum[bin], filter[bin], sum);
773 }
774 output[channel] = logf(sum + epsilon);
775 }
776 }
777 return 0;
778}

◆ audio_lstm_bidirectional_scan_f32()

int audio_lstm_bidirectional_scan_f32 ( const float *  input,
size_t  input_elements,
const float *  weight_ih,
size_t  weight_ih_elements,
const float *  weight_hh,
size_t  weight_hh_elements,
const float *  bias_ih,
size_t  bias_ih_elements,
const float *  bias_hh,
size_t  bias_hh_elements,
float *  output,
size_t  output_elements,
float *  hidden_state,
size_t  hidden_state_elements,
float *  cell_state,
size_t  cell_state_elements,
float *  gates_scratch,
size_t  gates_scratch_bytes,
int  tokens,
int  input_size,
int  hidden_size,
size_t  input_stride,
size_t  output_stride 
)

Definition at line 31 of file audio_lstm_scan.c.

43{
44 if (input == NULL || weight_ih == NULL || weight_hh == NULL ||
45 bias_ih == NULL || bias_hh == NULL || output == NULL ||
46 hidden_state == NULL || cell_state == NULL || gates_scratch == NULL) {
47 return -1;
48 }
49 if (tokens <= 0 || input_size <= 0 || hidden_size <= 0 ||
50 hidden_size > INT_MAX / 4) {
51 return -2;
52 }
53
54 const size_t token_count = (size_t)tokens;
55 const size_t input_width = (size_t)input_size;
56 const size_t hidden_width = (size_t)hidden_size;
57 const size_t output_width = hidden_width * 2u;
58 size_t input_required, output_required, gates_count;
59 size_t ih_per_direction, hh_per_direction, bias_required;
60 size_t ih_required, hh_required, gates_bytes, state_bytes;
61 if (input_stride < input_width || output_stride < output_width ||
62 !checked_span(token_count, input_stride, input_width, &input_required) ||
63 !checked_span(token_count, output_stride, output_width, &output_required) ||
64 !checked_product(hidden_width, 4u, &gates_count) ||
65 !checked_product(gates_count, input_width, &ih_per_direction) ||
66 !checked_product(gates_count, hidden_width, &hh_per_direction) ||
67 !checked_product(ih_per_direction, 2u, &ih_required) ||
68 !checked_product(hh_per_direction, 2u, &hh_required) ||
69 !checked_product(gates_count, 2u, &bias_required) ||
70 !checked_product(gates_count, sizeof(float), &gates_bytes) ||
71 !checked_product(output_width, sizeof(float), &state_bytes)) {
72 return -2;
73 }
74 if (input_elements < input_required || output_elements < output_required ||
75 weight_ih_elements < ih_required || weight_hh_elements < hh_required ||
76 bias_ih_elements < bias_required || bias_hh_elements < bias_required ||
77 hidden_state_elements < output_width ||
78 cell_state_elements < output_width ||
79 gates_scratch_bytes < gates_bytes) {
80 return -3;
81 }
82
83 /* Every invocation starts from zero state, as a batch-one PyTorch LSTM
84 * called without initial (h, c) does. Padding outside valid rows is not touched.
85 */
86 memset(hidden_state, 0, state_bytes);
87 memset(cell_state, 0, state_bytes);
88 for (size_t index = 0u; index < token_count; ++index) {
89 const int status = audio_lstm_step_f32(
90 input + index * input_stride,
91 weight_ih, weight_hh, bias_ih, bias_hh,
92 hidden_state, cell_state,
93 output + index * output_stride,
94 gates_scratch, gates_scratch_bytes, input_size, hidden_size);
95 if (status != 0) {
96 return status;
97 }
98 }
99 for (size_t reverse_index = 0u; reverse_index < token_count;
100 ++reverse_index) {
101 const size_t index = token_count - 1u - reverse_index;
102 const int status = audio_lstm_step_f32(
103 input + index * input_stride,
104 weight_ih + ih_per_direction,
105 weight_hh + hh_per_direction,
106 bias_ih + gates_count,
107 bias_hh + gates_count,
108 hidden_state + hidden_width,
109 cell_state + hidden_width,
110 output + index * output_stride + hidden_width,
111 gates_scratch, gates_scratch_bytes, input_size, hidden_size);
112 if (status != 0) {
113 return status;
114 }
115 }
116 return 0;
117}
static int checked_product(size_t left, size_t right, size_t *result)
static int checked_span(size_t rows, size_t stride, size_t width, size_t *result)
int audio_lstm_step_f32(const float *input, const float *weight_ih, const float *weight_hh, const float *bias_ih, const float *bias_hh, float *hidden_state, float *cell_state, float *output, float *gates_scratch, size_t gates_scratch_bytes, int input_size, int hidden_size)

References audio_lstm_step_f32(), checked_product(), and checked_span().

◆ audio_lstm_step_f32()

int audio_lstm_step_f32 ( const float *  input,
const float *  weight_ih,
const float *  weight_hh,
const float *  bias_ih,
const float *  bias_hh,
float *  hidden_state,
float *  cell_state,
float *  output,
float *  gates_scratch,
size_t  gates_scratch_bytes,
int  input_size,
int  hidden_size 
)

Definition at line 505 of file audio_kernels.c.

518{
519 if (input == NULL || weight_ih == NULL || weight_hh == NULL ||
520 bias_ih == NULL || bias_hh == NULL || hidden_state == NULL ||
521 cell_state == NULL || output == NULL || gates_scratch == NULL) {
522 return -1;
523 }
524 /* The IFGO update indexes gates[3 * hidden_size + index] with signed int. */
525 if (input_size <= 0 || hidden_size <= 0 ||
526 hidden_size > INT_MAX / 4 ||
527 (size_t)hidden_size > SIZE_MAX / 4u) {
528 return -2;
529 }
530 const size_t gate_count = (size_t)hidden_size * 4u;
531 if (gate_count > SIZE_MAX / sizeof(float) ||
532 gates_scratch_bytes < gate_count * sizeof(float)) {
533 return -3;
534 }
535
536 for (size_t gate = 0; gate < gate_count; ++gate) {
537 float sum = bias_ih[gate] + bias_hh[gate];
538 const float *input_weight = weight_ih + gate * (size_t)input_size;
539 const float *hidden_weight = weight_hh + gate * (size_t)hidden_size;
540 for (int index = 0; index < input_size; ++index) {
541 sum += input_weight[index] * input[index];
542 }
543 for (int index = 0; index < hidden_size; ++index) {
544 sum += hidden_weight[index] * hidden_state[index];
545 }
546 gates_scratch[gate] = sum;
547 }
548
549 for (int index = 0; index < hidden_size; ++index) {
550 const float input_gate = 1.0f /
551 (1.0f + expf(-gates_scratch[index]));
552 const float forget_gate = 1.0f /
553 (1.0f + expf(-gates_scratch[hidden_size + index]));
554 const float cell_gate = tanhf(gates_scratch[2 * hidden_size + index]);
555 const float output_gate = 1.0f /
556 (1.0f + expf(-gates_scratch[3 * hidden_size + index]));
557 const float cell = forget_gate * cell_state[index] +
558 input_gate * cell_gate;
559 const float hidden = output_gate * tanhf(cell);
560 cell_state[index] = cell;
561 hidden_state[index] = hidden;
562 output[index] = hidden;
563 }
564 return 0;
565}

Referenced by audio_lstm_bidirectional_scan_f32().

◆ audio_pad_or_truncate_f32()

int audio_pad_or_truncate_f32 ( const float *  input,
int  input_frames,
float *  output,
int  output_frames 
)

Definition at line 334 of file audio_kernels.c.

339{
340 if (input == NULL || output == NULL) {
341 return -1;
342 }
343 if (input_frames <= 0 || output_frames <= 0) {
344 return -2;
345 }
346 const int copied = input_frames < output_frames ? input_frames : output_frames;
347 memmove(output, input, (size_t)copied * sizeof(float));
348 if (copied < output_frames) {
349 memset(
350 output + copied,
351 0,
352 (size_t)(output_frames - copied) * sizeof(float));
353 }
354 return copied;
355}

◆ audio_pcm_s16_to_mono_f32()

int audio_pcm_s16_to_mono_f32 ( const int16_t *  interleaved,
int  n_frames,
int  n_channels,
float *  mono 
)

Definition at line 230 of file audio_kernels.c.

235{
236 if (interleaved == NULL || mono == NULL) {
237 return -1;
238 }
239 if (n_frames <= 0 || n_channels <= 0) {
240 return -2;
241 }
242 const float scale = 1.0f / 32768.0f;
243 for (int frame = 0; frame < n_frames; ++frame) {
244 float sum = 0.0f;
245 for (int channel = 0; channel < n_channels; ++channel) {
246 sum += (float)interleaved[(size_t)frame * n_channels + channel];
247 }
248 mono[frame] = (sum / (float)n_channels) * scale;
249 }
250 return 0;
251}

◆ audio_preemphasis_f32()

int audio_preemphasis_f32 ( const float *  input,
float *  output,
int  frames,
float  coefficient 
)

Definition at line 373 of file audio_kernels.c.

378{
379 if (input == NULL || output == NULL) {
380 return -1;
381 }
382 if (frames <= 0 || !isfinite(coefficient)) {
383 return -2;
384 }
385 if (input == output) {
386 for (int frame = frames - 1; frame > 0; --frame) {
387 output[frame] = input[frame] - coefficient * input[frame - 1];
388 }
389 } else {
390 output[0] = input[0];
391 for (int frame = 1; frame < frames; ++frame) {
392 output[frame] = input[frame] - coefficient * input[frame - 1];
393 }
394 }
395 return 0;
396}

◆ audio_relative_shift_f32()

int audio_relative_shift_f32 ( const float *  raw_scores,
float *  scores,
int  heads,
int  query_frames 
)

Definition at line 1654 of file audio_kernels.c.

1659{
1660 if (raw_scores == NULL || scores == NULL) {
1661 return -1;
1662 }
1663 if (heads <= 0 || query_frames <= 0) {
1664 return -2;
1665 }
1666 const int rows = heads * query_frames;
1667 ck_audio_relative_shift_f32_args_t args = {
1668 .raw_scores = raw_scores,
1669 .scores = scores,
1670 .query_frames = query_frames,
1671 .raw_key_frames = 2 * query_frames - 1,
1672 };
1673 ck_threadpool_t *pool = ck_threadpool_global();
1674 int active = pool ? ck_threadpool_n_threads(pool) : 1;
1675 if (active > rows) {
1676 active = rows;
1677 }
1678 if (pool != NULL && active > 1) {
1680 pool, active, 0, rows, 1,
1682 } else {
1683 ck_audio_relative_shift_f32_range(0, rows, &args);
1684 }
1685 return 0;
1686}
static void ck_audio_relative_shift_f32_range(int begin, int end, void *opaque)

References ck_audio_relative_shift_f32_range(), ck_threadpool_global(), ck_threadpool_n_threads(), and ck_threadpool_parallel_for_n().

◆ audio_relative_sinusoidal_position_f32()

int audio_relative_sinusoidal_position_f32 ( float *  output,
int  frames,
int  channels 
)

Definition at line 440 of file audio_kernels.c.

444{
445 if (output == NULL) {
446 return -1;
447 }
448 if (frames <= 0 || frames > (INT_MAX / 2) + 1 ||
449 channels <= 0 || (channels & 1) != 0) {
450 return -2;
451 }
452 if ((size_t)(2 * frames - 1) > SIZE_MAX / (size_t)channels) {
453 return -3;
454 }
455 const int positions = 2 * frames - 1;
456 for (int row = 0; row < positions; ++row) {
457 const float position = (float)(frames - 1 - row);
458 for (int channel = 0; channel < channels; channel += 2) {
459 const float exponent = (float)channel / (float)channels;
460 const float inverse_frequency = 1.0f / powf(10000.0f, exponent);
461 const float frequency = inverse_frequency * position;
462 output[(size_t)row * channels + channel] = sinf(frequency);
463 output[(size_t)row * channels + channel + 1] = cosf(frequency);
464 }
465 }
466 return 0;
467}

◆ audio_resample_linear_f32()

int audio_resample_linear_f32 ( const float *  input,
int  input_frames,
int  input_rate,
float *  output,
int  output_frames,
int  output_rate 
)

Definition at line 264 of file audio_kernels.c.

271{
272 if (input == NULL || output == NULL) {
273 return -1;
274 }
275 const int expected = audio_resampled_frame_count(input_frames, input_rate, output_rate);
276 if (expected <= 0 || output_frames != expected) {
277 return -2;
278 }
279 for (int frame = 0; frame < output_frames; ++frame) {
280 const long long numerator = (long long)frame * input_rate;
281 const int left = (int)(numerator / output_rate);
282 const int right = left + 1 < input_frames ? left + 1 : left;
283 const float fraction = (float)(numerator % output_rate) / (float)output_rate;
284 output[frame] = fmaf(input[right] - input[left], fraction, input[left]);
285 }
286 return 0;
287}
int audio_resampled_frame_count(int input_frames, int input_rate, int output_rate)
const char * left
Definition true_bpe.h:138
const char const char * right
Definition true_bpe.h:139

References audio_resampled_frame_count(), left, and right.

◆ audio_resample_windowed_sinc_f32()

int audio_resample_windowed_sinc_f32 ( const float *  input,
int  input_frames,
int  input_rate,
float *  output,
int  output_frames,
int  output_rate,
int  radius 
)

Definition at line 289 of file audio_kernels.c.

297{
298 if (input == NULL || output == NULL) {
299 return -1;
300 }
301 const int expected = audio_resampled_frame_count(input_frames, input_rate, output_rate);
302 if (expected <= 0 || output_frames != expected || radius < 2 || radius > 128) {
303 return -2;
304 }
305 const double ratio = (double)output_rate / (double)input_rate;
306 const double cutoff = ratio < 1.0 ? ratio : 1.0;
307 for (int frame = 0; frame < output_frames; ++frame) {
308 const double source = (double)frame * (double)input_rate / (double)output_rate;
309 const int center = (int)floor(source);
310 double weighted = 0.0;
311 double weight_sum = 0.0;
312 for (int tap = center - radius + 1; tap <= center + radius; ++tap) {
313 if (tap < 0 || tap >= input_frames) {
314 continue;
315 }
316 const double distance = source - (double)tap;
317 const double scaled = cutoff * distance;
318 const double sinc = fabs(scaled) < 1.0e-12 ? 1.0 :
319 sin(CK_AUDIO_PI_D * scaled) / (CK_AUDIO_PI_D * scaled);
320 const double window_x = distance / (double)radius;
321 if (fabs(window_x) >= 1.0) {
322 continue;
323 }
324 const double window = 0.5 * (1.0 + cos(CK_AUDIO_PI_D * window_x));
325 const double weight = cutoff * sinc * window;
326 weighted += (double)input[tap] * weight;
327 weight_sum += weight;
328 }
329 output[frame] = weight_sum != 0.0 ? (float)(weighted / weight_sum) : 0.0f;
330 }
331 return 0;
332}

References audio_resampled_frame_count(), and CK_AUDIO_PI_D.

◆ audio_resampled_frame_count()

int audio_resampled_frame_count ( int  input_frames,
int  input_rate,
int  output_rate 
)

Definition at line 253 of file audio_kernels.c.

257{
258 if (input_frames <= 0 || input_rate <= 0 || output_rate <= 0) {
259 return -1;
260 }
261 return 1 + (int)(((long long)(input_frames - 1) * output_rate) / input_rate);
262}

Referenced by audio_resample_linear_f32(), and audio_resample_windowed_sinc_f32().

◆ audio_scaled_residual_add_f32()

int audio_scaled_residual_add_f32 ( const float *  residual,
const float *  branch,
float  scale,
float *  output,
size_t  elements 
)

Definition at line 1852 of file audio_kernels.c.

1858{
1859 if (residual == NULL || branch == NULL || output == NULL) {
1860 return -1;
1861 }
1862 if (elements == 0 || !isfinite(scale)) {
1863 return -2;
1864 }
1865 for (size_t index = 0; index < elements; ++index) {
1866 /* Preserve the pinned elementwise multiply then add cast boundary. */
1867 volatile float scaled = branch[index] * scale;
1868 output[index] = residual[index] + scaled;
1869 }
1870 return 0;
1871}

Referenced by audio_fastconformer_block_f32().

◆ audio_stft_power_centered_window_f32()

int audio_stft_power_centered_window_f32 ( const float *  samples,
int  n_samples,
const float *  window,
int  window_length,
const float *  cos_table,
const float *  sin_table,
int  n_fft,
int  hop_length,
int  reflect_padding,
float *  power,
int  n_frames 
)

Definition at line 695 of file audio_kernels.c.

707{
708 if (samples == NULL || window == NULL || cos_table == NULL ||
709 sin_table == NULL || power == NULL) {
710 return -1;
711 }
712 if (n_samples <= 0 || window_length <= 0 || n_fft <= 0 ||
713 window_length > n_fft || (n_fft & 1) != 0 || hop_length <= 0 ||
714 n_frames <= 0 || (reflect_padding != 0 && reflect_padding != 1)) {
715 return -2;
716 }
717 if (n_frames != n_samples / hop_length + 1) {
718 return -3;
719 }
720
721 const int bins = n_fft / 2 + 1;
722 const int center = n_fft / 2;
723 const int window_start = (n_fft - window_length) / 2;
724 for (int frame = 0; frame < n_frames; ++frame) {
725 for (int bin = 0; bin < bins; ++bin) {
726 const float *cos_row = cos_table + (size_t)bin * n_fft;
727 const float *sin_row = sin_table + (size_t)bin * n_fft;
728 float real = 0.0f;
729 float imag = 0.0f;
730 for (int sample = 0; sample < window_length; ++sample) {
731 const int fft_sample = window_start + sample;
732 int source = frame * hop_length + fft_sample - center;
733 if (source < 0 || source >= n_samples) {
734 if (!reflect_padding) {
735 continue;
736 }
737 source = reflect_index(source, n_samples);
738 }
739 const float value = samples[source] * window[sample];
740 real = fmaf(value, cos_row[fft_sample], real);
741 imag = fmaf(value, sin_row[fft_sample], imag);
742 }
743 power[(size_t)frame * bins + bin] =
744 fmaf(real, real, imag * imag);
745 }
746 }
747 return 0;
748}
static int reflect_index(int index, int length)

References reflect_index().

◆ audio_stft_power_fft400_f32()

int audio_stft_power_fft400_f32 ( const float *  samples,
int  n_samples,
const float *  window,
const float *  cos_table,
const float *  sin_table,
int  hop_length,
float *  power,
int  n_frames,
float *  fft_scratch 
)

Definition at line 790 of file audio_kernels.c.

800{
801 const int n_fft = CK_AUDIO_WHISPER_N_FFT;
802 if (samples == NULL || window == NULL || cos_table == NULL ||
803 sin_table == NULL || power == NULL || fft_scratch == NULL) {
804 return -1;
805 }
806 if (hop_length != CK_AUDIO_WHISPER_HOP_LENGTH ||
807 n_samples <= n_fft / 2 || n_frames <= 0 ||
808 n_frames != n_samples / hop_length) {
809 return -2;
810 }
811 for (int frame = 0; frame < n_frames; ++frame) {
813 samples,
814 n_samples,
815 frame,
816 window,
817 cos_table,
818 sin_table,
819 power + (size_t)frame * CK_AUDIO_WHISPER_POWER_BINS,
820 fft_scratch);
821 }
822 return 0;
823}
static void audio_stft_power_fft400_frame_f32(const float *samples, int n_samples, int frame, const float *window, const float *cos_table, const float *sin_table, float *power, float *fft_scratch)
#define CK_AUDIO_WHISPER_N_FFT
#define CK_AUDIO_WHISPER_HOP_LENGTH
#define CK_AUDIO_WHISPER_POWER_BINS

References audio_stft_power_fft400_frame_f32(), CK_AUDIO_WHISPER_HOP_LENGTH, CK_AUDIO_WHISPER_N_FFT, and CK_AUDIO_WHISPER_POWER_BINS.

◆ audio_stft_power_precomputed_f32()

int audio_stft_power_precomputed_f32 ( const float *  samples,
int  n_samples,
const float *  window,
const float *  cos_table,
const float *  sin_table,
int  n_fft,
int  hop_length,
float *  power,
int  n_frames 
)

Definition at line 651 of file audio_kernels.c.

661{
662 if (samples == NULL || window == NULL || cos_table == NULL ||
663 sin_table == NULL || power == NULL) {
664 return -1;
665 }
666 if (n_fft <= 0 || hop_length <= 0 || n_samples <= n_fft / 2 ||
667 (n_fft & 1) != 0 || n_frames <= 0) {
668 return -2;
669 }
670 if (n_frames != n_samples / hop_length) {
671 return -3;
672 }
673 const int bins = n_fft / 2 + 1;
674 const int center = n_fft / 2;
675 for (int frame = 0; frame < n_frames; ++frame) {
676 for (int bin = 0; bin < bins; ++bin) {
677 const float *cos_row = cos_table + (size_t)bin * n_fft;
678 const float *sin_row = sin_table + (size_t)bin * n_fft;
679 float real = 0.0f;
680 float imag = 0.0f;
681 for (int sample = 0; sample < n_fft; ++sample) {
682 const int source = reflect_index(
683 frame * hop_length + sample - center, n_samples);
684 const float value = samples[source] * window[sample];
685 real = fmaf(value, cos_row[sample], real);
686 imag = fmaf(value, sin_row[sample], imag);
687 }
688 power[(size_t)frame * bins + bin] =
689 fmaf(real, real, imag * imag);
690 }
691 }
692 return 0;
693}

References reflect_index().

◆ audio_stft_precompute_tables_f32()

int audio_stft_precompute_tables_f32 ( int  n_fft,
float *  window,
float *  cos_table,
float *  sin_table 
)

Definition at line 567 of file audio_kernels.c.

572{
573 if (window == NULL || cos_table == NULL || sin_table == NULL) {
574 return -1;
575 }
576 if (n_fft <= 0 || (n_fft & 1) != 0) {
577 return -2;
578 }
579 const int bins = n_fft / 2 + 1;
580 for (int sample = 0; sample < n_fft; ++sample) {
581 window[sample] = 0.5f - 0.5f * cosf(
582 2.0f * CK_AUDIO_PI_F * (float)sample / (float)n_fft);
583 }
584 for (int bin = 0; bin < bins; ++bin) {
585 for (int sample = 0; sample < n_fft; ++sample) {
586 const float angle = -2.0f * CK_AUDIO_PI_F *
587 (float)(bin * sample) / (float)n_fft;
588 const size_t index = (size_t)bin * n_fft + sample;
589 cos_table[index] = cosf(angle);
590 sin_table[index] = sinf(angle);
591 }
592 }
593 return 0;
594}
#define CK_AUDIO_PI_F

References CK_AUDIO_PI_F.

◆ audio_transpose_channel_to_token_f32()

int audio_transpose_channel_to_token_f32 ( const float *  input,
float *  output,
int  channels,
int  frames 
)

Definition at line 1831 of file audio_kernels.c.

1836{
1837 if (input == NULL || output == NULL) {
1838 return -1;
1839 }
1840 if (channels <= 0 || frames <= 0) {
1841 return -2;
1842 }
1843 for (int frame = 0; frame < frames; ++frame) {
1844 for (int channel = 0; channel < channels; ++channel) {
1845 output[(size_t)frame * channels + channel] =
1846 input[(size_t)channel * frames + frame];
1847 }
1848 }
1849 return 0;
1850}

◆ audio_wav_decode_memory_pcm16_mono_f32()

int audio_wav_decode_memory_pcm16_mono_f32 ( const uint8_t *  bytes,
size_t  byte_count,
float *  mono,
int  mono_capacity,
CKAudioWavInfo *  info 
)

Definition at line 187 of file audio_kernels.c.

193{
195 bytes, byte_count, 0, mono, mono_capacity, info);
196}
int audio_wav_decode_memory_pcm16_mono_window_f32(const uint8_t *bytes, size_t byte_count, int start_frame, float *mono, int mono_capacity, CKAudioWavInfo *info)

References audio_wav_decode_memory_pcm16_mono_window_f32().

◆ audio_wav_decode_memory_pcm16_mono_window_f32()

int audio_wav_decode_memory_pcm16_mono_window_f32 ( const uint8_t *  bytes,
size_t  byte_count,
int  start_frame,
float *  mono,
int  mono_capacity,
CKAudioWavInfo *  info 
)

Definition at line 198 of file audio_kernels.c.

205{
206 const int status = audio_wav_parse_memory(bytes, byte_count, info);
207 if (status != 0) {
208 return status;
209 }
210 if (start_frame < 0 || start_frame >= info->frames || mono_capacity <= 0) {
211 return -7;
212 }
213 const int available = info->frames - start_frame;
214 const int decoded = available < mono_capacity ? available : mono_capacity;
215 const uint8_t *pcm = bytes + info->data_offset;
216 const float scale = 1.0f / 32768.0f;
217 for (int frame = 0; frame < decoded; ++frame) {
218 float sum = 0.0f;
219 const size_t source_frame = (size_t)start_frame + (size_t)frame;
220 for (int channel = 0; channel < info->channels; ++channel) {
221 const size_t index =
222 (source_frame * (size_t)info->channels + (size_t)channel) * 2u;
223 sum += (float)(int16_t)read_u16_le(pcm + index);
224 }
225 mono[frame] = (sum / (float)info->channels) * scale;
226 }
227 return decoded;
228}
int audio_wav_parse_memory(const uint8_t *bytes, size_t byte_count, CKAudioWavInfo *info)
static uint16_t read_u16_le(const uint8_t *p)

References audio_wav_parse_memory(), CKAudioWavInfo::channels, CKAudioWavInfo::data_offset, CKAudioWavInfo::frames, and read_u16_le().

Referenced by audio_wav_decode_memory_pcm16_mono_f32().

◆ audio_wav_decode_pcm16_mono_f32()

int audio_wav_decode_pcm16_mono_f32 ( const uint8_t *  bytes,
size_t  byte_count,
const CKAudioWavInfo *  info,
float *  mono,
int  mono_capacity 
)

Definition at line 159 of file audio_kernels.c.

165{
166 if (bytes == NULL || info == NULL || mono == NULL) {
167 return -1;
168 }
169 if (info->format_tag != 1 || info->bits_per_sample != 16 ||
170 info->channels <= 0 || info->frames <= 0 || mono_capacity < info->frames ||
171 info->data_offset > byte_count || info->data_bytes > byte_count - info->data_offset) {
172 return -2;
173 }
174 const uint8_t *pcm = bytes + info->data_offset;
175 const float scale = 1.0f / 32768.0f;
176 for (int frame = 0; frame < info->frames; ++frame) {
177 float sum = 0.0f;
178 for (int channel = 0; channel < info->channels; ++channel) {
179 const size_t index = ((size_t)frame * info->channels + channel) * 2u;
180 sum += (float)(int16_t)read_u16_le(pcm + index);
181 }
182 mono[frame] = (sum / (float)info->channels) * scale;
183 }
184 return info->frames;
185}

References CKAudioWavInfo::bits_per_sample, CKAudioWavInfo::channels, CKAudioWavInfo::data_bytes, CKAudioWavInfo::data_offset, CKAudioWavInfo::format_tag, CKAudioWavInfo::frames, and read_u16_le().

Referenced by audio_whisper_log_mel_window_wav_pcm16_f32().

◆ audio_wav_parse_memory()

int audio_wav_parse_memory ( const uint8_t *  bytes,
size_t  byte_count,
CKAudioWavInfo *  info 
)

Definition at line 98 of file audio_kernels.c.

102{
103 if (bytes == NULL || info == NULL) {
104 return -1;
105 }
106 if (byte_count < 12 || memcmp(bytes, "RIFF", 4) != 0 ||
107 memcmp(bytes + 8, "WAVE", 4) != 0) {
108 return -2;
109 }
110 const size_t riff_end = (size_t)read_u32_le(bytes + 4) + 8u;
111 if (riff_end < 12 || riff_end > byte_count) {
112 return -3;
113 }
114 memset(info, 0, sizeof(*info));
115 int found_format = 0;
116 int found_data = 0;
117 size_t offset = 12;
118 while (offset + 8 <= riff_end) {
119 const uint8_t *chunk = bytes + offset;
120 const uint32_t chunk_bytes = read_u32_le(chunk + 4);
121 const size_t payload = offset + 8;
122 if ((size_t)chunk_bytes > riff_end - payload) {
123 return -3;
124 }
125 if (!found_format && memcmp(chunk, "fmt ", 4) == 0) {
126 if (chunk_bytes < 16) {
127 return -4;
128 }
129 info->format_tag = (int)read_u16_le(bytes + payload);
130 info->channels = (int)read_u16_le(bytes + payload + 2);
131 info->sample_rate = (int)read_u32_le(bytes + payload + 4);
132 info->bits_per_sample = (int)read_u16_le(bytes + payload + 14);
133 found_format = 1;
134 } else if (!found_data && memcmp(chunk, "data", 4) == 0) {
135 info->data_offset = payload;
136 info->data_bytes = chunk_bytes;
137 found_data = 1;
138 }
139 const size_t padded = (size_t)chunk_bytes + ((size_t)chunk_bytes & 1u);
140 if (padded > SIZE_MAX - payload) {
141 return -3;
142 }
143 offset = payload + padded;
144 }
145 if (!found_format || !found_data || info->format_tag != 1 ||
146 info->channels <= 0 || info->sample_rate <= 0 ||
147 info->bits_per_sample != 16) {
148 return -5;
149 }
150 const size_t bytes_per_frame = (size_t)info->channels * 2u;
151 if (bytes_per_frame == 0 || info->data_bytes % bytes_per_frame != 0 ||
152 info->data_bytes / bytes_per_frame > (size_t)INT_MAX) {
153 return -6;
154 }
155 info->frames = (int)(info->data_bytes / bytes_per_frame);
156 return info->frames > 0 ? 0 : -6;
157}
static uint32_t read_u32_le(const uint8_t *p)

References CKAudioWavInfo::bits_per_sample, CKAudioWavInfo::channels, CKAudioWavInfo::data_bytes, CKAudioWavInfo::data_offset, CKAudioWavInfo::format_tag, CKAudioWavInfo::frames, read_u16_le(), read_u32_le(), and CKAudioWavInfo::sample_rate.

Referenced by audio_wav_decode_memory_pcm16_mono_window_f32(), and audio_whisper_log_mel_window_wav_pcm16_f32().

◆ audio_whisper_log_mel_from_power_reference_f32()

int audio_whisper_log_mel_from_power_reference_f32 ( const float *  power,
const float *  mel_filters,
int  n_mels,
int  n_frames,
float *  log_mel 
)

Definition at line 2214 of file audio_kernels.c.

2220{
2221 if (power == NULL || mel_filters == NULL || log_mel == NULL) {
2222 return -1;
2223 }
2224 if (n_mels <= 0 || n_frames <= 0) {
2225 return -2;
2226 }
2227
2228 float maximum = -INFINITY;
2229 for (int mel = 0; mel < n_mels; ++mel) {
2230 const float *filter = mel_filters + (size_t)mel * CK_AUDIO_WHISPER_POWER_BINS;
2231 float *output = log_mel + (size_t)mel * n_frames;
2232 for (int frame = 0; frame < n_frames; ++frame) {
2233 const float *spectrum = power + (size_t)frame * CK_AUDIO_WHISPER_POWER_BINS;
2234 float sum = 0.0f;
2235 for (int bin = 0; bin < CK_AUDIO_WHISPER_POWER_BINS; ++bin) {
2236 sum = fmaf(filter[bin], spectrum[bin], sum);
2237 }
2238 const float value = log10f(fmaxf(sum, 1.0e-10f));
2239 output[frame] = value;
2240 maximum = fmaxf(maximum, value);
2241 }
2242 }
2243
2244 const float floor = maximum - 8.0f;
2245 for (int mel = 0; mel < n_mels; ++mel) {
2246 float *output = log_mel + (size_t)mel * n_frames;
2247 for (int frame = 0; frame < n_frames; ++frame) {
2248 output[frame] = (fmaxf(output[frame], floor) + 4.0f) / 4.0f;
2249 }
2250 }
2251 return 0;
2252}

References CK_AUDIO_WHISPER_POWER_BINS.

Referenced by audio_whisper_log_mel_reference_f32().

◆ audio_whisper_log_mel_reference_f32()

int audio_whisper_log_mel_reference_f32 ( const float *  samples,
int  n_samples,
const float *  mel_filters,
int  n_mels,
float *  power_scratch,
float *  log_mel,
int  n_frames 
)

Definition at line 2254 of file audio_kernels.c.

2262{
2263 const int stft_status = audio_whisper_stft_power_reference_f32(
2264 samples, n_samples, power_scratch, n_frames);
2265 if (stft_status != 0) {
2266 return stft_status;
2267 }
2269 power_scratch, mel_filters, n_mels, n_frames, log_mel);
2270}
int audio_whisper_stft_power_reference_f32(const float *samples, int n_samples, float *power, int n_frames)
int audio_whisper_log_mel_from_power_reference_f32(const float *power, const float *mel_filters, int n_mels, int n_frames, float *log_mel)

References audio_whisper_log_mel_from_power_reference_f32(), and audio_whisper_stft_power_reference_f32().

◆ audio_whisper_log_mel_window_wav_pcm16_f32()

int audio_whisper_log_mel_window_wav_pcm16_f32 ( const uint8_t *  bytes,
size_t  byte_count,
int  start_frame,
int  target_sample_rate,
const float *  window,
const float *  cos_table,
const float *  sin_table,
const float *  mel_filters,
int  n_mels,
int  output_frames,
float *  log_mel 
)

Definition at line 878 of file audio_kernels.c.

890{
891 if (bytes == NULL || window == NULL || cos_table == NULL ||
892 sin_table == NULL || mel_filters == NULL || log_mel == NULL) {
893 return -1;
894 }
895 CKAudioWavInfo info;
896 if (audio_wav_parse_memory(bytes, byte_count, &info) != 0 ||
897 info.sample_rate != target_sample_rate ||
898 target_sample_rate != CK_AUDIO_WHISPER_SAMPLE_RATE ||
899 start_frame < 0 ||
900 start_frame % CK_AUDIO_WHISPER_HOP_LENGTH != 0 ||
901 n_mels <= 0 || output_frames <= 0) {
902 return -2;
903 }
904 float *samples = (float *)malloc((size_t)info.frames * sizeof(float));
905 if (samples == NULL) {
906 return -3;
907 }
908 const int decoded = audio_wav_decode_pcm16_mono_f32(
909 bytes, byte_count, &info, samples, info.frames);
910 if (decoded != info.frames) {
911 free(samples);
912 return -4;
913 }
914
915 memset(
916 log_mel,
917 0,
918 (size_t)n_mels * (size_t)output_frames * sizeof(float));
919 const int global_frames = info.frames / CK_AUDIO_WHISPER_HOP_LENGTH;
920 const int start_feature = start_frame / CK_AUDIO_WHISPER_HOP_LENGTH;
921 float maximum = -INFINITY;
922 float power[CK_AUDIO_WHISPER_POWER_BINS];
923 float fft_scratch[2 * CK_AUDIO_WHISPER_N_FFT];
924 for (int frame = 0; frame < global_frames; ++frame) {
926 samples,
927 info.frames,
928 frame,
929 window,
930 cos_table,
931 sin_table,
932 power,
933 fft_scratch);
934 for (int mel = 0; mel < n_mels; ++mel) {
935 const float *filter =
936 mel_filters + (size_t)mel * CK_AUDIO_WHISPER_POWER_BINS;
937 float sum = 0.0f;
938 for (int bin = 0; bin < CK_AUDIO_WHISPER_POWER_BINS; ++bin) {
939 sum = fmaf(filter[bin], power[bin], sum);
940 }
941 const float value = log10f(fmaxf(sum, 1.0e-10f));
942 maximum = fmaxf(maximum, value);
943 const int output_frame = frame - start_feature;
944 if (output_frame >= 0 && output_frame < output_frames) {
945 log_mel[(size_t)mel * output_frames + output_frame] = value;
946 }
947 }
948 }
949 free(samples);
950 if (!isfinite(maximum)) {
951 return -5;
952 }
953
954 const int available = global_frames - start_feature;
955 const int valid_frames =
956 available < output_frames ? (available > 0 ? available : 0) : output_frames;
957 const float floor = maximum - 8.0f;
958 for (int mel = 0; mel < n_mels; ++mel) {
959 float *output = log_mel + (size_t)mel * output_frames;
960 for (int frame = 0; frame < valid_frames; ++frame) {
961 output[frame] = (fmaxf(output[frame], floor) + 4.0f) / 4.0f;
962 }
963 }
964 return valid_frames;
965}
int audio_wav_decode_pcm16_mono_f32(const uint8_t *bytes, size_t byte_count, const CKAudioWavInfo *info, float *mono, int mono_capacity)
#define CK_AUDIO_WHISPER_SAMPLE_RATE

References audio_stft_power_fft400_frame_f32(), audio_wav_decode_pcm16_mono_f32(), audio_wav_parse_memory(), CK_AUDIO_WHISPER_HOP_LENGTH, CK_AUDIO_WHISPER_N_FFT, CK_AUDIO_WHISPER_POWER_BINS, CK_AUDIO_WHISPER_SAMPLE_RATE, CKAudioWavInfo::frames, and CKAudioWavInfo::sample_rate.

◆ audio_whisper_mel_filters_slaney_f32()

int audio_whisper_mel_filters_slaney_f32 ( int  sample_rate,
int  n_fft,
int  n_mels,
float *  mel_filters 
)

Definition at line 612 of file audio_kernels.c.

617{
618 if (mel_filters == NULL) {
619 return -1;
620 }
621 if (sample_rate <= 0 || n_fft <= 0 || (n_fft & 1) != 0 || n_mels <= 0) {
622 return -2;
623 }
624 const int bins = n_fft / 2 + 1;
625 const double mel_min = audio_hz_to_mel_slaney(0.0);
626 const double mel_max = audio_hz_to_mel_slaney((double)sample_rate / 2.0);
627 for (int mel = 0; mel < n_mels; ++mel) {
628 const double left_mel =
629 mel_min + (mel_max - mel_min) * (double)mel / (double)(n_mels + 1);
630 const double center_mel =
631 mel_min + (mel_max - mel_min) * (double)(mel + 1) / (double)(n_mels + 1);
632 const double right_mel =
633 mel_min + (mel_max - mel_min) * (double)(mel + 2) / (double)(n_mels + 1);
634 const double left = audio_mel_to_hz_slaney(left_mel);
635 const double center = audio_mel_to_hz_slaney(center_mel);
636 const double right = audio_mel_to_hz_slaney(right_mel);
637 const double normalization = 2.0 / (right - left);
638 for (int bin = 0; bin < bins; ++bin) {
639 const double hz =
640 ((double)sample_rate / 2.0) * (double)bin / (double)(bins - 1);
641 const double lower = (hz - left) / (center - left);
642 const double upper = (right - hz) / (right - center);
643 const double triangle = fmax(0.0, fmin(lower, upper));
644 mel_filters[(size_t)mel * bins + bin] =
645 (float)(triangle * normalization);
646 }
647 }
648 return 0;
649}
static double audio_hz_to_mel_slaney(double hz)
static double audio_mel_to_hz_slaney(double mel)

References audio_hz_to_mel_slaney(), audio_mel_to_hz_slaney(), left, and right.

◆ audio_whisper_stft_power_reference_f32()

int audio_whisper_stft_power_reference_f32 ( const float *  samples,
int  n_samples,
float *  power,
int  n_frames 
)

Definition at line 2173 of file audio_kernels.c.

2178{
2179 if (samples == NULL || power == NULL) {
2180 return -1;
2181 }
2182 if (n_samples <= CK_AUDIO_WHISPER_N_FFT / 2 || n_frames <= 0) {
2183 return -2;
2184 }
2185 if (n_frames != n_samples / CK_AUDIO_WHISPER_HOP_LENGTH) {
2186 return -3;
2187 }
2188
2189 const int center = CK_AUDIO_WHISPER_N_FFT / 2;
2190 for (int frame = 0; frame < n_frames; ++frame) {
2191 for (int bin = 0; bin < CK_AUDIO_WHISPER_POWER_BINS; ++bin) {
2192 float real = 0.0f;
2193 float imag = 0.0f;
2194 for (int sample = 0; sample < CK_AUDIO_WHISPER_N_FFT; ++sample) {
2195 const int source = reflect_index(
2196 frame * CK_AUDIO_WHISPER_HOP_LENGTH + sample - center,
2197 n_samples);
2198 const float window = 0.5f - 0.5f * cosf(
2199 2.0f * CK_AUDIO_PI_F * (float)sample /
2200 (float)CK_AUDIO_WHISPER_N_FFT);
2201 const float value = samples[source] * window;
2202 const float angle = -2.0f * CK_AUDIO_PI_F *
2203 (float)(bin * sample) / (float)CK_AUDIO_WHISPER_N_FFT;
2204 real = fmaf(value, cosf(angle), real);
2205 imag = fmaf(value, sinf(angle), imag);
2206 }
2207 power[(size_t)frame * CK_AUDIO_WHISPER_POWER_BINS + bin] =
2208 fmaf(real, real, imag * imag);
2209 }
2210 }
2211 return 0;
2212}

References CK_AUDIO_PI_F, CK_AUDIO_WHISPER_HOP_LENGTH, CK_AUDIO_WHISPER_N_FFT, CK_AUDIO_WHISPER_POWER_BINS, and reflect_index().

Referenced by audio_whisper_log_mel_reference_f32().