← 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_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_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_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_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_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_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_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_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 902 of file audio_kernels.c.

914{
915 if (input == NULL || weight == NULL || output == NULL) {
916 return -1;
917 }
918 if (input_channels <= 0 || output_channels <= 0 || input_frames <= 0 ||
919 kernel_size <= 0 || stride <= 0 || padding < 0 || output_frames <= 0) {
920 return -2;
921 }
922 const int expected = (input_frames + 2 * padding - kernel_size) / stride + 1;
923 if (output_frames != expected) {
924 return -3;
925 }
926 const char *disable_stride2 =
927 getenv("CK_DISABLE_AUDIO_CONV_STRIDE2_CONTIGUOUS");
928 ck_audio_conv1d_f32_args_t args = {
929 .input = input,
930 .weight = weight,
931 .bias = bias,
932 .output = output,
933 .input_channels = input_channels,
934 .output_channels = output_channels,
935 .input_frames = input_frames,
936 .kernel_size = kernel_size,
937 .stride = stride,
938 .padding = padding,
939 .output_frames = output_frames,
940 .use_stride2_contiguous = !(
941 disable_stride2 && disable_stride2[0] &&
942 strcmp(disable_stride2, "0") != 0),
943 };
944 ck_threadpool_t *pool = ck_threadpool_global();
945 int active = pool ? ck_threadpool_n_threads(pool) : 1;
946 if (active > output_channels) active = output_channels;
947 if (pool != NULL && active > 1) {
949 pool, active, ck_audio_conv1d_channel_major_f32_work, &args);
950 } else {
952 }
953 return 0;
954}
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)
ck_threadpool_t * ck_threadpool_global(void)
int ck_threadpool_n_threads(const ck_threadpool_t *pool)

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

◆ 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 1025 of file audio_kernels.c.

1043{
1044 if (input == NULL || weight == NULL || output == NULL) {
1045 return -1;
1046 }
1047 if (input_width <= 0 || input_height <= 0 || input_channels <= 0 ||
1048 output_channels <= 0 || kernel_width <= 0 || kernel_height <= 0 ||
1049 stride_width <= 0 || stride_height <= 0 || padding_width < 0 ||
1050 padding_height < 0 || groups <= 0 || output_width <= 0 ||
1051 output_height <= 0 || input_channels % groups != 0 ||
1052 output_channels % groups != 0) {
1053 return -2;
1054 }
1055 const int expected_width =
1056 (input_width + 2 * padding_width - kernel_width) / stride_width + 1;
1057 const int expected_height =
1058 (input_height + 2 * padding_height - kernel_height) / stride_height + 1;
1059 if (output_width != expected_width || output_height != expected_height) {
1060 return -3;
1061 }
1062 ck_audio_conv2d_whc_f32_args_t args = {
1063 .input = input,
1064 .weight = weight,
1065 .bias = bias,
1066 .output = output,
1067 .input_width = input_width,
1068 .input_height = input_height,
1069 .input_channels = input_channels,
1070 .output_channels = output_channels,
1071 .kernel_width = kernel_width,
1072 .kernel_height = kernel_height,
1073 .stride_width = stride_width,
1074 .stride_height = stride_height,
1075 .padding_width = padding_width,
1076 .padding_height = padding_height,
1077 .groups = groups,
1078 .output_width = output_width,
1079 .output_height = output_height,
1080 };
1081 const int output_elements = output_channels * output_height * output_width;
1082 ck_threadpool_t *pool = ck_threadpool_global();
1083 int active = pool ? ck_threadpool_n_threads(pool) : 1;
1084 if (active > output_elements) {
1085 active = output_elements;
1086 }
1087 if (pool != NULL && active > 1) {
1088 const int grain = output_width > 0 ? output_width : 1;
1090 pool, active, 0, output_elements, grain,
1092 } else {
1093 ck_audio_conv2d_whc_grouped_f32_range(0, output_elements, &args);
1094 }
1095 return 0;
1096}
static void ck_audio_conv2d_whc_grouped_f32_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)

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

