← Back to C-Kernel-Engine Docs Doxygen Source Documentation
 
Loading...
Searching...
No Matches
audio_istft_mag_phase.c File Reference
#include "ckernel_tts.h"
#include <math.h>
#include <stdint.h>
#include <string.h>

Go to the source code of this file.

Functions

static int add_size (size_t a, size_t b, size_t *out)
 
int audio_istft_mag_phase_f32 (const float *magnitude, const float *phase, size_t spectral_elements, size_t frames, size_t n_fft, size_t hop, float *output, size_t output_capacity, float *scratch, size_t scratch_elements)
 
int audio_istft_mag_phase_plan_f32 (size_t frames, size_t n_fft, size_t hop, size_t *spectral_elements, size_t *output_samples, size_t *scratch_elements)
 
static int mul_size (size_t a, size_t b, size_t *out)
 

Function Documentation

◆ add_size()

static int add_size ( size_t  a,
size_t  b,
size_t *  out 
)
static

Definition at line 7 of file audio_istft_mag_phase.c.

7 {
8 if (b > SIZE_MAX - a) return 0;
9 *out = a + b;
10 return 1;
11}

Referenced by audio_istft_mag_phase_plan_f32().

◆ audio_istft_mag_phase_f32()

int audio_istft_mag_phase_f32 ( const float *  magnitude,
const float *  phase,
size_t  spectral_elements,
size_t  frames,
size_t  n_fft,
size_t  hop,
float *  output,
size_t  output_capacity,
float *  scratch,
size_t  scratch_elements 
)

Definition at line 50 of file audio_istft_mag_phase.c.

60 {
61 if (!magnitude || !phase || !output || !scratch)
63 size_t required_spectrum, output_samples, required_scratch;
65 frames, n_fft, hop, &required_spectrum, &output_samples,
66 &required_scratch);
67 if (status != CK_AUDIO_EXTENT_OK) return status;
68 if (spectral_elements < required_spectrum ||
69 output_capacity < output_samples ||
70 scratch_elements < required_scratch) return CK_AUDIO_EXTENT_LIMIT;
71 for (size_t i = 0; i < required_spectrum; ++i) {
72 if (!isfinite(magnitude[i]) || !isfinite(phase[i]) || magnitude[i] < 0.0f)
74 }
75
76 const size_t padded_samples = output_samples + n_fft;
77 float *overlap = scratch;
78 float *window_sum = overlap + padded_samples;
79 float *window = window_sum + padded_samples;
80 memset(overlap, 0, padded_samples * sizeof(float));
81 memset(window_sum, 0, padded_samples * sizeof(float));
82 const float tau = 6.2831853071795864769f;
83 for (size_t n = 0; n < n_fft; ++n)
84 window[n] = 0.5f - 0.5f * cosf(tau * (float)n / (float)n_fft);
85
86 const size_t bins = n_fft / 2 + 1;
87 const float inverse_n = 1.0f / (float)n_fft;
88 for (size_t frame = 0; frame < frames; ++frame) {
89 const size_t base = frame * bins;
90 const size_t offset = frame * hop;
91 for (size_t n = 0; n < n_fft; ++n) {
92 float acc = magnitude[base] * cosf(phase[base]);
93 const size_t nyquist = bins - 1;
94 float end = magnitude[base + nyquist] * cosf(phase[base + nyquist]);
95 acc += (n & 1) ? -end : end;
96 for (size_t k = 1; k < nyquist; ++k) {
97 const float real = magnitude[base + k] * cosf(phase[base + k]);
98 const float imag = magnitude[base + k] * sinf(phase[base + k]);
99 const float angle = tau * (float)k * (float)n / (float)n_fft;
100 acc += 2.0f * (real * cosf(angle) - imag * sinf(angle));
101 }
102 const float w = window[n];
103 overlap[offset + n] += acc * inverse_n * w;
104 window_sum[offset + n] += w * w;
105 }
106 }
107
108 const size_t left_trim = n_fft / 2;
109 for (size_t i = 0; i < output_samples; ++i) {
110 const size_t pos = left_trim + i;
111 const float norm = window_sum[pos];
112 if (!(norm > 1e-11f)) return CK_AUDIO_EXTENT_INVALID;
113 if (!isfinite(overlap[pos] / norm)) return CK_AUDIO_EXTENT_INVALID;
114 }
115 for (size_t i = 0; i < output_samples; ++i) {
116 const size_t pos = left_trim + i;
117 output[i] = overlap[pos] / window_sum[pos];
118 }
119 return CK_AUDIO_EXTENT_OK;
120}
int audio_istft_mag_phase_plan_f32(size_t frames, size_t n_fft, size_t hop, size_t *spectral_elements, size_t *output_samples, size_t *scratch_elements)
@ CK_AUDIO_EXTENT_INVALID
Definition ckernel_tts.h:42
@ CK_AUDIO_EXTENT_LIMIT
Definition ckernel_tts.h:43
@ CK_AUDIO_EXTENT_OK
Definition ckernel_tts.h:41
uint32_t end
Definition utf8.c:215

References audio_istft_mag_phase_plan_f32(), CK_AUDIO_EXTENT_INVALID, CK_AUDIO_EXTENT_LIMIT, CK_AUDIO_EXTENT_OK, and end.

◆ audio_istft_mag_phase_plan_f32()

int audio_istft_mag_phase_plan_f32 ( size_t  frames,
size_t  n_fft,
size_t  hop,
size_t *  spectral_elements,
size_t *  output_samples,
size_t *  scratch_elements 
)

Definition at line 19 of file audio_istft_mag_phase.c.

25 {
26 if (!spectral_elements || !output_samples || !scratch_elements ||
27 frames < 2 || n_fft < 2 || (n_fft & 1) || !hop || hop > n_fft / 2) {
29 }
30 size_t bins = n_fft / 2 + 1;
31 size_t spectrum, output, padded, scratch;
32 if (!mul_size(frames, bins, &spectrum) ||
33 !mul_size(frames - 1, hop, &output) ||
34 !add_size(output, n_fft, &padded) ||
35 !mul_size(padded, 2, &scratch) ||
36 !add_size(scratch, n_fft, &scratch)) {
38 }
39 if (spectrum > SIZE_MAX / sizeof(float) ||
40 output > SIZE_MAX / sizeof(float) ||
41 scratch > SIZE_MAX / sizeof(float)) {
43 }
44 *spectral_elements = spectrum;
45 *output_samples = output;
46 *scratch_elements = scratch;
47 return CK_AUDIO_EXTENT_OK;
48}
static int mul_size(size_t a, size_t b, size_t *out)
static int add_size(size_t a, size_t b, size_t *out)
@ CK_AUDIO_EXTENT_OVERFLOW
Definition ckernel_tts.h:44

References add_size(), CK_AUDIO_EXTENT_INVALID, CK_AUDIO_EXTENT_OK, CK_AUDIO_EXTENT_OVERFLOW, and mul_size().

Referenced by audio_istft_mag_phase_f32().

◆ mul_size()

static int mul_size ( size_t  a,
size_t  b,
size_t *  out 
)
static

Definition at line 13 of file audio_istft_mag_phase.c.

13 {
14 if (a && b > SIZE_MAX / a) return 0;
15 *out = a * b;
16 return 1;
17}

Referenced by audio_istft_mag_phase_plan_f32().