23 size_t *spectral_elements,
24 size_t *output_samples,
25 size_t *scratch_elements) {
26 if (!spectral_elements || !output_samples || !scratch_elements ||
27 frames < 2 || n_fft < 2 || (n_fft & 1) || !hop || hop > n_fft / 2) {
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) ||
36 !
add_size(scratch, n_fft, &scratch)) {
39 if (spectrum > SIZE_MAX /
sizeof(
float) ||
40 output > SIZE_MAX /
sizeof(
float) ||
41 scratch > SIZE_MAX /
sizeof(
float)) {
44 *spectral_elements = spectrum;
45 *output_samples = output;
46 *scratch_elements = scratch;
51 const float *magnitude,
53 size_t spectral_elements,
58 size_t output_capacity,
60 size_t scratch_elements) {
61 if (!magnitude || !phase || !output || !scratch)
63 size_t required_spectrum, output_samples, required_scratch;
65 frames, n_fft, hop, &required_spectrum, &output_samples,
68 if (spectral_elements < required_spectrum ||
69 output_capacity < output_samples ||
71 for (
size_t i = 0; i < required_spectrum; ++i) {
72 if (!isfinite(magnitude[i]) || !isfinite(phase[i]) || magnitude[i] < 0.0f)
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);
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));
102 const float w = window[n];
103 overlap[offset + n] += acc * inverse_n * w;
104 window_sum[offset + n] += w * w;
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];
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];
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)