◆ 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 328 of file audio_kernels.c.

334{
335 if (input == NULL || output == NULL) {
336 return -1;
337 }
338 if (channels <= 0 || frames <= 0 || !isfinite(epsilon) || epsilon < 0.0f) {
339 return -2;
340 }
341 const int denominator = frames > 1 ? frames - 1 : 1;
342 for (int channel = 0; channel < channels; ++channel) {
343 double sum = 0.0;
344 double sum_squared_difference = 0.0;
345 for (int frame = 0; frame < frames; ++frame) {
346 sum += (double)input[(size_t)frame * channels + channel];
347 }
348 const double mean = sum / (double)frames;
349 for (int frame = 0; frame < frames; ++frame) {
350 const double difference =
351 (double)input[(size_t)frame * channels + channel] - mean;
352 sum_squared_difference += difference * difference;
353 }
354 float standard_deviation = sqrtf(
355 (float)(sum_squared_difference / (double)denominator));
356 if (isnan(standard_deviation)) {
357 standard_deviation = 0.0f;
358 }
359 const float inverse_standard_deviation =
360 1.0f / (standard_deviation + epsilon);
361 for (int frame = 0; frame < frames; ++frame) {
362 const size_t index = (size_t)frame * channels + channel;
363 output[index] = (float)((double)input[index] - mean) *
364 inverse_standard_deviation;
365 }
366 }
367 return 0;
368}

◆ 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 1115 of file audio_kernels.c.

1120{
1121 if (input == NULL || output == NULL) {
1122 return -1;
1123 }
1124 if (channels <= 0 || frames <= 0) {
1125 return -2;
1126 }
1127 const int elements = channels * frames;
1128 ck_audio_glu_split_f32_args_t args = {
1129 .value = input,
1130 .gate = input + elements,
1131 .output = output,
1132 };
1133 ck_threadpool_t *pool = ck_threadpool_global();
1134 int active = pool ? ck_threadpool_n_threads(pool) : 1;
1135 if (active > elements) {
1136 active = elements;
1137 }
1138 if (pool != NULL && active > 1) {
1140 pool, active, 0, elements, 256,
1142 } else {
1143 ck_audio_glu_split_f32_range(0, elements, &args);
1144 }
1145 return 0;
1146}
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().

◆ 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 553 of file audio_kernels.c.

561{
562 if (power == NULL || mel_filters == NULL || log_mel == NULL) {
563 return -1;
564 }
565 if (frames <= 0 || bins <= 0 || channels <= 0 || epsilon <= 0.0f) {
566 return -2;
567 }
568 for (int frame = 0; frame < frames; ++frame) {
569 const float *spectrum = power + (size_t)frame * bins;
570 float *output = log_mel + (size_t)frame * channels;
571 for (int channel = 0; channel < channels; ++channel) {
572 const float *filter = mel_filters + (size_t)channel * bins;
573 float sum = 0.0f;
574 for (int bin = 0; bin < bins; ++bin) {
575 sum = fmaf(spectrum[bin], filter[bin], sum);
576 }
577 output[channel] = logf(sum + epsilon);
578 }
579 }
580 return 0;
581}

◆ 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 280 of file audio_kernels.c.

285{
286 if (input == NULL || output == NULL) {
287 return -1;
288 }
289 if (input_frames <= 0 || output_frames <= 0) {
290 return -2;
291 }
292 const int copied = input_frames < output_frames ? input_frames : output_frames;
293 memmove(output, input, (size_t)copied * sizeof(float));
294 if (copied < output_frames) {
295 memset(
296 output + copied,
297 0,
298 (size_t)(output_frames - copied) * sizeof(float));
299 }
300 return copied;
301}

◆ 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 176 of file audio_kernels.c.

181{
182 if (interleaved == NULL || mono == NULL) {
183 return -1;
184 }
185 if (n_frames <= 0 || n_channels <= 0) {
186 return -2;
187 }
188 const float scale = 1.0f / 32768.0f;
189 for (int frame = 0; frame < n_frames; ++frame) {
190 float sum = 0.0f;
191 for (int channel = 0; channel < n_channels; ++channel) {
192 sum += (float)interleaved[(size_t)frame * n_channels + channel];
193 }
194 mono[frame] = (sum / (float)n_channels) * scale;
195 }
196 return 0;
197}

◆ audio_preemphasis_f32()

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

Definition at line 303 of file audio_kernels.c.

308{
309 if (input == NULL || output == NULL) {
310 return -1;
311 }
312 if (frames <= 0 || !isfinite(coefficient)) {
313 return -2;
314 }
315 if (input == output) {
316 for (int frame = frames - 1; frame > 0; --frame) {
317 output[frame] = input[frame] - coefficient * input[frame - 1];
318 }
319 } else {
320 output[0] = input[0];
321 for (int frame = 1; frame < frames; ++frame) {
322 output[frame] = input[frame] - coefficient * input[frame - 1];
323 }
324 }
325 return 0;
326}

◆ audio_relative_shift_f32()

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

Definition at line 1173 of file audio_kernels.c.

1178{
1179 if (raw_scores == NULL || scores == NULL) {
1180 return -1;
1181 }
1182 if (heads <= 0 || query_frames <= 0) {
1183 return -2;
1184 }
1185 const int rows = heads * query_frames;
1186 ck_audio_relative_shift_f32_args_t args = {
1187 .raw_scores = raw_scores,
1188 .scores = scores,
1189 .query_frames = query_frames,
1190 .raw_key_frames = 2 * query_frames - 1,
1191 };
1192 ck_threadpool_t *pool = ck_threadpool_global();
1193 int active = pool ? ck_threadpool_n_threads(pool) : 1;
1194 if (active > rows) {
1195 active = rows;
1196 }
1197 if (pool != NULL && active > 1) {
1199 pool, active, 0, rows, 1,
1201 } else {
1202 ck_audio_relative_shift_f32_range(0, rows, &args);
1203 }
1204 return 0;
1205}
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_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 210 of file audio_kernels.c.

217{
218 if (input == NULL || output == NULL) {
219 return -1;
220 }
221 const int expected = audio_resampled_frame_count(input_frames, input_rate, output_rate);
222 if (expected <= 0 || output_frames != expected) {
223 return -2;
224 }
225 for (int frame = 0; frame < output_frames; ++frame) {
226 const long long numerator = (long long)frame * input_rate;
227 const int left = (int)(numerator / output_rate);
228 const int right = left + 1 < input_frames ? left + 1 : left;
229 const float fraction = (float)(numerator % output_rate) / (float)output_rate;
230 output[frame] = fmaf(input[right] - input[left], fraction, input[left]);
231 }
232 return 0;
233}
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 235 of file audio_kernels.c.

243{
244 if (input == NULL || output == NULL) {
245 return -1;
246 }
247 const int expected = audio_resampled_frame_count(input_frames, input_rate, output_rate);
248 if (expected <= 0 || output_frames != expected || radius < 2 || radius > 128) {
249 return -2;
250 }
251 const double ratio = (double)output_rate / (double)input_rate;
252 const double cutoff = ratio < 1.0 ? ratio : 1.0;
253 for (int frame = 0; frame < output_frames; ++frame) {
254 const double source = (double)frame * (double)input_rate / (double)output_rate;
255 const int center = (int)floor(source);
256 double weighted = 0.0;
257 double weight_sum = 0.0;
258 for (int tap = center - radius + 1; tap <= center + radius; ++tap) {
259 if (tap < 0 || tap >= input_frames) {
260 continue;
261 }
262 const double distance = source - (double)tap;
263 const double scaled = cutoff * distance;
264 const double sinc = fabs(scaled) < 1.0e-12 ? 1.0 :
265 sin(CK_AUDIO_PI_D * scaled) / (CK_AUDIO_PI_D * scaled);
266 const double window_x = distance / (double)radius;
267 if (fabs(window_x) >= 1.0) {
268 continue;
269 }
270 const double window = 0.5 * (1.0 + cos(CK_AUDIO_PI_D * window_x));
271 const double weight = cutoff * sinc * window;
272 weighted += (double)input[tap] * weight;
273 weight_sum += weight;
274 }
275 output[frame] = weight_sum != 0.0 ? (float)(weighted / weight_sum) : 0.0f;
276 }
277 return 0;
278}
#define CK_AUDIO_PI_D

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 199 of file audio_kernels.c.

203{
204 if (input_frames <= 0 || input_rate <= 0 || output_rate <= 0) {
205 return -1;
206 }
207 return 1 + (int)(((long long)(input_frames - 1) * output_rate) / input_rate);
208}

Referenced by audio_resample_linear_f32(), and audio_resample_windowed_sinc_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 498 of file audio_kernels.c.

510{
511 if (samples == NULL || window == NULL || cos_table == NULL ||
512 sin_table == NULL || power == NULL) {
513 return -1;
514 }
515 if (n_samples <= 0 || window_length <= 0 || n_fft <= 0 ||
516 window_length > n_fft || (n_fft & 1) != 0 || hop_length <= 0 ||
517 n_frames <= 0 || (reflect_padding != 0 && reflect_padding != 1)) {
518 return -2;
519 }
520 if (n_frames != n_samples / hop_length + 1) {
521 return -3;
522 }
523
524 const int bins = n_fft / 2 + 1;
525 const int center = n_fft / 2;
526 const int window_start = (n_fft - window_length) / 2;
527 for (int frame = 0; frame < n_frames; ++frame) {
528 for (int bin = 0; bin < bins; ++bin) {
529 const float *cos_row = cos_table + (size_t)bin * n_fft;
530 const float *sin_row = sin_table + (size_t)bin * n_fft;
531 float real = 0.0f;
532 float imag = 0.0f;
533 for (int sample = 0; sample < window_length; ++sample) {
534 const int fft_sample = window_start + sample;
535 int source = frame * hop_length + fft_sample - center;
536 if (source < 0 || source >= n_samples) {
537 if (!reflect_padding) {
538 continue;
539 }
540 source = reflect_index(source, n_samples);
541 }
542 const float value = samples[source] * window[sample];
543 real = fmaf(value, cos_row[fft_sample], real);
544 imag = fmaf(value, sin_row[fft_sample], imag);
545 }
546 power[(size_t)frame * bins + bin] =
547 fmaf(real, real, imag * imag);
548 }
549 }
550 return 0;
551}
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 593 of file audio_kernels.c.

603{
604 const int n_fft = CK_AUDIO_WHISPER_N_FFT;
605 if (samples == NULL || window == NULL || cos_table == NULL ||
606 sin_table == NULL || power == NULL || fft_scratch == NULL) {
607 return -1;
608 }
609 if (hop_length != CK_AUDIO_WHISPER_HOP_LENGTH ||
610 n_samples <= n_fft / 2 || n_frames <= 0 ||
611 n_frames != n_samples / hop_length) {
612 return -2;
613 }
614 for (int frame = 0; frame < n_frames; ++frame) {
616 samples,
617 n_samples,
618 frame,
619 window,
620 cos_table,
621 sin_table,
622 power + (size_t)frame * CK_AUDIO_WHISPER_POWER_BINS,
623 fft_scratch);
624 }
625 return 0;
626}
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 454 of file audio_kernels.c.

464{
465 if (samples == NULL || window == NULL || cos_table == NULL ||
466 sin_table == NULL || power == NULL) {
467 return -1;
468 }
469 if (n_fft <= 0 || hop_length <= 0 || n_samples <= n_fft / 2 ||
470 (n_fft & 1) != 0 || n_frames <= 0) {
471 return -2;
472 }
473 if (n_frames != n_samples / hop_length) {
474 return -3;
475 }
476 const int bins = n_fft / 2 + 1;
477 const int center = n_fft / 2;
478 for (int frame = 0; frame < n_frames; ++frame) {
479 for (int bin = 0; bin < bins; ++bin) {
480 const float *cos_row = cos_table + (size_t)bin * n_fft;
481 const float *sin_row = sin_table + (size_t)bin * n_fft;
482 float real = 0.0f;
483 float imag = 0.0f;
484 for (int sample = 0; sample < n_fft; ++sample) {
485 const int source = reflect_index(
486 frame * hop_length + sample - center, n_samples);
487 const float value = samples[source] * window[sample];
488 real = fmaf(value, cos_row[sample], real);
489 imag = fmaf(value, sin_row[sample], imag);
490 }
491 power[(size_t)frame * bins + bin] =
492 fmaf(real, real, imag * imag);
493 }
494 }
495 return 0;
496}

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 370 of file audio_kernels.c.

375{
376 if (window == NULL || cos_table == NULL || sin_table == NULL) {
377 return -1;
378 }
379 if (n_fft <= 0 || (n_fft & 1) != 0) {
380 return -2;
381 }
382 const int bins = n_fft / 2 + 1;
383 for (int sample = 0; sample < n_fft; ++sample) {
384 window[sample] = 0.5f - 0.5f * cosf(
385 2.0f * CK_AUDIO_PI_F * (float)sample / (float)n_fft);
386 }
387 for (int bin = 0; bin < bins; ++bin) {
388 for (int sample = 0; sample < n_fft; ++sample) {
389 const float angle = -2.0f * CK_AUDIO_PI_F *
390 (float)(bin * sample) / (float)n_fft;
391 const size_t index = (size_t)bin * n_fft + sample;
392 cos_table[index] = cosf(angle);
393 sin_table[index] = sinf(angle);
394 }
395 }
396 return 0;
397}
#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 1207 of file audio_kernels.c.

1212{
1213 if (input == NULL || output == NULL) {
1214 return -1;
1215 }
1216 if (channels <= 0 || frames <= 0) {
1217 return -2;
1218 }
1219 for (int frame = 0; frame < frames; ++frame) {
1220 for (int channel = 0; channel < channels; ++channel) {
1221 output[(size_t)frame * channels + channel] =
1222 input[(size_t)channel * frames + frame];
1223 }
1224 }
1225 return 0;
1226}

◆ 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 133 of file audio_kernels.c.

139{
141 bytes, byte_count, 0, mono, mono_capacity, info);
142}
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 144 of file audio_kernels.c.

151{
152 const int status = audio_wav_parse_memory(bytes, byte_count, info);
153 if (status != 0) {
154 return status;
155 }
156 if (start_frame < 0 || start_frame >= info->frames || mono_capacity <= 0) {
157 return -7;
158 }
159 const int available = info->frames - start_frame;
160 const int decoded = available < mono_capacity ? available : mono_capacity;
161 const uint8_t *pcm = bytes + info->data_offset;
162 const float scale = 1.0f / 32768.0f;
163 for (int frame = 0; frame < decoded; ++frame) {
164 float sum = 0.0f;
165 const size_t source_frame = (size_t)start_frame + (size_t)frame;
166 for (int channel = 0; channel < info->channels; ++channel) {
167 const size_t index =
168 (source_frame * (size_t)info->channels + (size_t)channel) * 2u;
169 sum += (float)(int16_t)read_u16_le(pcm + index);
170 }
171 mono[frame] = (sum / (float)info->channels) * scale;
172 }
173 return decoded;
174}
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 105 of file audio_kernels.c.

111{
112 if (bytes == NULL || info == NULL || mono == NULL) {
113 return -1;
114 }
115 if (info->format_tag != 1 || info->bits_per_sample != 16 ||
116 info->channels <= 0 || info->frames <= 0 || mono_capacity < info->frames ||
117 info->data_offset > byte_count || info->data_bytes > byte_count - info->data_offset) {
118 return -2;
119 }
120 const uint8_t *pcm = bytes + info->data_offset;
121 const float scale = 1.0f / 32768.0f;
122 for (int frame = 0; frame < info->frames; ++frame) {
123 float sum = 0.0f;
124 for (int channel = 0; channel < info->channels; ++channel) {
125 const size_t index = ((size_t)frame * info->channels + channel) * 2u;
126 sum += (float)(int16_t)read_u16_le(pcm + index);
127 }
128 mono[frame] = (sum / (float)info->channels) * scale;
129 }
130 return info->frames;
131}

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 44 of file audio_kernels.c.

48{
49 if (bytes == NULL || info == NULL) {
50 return -1;
51 }
52 if (byte_count < 12 || memcmp(bytes, "RIFF", 4) != 0 ||
53 memcmp(bytes + 8, "WAVE", 4) != 0) {
54 return -2;
55 }
56 const size_t riff_end = (size_t)read_u32_le(bytes + 4) + 8u;
57 if (riff_end < 12 || riff_end > byte_count) {
58 return -3;
59 }
60 memset(info, 0, sizeof(*info));
61 int found_format = 0;
62 int found_data = 0;
63 size_t offset = 12;
64 while (offset + 8 <= riff_end) {
65 const uint8_t *chunk = bytes + offset;
66 const uint32_t chunk_bytes = read_u32_le(chunk + 4);
67 const size_t payload = offset + 8;
68 if ((size_t)chunk_bytes > riff_end - payload) {
69 return -3;
70 }
71 if (!found_format && memcmp(chunk, "fmt ", 4) == 0) {
72 if (chunk_bytes < 16) {
73 return -4;
74 }
75 info->format_tag = (int)read_u16_le(bytes + payload);
76 info->channels = (int)read_u16_le(bytes + payload + 2);
77 info->sample_rate = (int)read_u32_le(bytes + payload + 4);
78 info->bits_per_sample = (int)read_u16_le(bytes + payload + 14);
79 found_format = 1;
80 } else if (!found_data && memcmp(chunk, "data", 4) == 0) {
81 info->data_offset = payload;
82 info->data_bytes = chunk_bytes;
83 found_data = 1;
84 }
85 const size_t padded = (size_t)chunk_bytes + ((size_t)chunk_bytes & 1u);
86 if (padded > SIZE_MAX - payload) {
87 return -3;
88 }
89 offset = payload + padded;
90 }
91 if (!found_format || !found_data || info->format_tag != 1 ||
92 info->channels <= 0 || info->sample_rate <= 0 ||
93 info->bits_per_sample != 16) {
94 return -5;
95 }
96 const size_t bytes_per_frame = (size_t)info->channels * 2u;
97 if (bytes_per_frame == 0 || info->data_bytes % bytes_per_frame != 0 ||
98 info->data_bytes / bytes_per_frame > (size_t)INT_MAX) {
99 return -6;
100 }
101 info->frames = (int)(info->data_bytes / bytes_per_frame);
102 return info->frames > 0 ? 0 : -6;
103}
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 1269 of file audio_kernels.c.

1275{
1276 if (power == NULL || mel_filters == NULL || log_mel == NULL) {
1277 return -1;
1278 }
1279 if (n_mels <= 0 || n_frames <= 0) {
1280 return -2;
1281 }
1282
1283 float maximum = -INFINITY;
1284 for (int mel = 0; mel < n_mels; ++mel) {
1285 const float *filter = mel_filters + (size_t)mel * CK_AUDIO_WHISPER_POWER_BINS;
1286 float *output = log_mel + (size_t)mel * n_frames;
1287 for (int frame = 0; frame < n_frames; ++frame) {
1288 const float *spectrum = power + (size_t)frame * CK_AUDIO_WHISPER_POWER_BINS;
1289 float sum = 0.0f;
1290 for (int bin = 0; bin < CK_AUDIO_WHISPER_POWER_BINS; ++bin) {
1291 sum = fmaf(filter[bin], spectrum[bin], sum);
1292 }
1293 const float value = log10f(fmaxf(sum, 1.0e-10f));
1294 output[frame] = value;
1295 maximum = fmaxf(maximum, value);
1296 }
1297 }
1298
1299 const float floor = maximum - 8.0f;
1300 for (int mel = 0; mel < n_mels; ++mel) {
1301 float *output = log_mel + (size_t)mel * n_frames;
1302 for (int frame = 0; frame < n_frames; ++frame) {
1303 output[frame] = (fmaxf(output[frame], floor) + 4.0f) / 4.0f;
1304 }
1305 }
1306 return 0;
1307}

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 1309 of file audio_kernels.c.

1317{
1318 const int stft_status = audio_whisper_stft_power_reference_f32(
1319 samples, n_samples, power_scratch, n_frames);
1320 if (stft_status != 0) {
1321 return stft_status;
1322 }
1324 power_scratch, mel_filters, n_mels, n_frames, log_mel);
1325}
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 681 of file audio_kernels.c.

693{
694 if (bytes == NULL || window == NULL || cos_table == NULL ||
695 sin_table == NULL || mel_filters == NULL || log_mel == NULL) {
696 return -1;
697 }
698 CKAudioWavInfo info;
699 if (audio_wav_parse_memory(bytes, byte_count, &info) != 0 ||
700 info.sample_rate != target_sample_rate ||
701 target_sample_rate != CK_AUDIO_WHISPER_SAMPLE_RATE ||
702 start_frame < 0 ||
703 start_frame % CK_AUDIO_WHISPER_HOP_LENGTH != 0 ||
704 n_mels <= 0 || output_frames <= 0) {
705 return -2;
706 }
707 float *samples = (float *)malloc((size_t)info.frames * sizeof(float));
708 if (samples == NULL) {
709 return -3;
710 }
711 const int decoded = audio_wav_decode_pcm16_mono_f32(
712 bytes, byte_count, &info, samples, info.frames);
713 if (decoded != info.frames) {
714 free(samples);
715 return -4;
716 }
717
718 memset(
719 log_mel,
720 0,
721 (size_t)n_mels * (size_t)output_frames * sizeof(float));
722 const int global_frames = info.frames / CK_AUDIO_WHISPER_HOP_LENGTH;
723 const int start_feature = start_frame / CK_AUDIO_WHISPER_HOP_LENGTH;
724 float maximum = -INFINITY;
725 float power[CK_AUDIO_WHISPER_POWER_BINS];
726 float fft_scratch[2 * CK_AUDIO_WHISPER_N_FFT];
727 for (int frame = 0; frame < global_frames; ++frame) {
729 samples,
730 info.frames,
731 frame,
732 window,
733 cos_table,
734 sin_table,
735 power,
736 fft_scratch);
737 for (int mel = 0; mel < n_mels; ++mel) {
738 const float *filter =
739 mel_filters + (size_t)mel * CK_AUDIO_WHISPER_POWER_BINS;
740 float sum = 0.0f;
741 for (int bin = 0; bin < CK_AUDIO_WHISPER_POWER_BINS; ++bin) {
742 sum = fmaf(filter[bin], power[bin], sum);
743 }
744 const float value = log10f(fmaxf(sum, 1.0e-10f));
745 maximum = fmaxf(maximum, value);
746 const int output_frame = frame - start_feature;
747 if (output_frame >= 0 && output_frame < output_frames) {
748 log_mel[(size_t)mel * output_frames + output_frame] = value;
749 }
750 }
751 }
752 free(samples);
753 if (!isfinite(maximum)) {
754 return -5;
755 }
756
757 const int available = global_frames - start_feature;
758 const int valid_frames =
759 available < output_frames ? (available > 0 ? available : 0) : output_frames;
760 const float floor = maximum - 8.0f;
761 for (int mel = 0; mel < n_mels; ++mel) {
762 float *output = log_mel + (size_t)mel * output_frames;
763 for (int frame = 0; frame < valid_frames; ++frame) {
764 output[frame] = (fmaxf(output[frame], floor) + 4.0f) / 4.0f;
765 }
766 }
767 return valid_frames;
768}
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 415 of file audio_kernels.c.

420{
421 if (mel_filters == NULL) {
422 return -1;
423 }
424 if (sample_rate <= 0 || n_fft <= 0 || (n_fft & 1) != 0 || n_mels <= 0) {
425 return -2;
426 }
427 const int bins = n_fft / 2 + 1;
428 const double mel_min = audio_hz_to_mel_slaney(0.0);
429 const double mel_max = audio_hz_to_mel_slaney((double)sample_rate / 2.0);
430 for (int mel = 0; mel < n_mels; ++mel) {
431 const double left_mel =
432 mel_min + (mel_max - mel_min) * (double)mel / (double)(n_mels + 1);
433 const double center_mel =
434 mel_min + (mel_max - mel_min) * (double)(mel + 1) / (double)(n_mels + 1);
435 const double right_mel =
436 mel_min + (mel_max - mel_min) * (double)(mel + 2) / (double)(n_mels + 1);
437 const double left = audio_mel_to_hz_slaney(left_mel);
438 const double center = audio_mel_to_hz_slaney(center_mel);
439 const double right = audio_mel_to_hz_slaney(right_mel);
440 const double normalization = 2.0 / (right - left);
441 for (int bin = 0; bin < bins; ++bin) {
442 const double hz =
443 ((double)sample_rate / 2.0) * (double)bin / (double)(bins - 1);
444 const double lower = (hz - left) / (center - left);
445 const double upper = (right - hz) / (right - center);
446 const double triangle = fmax(0.0, fmin(lower, upper));
447 mel_filters[(size_t)mel * bins + bin] =
448 (float)(triangle * normalization);
449 }
450 }
451 return 0;
452}
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 1228 of file audio_kernels.c.

1233{
1234 if (samples == NULL || power == NULL) {
1235 return -1;
1236 }
1237 if (n_samples <= CK_AUDIO_WHISPER_N_FFT / 2 || n_frames <= 0) {
1238 return -2;
1239 }
1240 if (n_frames != n_samples / CK_AUDIO_WHISPER_HOP_LENGTH) {
1241 return -3;
1242 }
1243
1244 const int center = CK_AUDIO_WHISPER_N_FFT / 2;
1245 for (int frame = 0; frame < n_frames; ++frame) {
1246 for (int bin = 0; bin < CK_AUDIO_WHISPER_POWER_BINS; ++bin) {
1247 float real = 0.0f;
1248 float imag = 0.0f;
1249 for (int sample = 0; sample < CK_AUDIO_WHISPER_N_FFT; ++sample) {
1250 const int source = reflect_index(
1251 frame * CK_AUDIO_WHISPER_HOP_LENGTH + sample - center,
1252 n_samples);
1253 const float window = 0.5f - 0.5f * cosf(
1254 2.0f * CK_AUDIO_PI_F * (float)sample /
1255 (float)CK_AUDIO_WHISPER_N_FFT);
1256 const float value = samples[source] * window;
1257 const float angle = -2.0f * CK_AUDIO_PI_F *
1258 (float)(bin * sample) / (float)CK_AUDIO_WHISPER_N_FFT;
1259 real = fmaf(value, cosf(angle), real);
1260 imag = fmaf(value, sinf(angle), imag);
1261 }
1262 power[(size_t)frame * CK_AUDIO_WHISPER_POWER_BINS + bin] =
1263 fmaf(real, real, imag * imag);
1264 }
1265 }
1266 return 0;
1267}

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().