void irmeasure_process(t_irmeasure *x, t_symbol *sym, short argc, t_atom *argv) { FFT_SETUP_D fft_setup; FFT_SPLIT_COMPLEX_D spectrum_1; FFT_SPLIT_COMPLEX_D spectrum_2; FFT_SPLIT_COMPLEX_D spectrum_3; void *measurement_rec; void *rec_mem; double *excitation_sig; double *out_buf; double *out_mem; float *filter_in; t_symbol *filter = filter_retriever(x->deconvolve_filter_specifier); double filter_specifier[HIRT_MAX_SPECIFIER_ITEMS]; double range_specifier[HIRT_MAX_SPECIFIER_ITEMS]; double test_pow; double max_pow; double sample_rate = x->sample_rate; double deconvolve_phase = phase_retriever(x->deconvolve_phase); long deconvolve_mode = x->deconvolve_mode; long bandlimit = x->measure_mode == SWEEP ? x->bandlimit : 0; AH_SIntPtr rec_length = x->T2; AH_SIntPtr gen_length = 0; AH_SIntPtr filter_length = buffer_length(filter); AH_UIntPtr fft_size; AH_UIntPtr fft_size_log2; AH_UIntPtr mem_size; AH_UIntPtr i; t_ess sweep_params; t_mls max_length_params; t_noise_params noise_params; switch (x->measure_mode) { case SWEEP: ess_params(&sweep_params, x->sweep_params.rf1, x->sweep_params.rf2, x->sweep_params.fade_in, x->sweep_params.fade_out, x->sweep_params.RT, x->sweep_params.sample_rate, x->inv_amp ? x->sweep_params.amp : 1, x->amp_curve); gen_length = ess_get_length(&sweep_params); break; case MLS: mls_params(&max_length_params, x->max_length_params.order, x->inv_amp ? x->max_length_params.amp : 1); gen_length = mls_get_length(&max_length_params); break; case NOISE: coloured_noise_params(&noise_params, x->noise_params.mode, x->noise_params.fade_in, x->noise_params.fade_out, x->noise_params.RT, x->noise_params.sample_rate, x->inv_amp ? x->noise_params.amp : 1); gen_length = coloured_noise_get_length(&noise_params); break; } // Check and calculate lengths fft_size = calculate_fft_size(rec_length + gen_length, &fft_size_log2); // Allocate Temporary Memory fft_setup = hisstools_create_setup_d(fft_size_log2); excitation_sig = (double *) malloc(gen_length * sizeof(double)); spectrum_1.realp = ALIGNED_MALLOC((sizeof(double) * fft_size * 4)); spectrum_1.imagp = spectrum_1.realp + (fft_size >> 1); spectrum_2.realp = spectrum_1.imagp + (fft_size >> 1); spectrum_2.imagp = spectrum_2.realp + (fft_size >> 1); spectrum_3.realp = spectrum_2.imagp + (fft_size >> 1); spectrum_3.imagp = spectrum_3.realp + fft_size; filter_in = filter_length ? (float *) ALIGNED_MALLOC(sizeof(float) * filter_length) : 0; if (!fft_setup || !excitation_sig || !spectrum_1.realp || (filter_length && !filter_in)) { object_error ((t_object *) x, "could not allocate temporary memory for processing"); hisstools_destroy_setup_d(fft_setup); free(excitation_sig); ALIGNED_FREE(spectrum_1.realp); ALIGNED_FREE(filter_in); return; } // Allocate output memory and get record memory rec_mem = access_mem_swap(&x->rec_mem, &mem_size); out_mem = grow_mem_swap(&x->out_mem, fft_size * x->current_num_active_ins * sizeof(double), fft_size * x->current_num_active_ins); if (!out_mem) { object_error ((t_object *) x, "could not allocate memory for output storage"); free(excitation_sig); hisstools_destroy_setup_d(fft_setup); return; } // Generate Signal switch (x->measure_mode) { case SWEEP: ess_gen(&sweep_params, excitation_sig, true); break; case MLS: mls_gen(&max_length_params, excitation_sig, true); break; case NOISE: coloured_noise_gen(&noise_params, excitation_sig, true); break; } // Transform excitation signal into complex spectrum 2 time_to_halfspectrum_double(fft_setup, excitation_sig, gen_length, spectrum_2, fft_size); if (bandlimit) { // Calculate standard filter for bandlimited deconvolution (sweep * inv sweep) ess_igen(&sweep_params, excitation_sig, INVERT_ALL, true); time_to_halfspectrum_double(fft_setup, excitation_sig, gen_length, spectrum_3, fft_size); convolve(spectrum_3, spectrum_2, fft_size, SPECTRUM_REAL); // Calculate full power spectrum from half spectrum - convert filter to have the required phase power_full_spectrum_from_half_spectrum(spectrum_3, fft_size); variable_phase_from_power_spectrum(fft_setup, spectrum_3, fft_size, deconvolve_phase, true); // Convert back to real format spectrum_3.imagp[0] = spectrum_3.realp[fft_size >> 1]; } else { // Find maximum power to scale for (i = 1, max_pow = 0; i < (fft_size >> 1); i++)
void bufconvolve_process_internal (t_bufconvolve *x, t_symbol *sym, short argc, t_atom *argv) { FFT_SETUP_D fft_setup; FFT_SPLIT_COMPLEX_D spectrum_1; FFT_SPLIT_COMPLEX_D spectrum_2; FFT_SPLIT_COMPLEX_D spectrum_3; double *out_buf; float *in_temp; float *filter_in; AH_Boolean convolve_mode = sym == gensym("convolve") ? true : false; t_symbol *target = atom_getsym(argv++); t_symbol *source_1 = atom_getsym(argv++); t_symbol *source_2 = atom_getsym(argv++); t_symbol *filter = filter_retriever(x->deconvolve_filter_specifier); double filter_specifier[HIRT_MAX_SPECIFIER_ITEMS]; double range_specifier[HIRT_MAX_SPECIFIER_ITEMS]; double time_mul = atom_getfloat(argv++); double sample_rate = buffer_sample_rate(source_1); double deconvolve_phase = phase_retriever(x->deconvolve_phase); double deconvolve_delay; AH_SIntPtr source_length_1 = buffer_length(source_1); AH_SIntPtr source_length_2 = buffer_length(source_2); AH_SIntPtr filter_length = buffer_length(filter); AH_UIntPtr fft_size; AH_UIntPtr fft_size_log2; long deconvolve_mode = x->deconvolve_mode; t_buffer_write_error error; // Check input buffers if (buffer_check((t_object *) x, source_1) || buffer_check((t_object *) x, source_2)) return; // Check sample rates if (sample_rate != buffer_sample_rate(source_2)) object_warn((t_object *) x, "sample rates do not match"); // Check and calculate lengths if (convolve_mode == true) fft_size = (AH_UIntPtr) ((source_length_1 + source_length_2) * time_mul); else fft_size = (AH_UIntPtr) (source_length_1 < source_length_2 ? source_length_2 * time_mul : source_length_1 * time_mul); fft_size = calculate_fft_size(fft_size, &fft_size_log2); deconvolve_delay = delay_retriever(x->deconvolve_delay, fft_size, sample_rate); if (fft_size < 8) { object_error((t_object *) x, "input buffers are too short, or have no length"); return; } // Allocate Memory (use pointer aliasing where possible for efficiency) fft_setup = hisstools_create_setup_d(fft_size_log2); spectrum_1.realp = ALIGNED_MALLOC(sizeof(double) * fft_size * (convolve_mode == true ? 3 : 4)); spectrum_1.imagp = spectrum_1.realp + (fft_size >> 1); spectrum_2.realp = spectrum_1.imagp + (fft_size >> 1); spectrum_2.imagp = spectrum_2.realp + (fft_size >> 1); spectrum_3.realp = spectrum_2.imagp + (fft_size >> 1); spectrum_3.imagp = convolve_mode == true ? 0 : spectrum_3.realp + fft_size; filter_in = filter_length ? ALIGNED_MALLOC(sizeof(float *) * filter_length) : 0; out_buf = spectrum_2.realp; in_temp = (float *) spectrum_3.realp; // Check memory allocations if (!fft_setup || !spectrum_1.realp || (filter_length && !filter_in)) { object_error((t_object *) x, "could not allocate temporary memory for processing"); hisstools_destroy_setup_d(fft_setup); ALIGNED_FREE(spectrum_1.realp); ALIGNED_FREE(filter_in); return; } // Get inputs - convert to frequency domain buffer_read(source_1, x->read_chan - 1, in_temp, source_length_1); time_to_halfspectrum_float(fft_setup, in_temp, source_length_1, spectrum_1, fft_size); buffer_read(source_2, x->read_chan - 1, in_temp, source_length_2); time_to_halfspectrum_float(fft_setup, in_temp, source_length_2, spectrum_2, fft_size); // Do deconvolution or convolution if (convolve_mode == true) convolve(spectrum_1, spectrum_2, fft_size, SPECTRUM_REAL); else { // Fill deconvolution filter specifiers - load filter from buffer (if specified) - deconvolve fill_power_array_specifier(filter_specifier, x->deconvolve_filter_specifier, x->deconvolve_num_filter_specifiers); fill_power_array_specifier(range_specifier, x->deconvolve_range_specifier, x->deconvolve_num_range_specifiers); buffer_read(filter, 0, filter_in, fft_size); deconvolve(fft_setup, spectrum_1, spectrum_2, spectrum_3, filter_specifier, range_specifier, 0.0, filter_in, filter_length, fft_size, SPECTRUM_REAL, deconvolve_mode, deconvolve_phase, deconvolve_delay, sample_rate); } // Convert to time domain - copy out to buffer spectrum_to_time(fft_setup, out_buf, spectrum_1, fft_size, SPECTRUM_REAL); error = buffer_write(target, out_buf, (convolve_mode == true ? source_length_1 + source_length_2 - 1 : fft_size), x->write_chan - 1, x->resize, sample_rate, 1.); buffer_write_error((t_object *) x, target, error); // Free resources hisstools_destroy_setup_d(fft_setup); ALIGNED_FREE(spectrum_1.realp); ALIGNED_FREE(filter_in); if (!error) outlet_bang(x->process_done); }
void irreference_process (t_irreference *x, t_symbol *sym, short argc, t_atom *argv) { FFT_SETUP_D fft_setup; FFT_SPLIT_COMPLEX_D spectrum_1; FFT_SPLIT_COMPLEX_D spectrum_2; FFT_SPLIT_COMPLEX_D spectrum_3; FFT_SPLIT_COMPLEX_D spectrum_4; void *rec_mem1; void *rec_mem2; double *out_mem; double *out_buf; float *filter_in; t_symbol *filter = filter_retriever(x->deconvolve_filter_specifier); double filter_specifier[HIRT_MAX_SPECIFIER_ITEMS]; double range_specifier[HIRT_MAX_SPECIFIER_ITEMS]; double sample_rate = x->sample_rate; double deconvolve_phase = phase_retriever(x->deconvolve_phase); double deconvolve_delay; long deconvolve_mode = deconvolve_mode = x->deconvolve_mode; long smoothing_on = x->num_smooth; AH_SIntPtr alloc_rec_length = x->T; AH_SIntPtr rec_length = x->current_length; AH_SIntPtr filter_length = buffer_length(filter); AH_UIntPtr fft_size; AH_UIntPtr fft_size_log2; AH_UIntPtr mem_size; AH_UIntPtr i; // Sanity check if (!rec_length) return; // Check and calculate lengths fft_size = calculate_fft_size(rec_length * 2, &fft_size_log2); deconvolve_delay = delay_retriever(x->deconvolve_delay, fft_size, sample_rate); // Allocate Temporary Memory fft_setup = hisstools_create_setup_d(fft_size_log2); spectrum_1.realp = ALIGNED_MALLOC((sizeof(double) * fft_size * 4)); spectrum_1.imagp = spectrum_1.realp + (fft_size >> 1); spectrum_2.realp = spectrum_1.imagp + (fft_size >> 1); spectrum_2.imagp = spectrum_2.realp + (fft_size >> 1); spectrum_3.realp = spectrum_2.imagp + (fft_size >> 1); spectrum_3.imagp = spectrum_3.realp + fft_size; filter_in = filter_length ? ALIGNED_MALLOC(sizeof(float *) * filter_length) : 0; if (smoothing_on) { spectrum_4.realp = malloc(sizeof(double) * 2 * fft_size); spectrum_4.imagp = spectrum_4.realp + fft_size; } else spectrum_4.realp = 0; if (!fft_setup || !spectrum_1.realp || (smoothing_on && !spectrum_4.realp) || (filter_length && !filter_in)) { object_error ((t_object *) x, "could not allocate temporary memory for processing"); hisstools_destroy_setup_d(fft_setup); ALIGNED_FREE(spectrum_1.realp); ALIGNED_FREE(filter_in); free(spectrum_4.realp); return; } x->fft_size = fft_size; // Allocate output memory and get record memory rec_mem1 = access_mem_swap(&x->rec_mem, &mem_size); out_mem = grow_mem_swap(&x->out_mem, fft_size * x->current_num_active_ins * sizeof(double), fft_size); if (!out_mem) { object_error ((t_object *) x, "could not allocate memory for output storage"); free(spectrum_1.realp); hisstools_destroy_setup_d(fft_setup); return; } // Transform reference into spectrum 2 - [smooth] time_to_halfspectrum_double(fft_setup, rec_mem1, rec_length, spectrum_2, fft_size); if (smoothing_on) irreference_smooth(fft_setup, spectrum_2, spectrum_4, x->smooth_mode, fft_size, x->num_smooth > 1 ? x->smooth[0] : 0., x->num_smooth > 1 ? x->smooth[1] : x->smooth[0]); // Fill deconvolution filter specifiers - read filter from buffer (if specified) - make deconvolution filter - delay filter fill_power_array_specifier(filter_specifier, x->deconvolve_filter_specifier, x->deconvolve_num_filter_specifiers); fill_power_array_specifier(range_specifier, x->deconvolve_range_specifier, x->deconvolve_num_range_specifiers); buffer_read(filter, 0, filter_in, fft_size); make_deconvolution_filter(fft_setup, spectrum_2, spectrum_3, filter_specifier, range_specifier, 0, filter_in, filter_length, fft_size, SPECTRUM_REAL, deconvolve_mode, deconvolve_phase, sample_rate); delay_spectrum(spectrum_3, fft_size, SPECTRUM_REAL, deconvolve_delay); // Deconvolve each input for (i = 0; i < (AH_UIntPtr) x->current_num_active_ins; i++) { // Get current input and output buffers rec_mem2 = (double *) rec_mem1 + ((i + 1) * alloc_rec_length); out_buf = out_mem + (i * fft_size); // Do transform into spectrum_1 - [smooth] - deconvolve - [delay] - transform back time_to_halfspectrum_double(fft_setup, rec_mem2, rec_length, spectrum_1, fft_size); if (smoothing_on) irreference_smooth(fft_setup, spectrum_1, spectrum_4, x->smooth_mode, fft_size, x->num_smooth > 1 ? x->smooth[0] : 0., x->num_smooth > 1 ? x->smooth[1] : x->smooth[0]); deconvolve_with_filter(spectrum_1, spectrum_2, spectrum_3, fft_size, SPECTRUM_REAL); spectrum_to_time(fft_setup, out_buf, spectrum_1, fft_size, SPECTRUM_REAL); } // Free Memory hisstools_destroy_setup_d(fft_setup); ALIGNED_FREE(spectrum_1.realp); ALIGNED_FREE(filter_in); free(spectrum_4.realp); // Done outlet_bang(x->process_done); }
void irphase_process_internal (t_irphase *x, t_symbol *sym, short argc, t_atom *argv) { FFT_SETUP_D fft_setup; FFT_SPLIT_COMPLEX_D spectrum_1; FFT_SPLIT_COMPLEX_D spectrum_2; FFT_SPLIT_COMPLEX_D spectrum_3; float *in; float *filter_in; double *out_buf; t_symbol *filter = filter_retriever(x->deconvolve_filter_specifier); t_symbol *target = atom_getsym(argv++); t_symbol *source = atom_getsym(argv++); double filter_specifier[HIRT_MAX_SPECIFIER_ITEMS]; double range_specifier[HIRT_MAX_SPECIFIER_ITEMS]; double phase = atom_getfloat(argv++); double time_mul = atom_getfloat(argv++); double sample_rate = buffer_sample_rate(source); double deconvolve_delay; double deconvolve_phase; t_phase_type mode = (t_phase_type) atom_getlong(argv++); AH_UIntPtr fft_size; AH_UIntPtr fft_size_log2; AH_UIntPtr i; t_buffer_write_error error; long deconvolve_mode; // Get input buffer lengths AH_SIntPtr source_length_1 = buffer_length(source); AH_SIntPtr filter_length = buffer_length(filter); AH_SIntPtr max_length = source_length_1; // Check input buffers if (buffer_check((t_object *) x, source)) return; // Calculate fft size time_mul = time_mul == 0. ? 1 : time_mul; if (time_mul < 1) { object_warn((t_object *) x, " time multiplier cannot be less than 1 (using 1)"); time_mul = 1; } fft_size = calculate_fft_size((long) (max_length * time_mul), &fft_size_log2); if (fft_size < 8) { object_error((t_object *) x, "buffers are too short, or have no length"); return; } deconvolve_mode = x->deconvolve_mode; deconvolve_phase = phase_retriever(x->deconvolve_phase); deconvolve_delay = delay_retriever(x->deconvolve_delay, fft_size, sample_rate); // Allocate momory fft_setup = hisstools_create_setup_d(fft_size_log2); spectrum_1.realp = ALIGNED_MALLOC(sizeof(double) * fft_size * (mode == MODE_ALLPASS ? 6 : 3)); spectrum_1.imagp = spectrum_1.realp + fft_size; spectrum_2.realp = spectrum_1.imagp + fft_size; spectrum_2.imagp = mode == MODE_ALLPASS ? spectrum_2.realp + fft_size : 0; spectrum_3.realp = mode == MODE_ALLPASS ? spectrum_2.imagp + fft_size : 0; spectrum_3.imagp = mode == MODE_ALLPASS ? spectrum_3.realp + fft_size : 0; filter_in = filter_length ? ALIGNED_MALLOC(sizeof(float *) * filter_length) : 0; out_buf = mode == MODE_ALLPASS ? spectrum_3.realp : spectrum_2.realp; in = (float *) out_buf; if (!spectrum_1.realp || !fft_setup || (filter_length && !filter_in)) { object_error((t_object *) x, "could not allocate temporary memory for processing"); hisstools_destroy_setup_d(fft_setup); ALIGNED_FREE(spectrum_1.realp); ALIGNED_FREE(filter_in); return; } // Get input - convert to frequency domain - get power spectrum - convert phase buffer_read(source, x->read_chan - 1, in, fft_size); time_to_spectrum_float(fft_setup, in, source_length_1, spectrum_1, fft_size); power_spectrum(spectrum_1, fft_size, SPECTRUM_FULL); variable_phase_from_power_spectrum(fft_setup, spectrum_1, fft_size, phase, false); if (mode == MODE_ALLPASS) { // Copy minimum phase spectrum to spectrum_2 for (i = 0; i < fft_size; i++) { spectrum_2.realp[i] = spectrum_1.realp[i]; spectrum_2.imagp[i] = spectrum_1.imagp[i]; } // Get input again time_to_spectrum_float(fft_setup, in, source_length_1, spectrum_1, fft_size); // Fill deconvolution filter specifiers - read filter from buffer (if specified) - deconvolve input by minimum phase spectrum fill_power_array_specifier(filter_specifier, x->deconvolve_filter_specifier, x->deconvolve_num_filter_specifiers); fill_power_array_specifier(range_specifier, x->deconvolve_range_specifier, x->deconvolve_num_range_specifiers); buffer_read(filter, 0, filter_in, fft_size); deconvolve(fft_setup, spectrum_1, spectrum_2, spectrum_3, filter_specifier, range_specifier, 0, filter_in, filter_length, fft_size, SPECTRUM_FULL, deconvolve_mode, deconvolve_phase, deconvolve_delay, sample_rate); } // Convert to time domain - copy out to buffer spectrum_to_time(fft_setup, out_buf, spectrum_1, fft_size, SPECTRUM_FULL); error = buffer_write(target, out_buf, fft_size, x->write_chan - 1, x->resize, sample_rate, 1); buffer_write_error((t_object *) x, target, error); // Free memory hisstools_destroy_setup_d(fft_setup); ALIGNED_FREE(spectrum_1.realp); ALIGNED_FREE(filter_in); if (!error) outlet_bang(x->process_done); }
void irextract_process (t_irextract *x, t_symbol *rec_buffer, t_atom_long num_channels, double sample_rate) { FFT_SETUP_D fft_setup; FFT_SPLIT_COMPLEX_D spectrum_1; FFT_SPLIT_COMPLEX_D spectrum_2; FFT_SPLIT_COMPLEX_D spectrum_3; void *excitation_sig; double *out_mem; float *rec_mem; float *filter_in; t_symbol *filter = filter_retriever(x->deconvolve_filter_specifier); double filter_specifier[HIRT_MAX_SPECIFIER_ITEMS]; double range_specifier[HIRT_MAX_SPECIFIER_ITEMS]; double test_pow; double max_pow; double deconvolve_phase = phase_retriever(x->deconvolve_phase); long deconvolve_mode = x->deconvolve_mode; long bandlimit = x->measure_mode == SWEEP ? x->bandlimit : 0; AH_SIntPtr rec_length = buffer_length(rec_buffer); AH_SIntPtr gen_length = 0; AH_SIntPtr filter_length = buffer_length(filter); AH_SIntPtr out_length_samps; AH_UIntPtr fft_size; AH_UIntPtr fft_size_log2; AH_UIntPtr i; if (buffer_check((t_object *)x, rec_buffer) || !rec_length) return; switch (x->measure_mode) { case SWEEP: gen_length = ess_get_length(&x->sweep_params); break; case MLS: gen_length = mls_get_length(&x->max_length_params); break; case NOISE: gen_length = coloured_noise_get_length(&x->noise_params); break; } // Check and calculate lengths fft_size = calculate_fft_size(rec_length + gen_length, &fft_size_log2); if (rec_length % num_channels) object_warn ((t_object *) x, "buffer length is not a multiple of the number of channels - number may be wrong"); if (((rec_length / num_channels) - gen_length) < 1) { object_error ((t_object *) x, "buffer is not long enough for generated signal"); return; } out_length_samps = ((rec_length / num_channels) - gen_length); if (x->out_length) { if (out_length_samps < (x->out_length * sample_rate)) object_warn ((t_object *) x, "buffer is not long enough for requested output length"); else out_length_samps = (AH_SIntPtr) (x->out_length * sample_rate); } // Allocate Temporary Memory fft_setup = hisstools_create_setup_d(fft_size_log2); excitation_sig = malloc(((gen_length > filter_length) ? gen_length : filter_length) * sizeof(double)); spectrum_1.realp = ALIGNED_MALLOC((sizeof(double) * fft_size * 4)); spectrum_1.imagp = spectrum_1.realp + (fft_size >> 1); spectrum_2.realp = spectrum_1.imagp + (fft_size >> 1); spectrum_2.imagp = spectrum_2.realp + (fft_size >> 1); spectrum_3.realp = spectrum_2.imagp + (fft_size >> 1); spectrum_3.imagp = spectrum_3.realp + fft_size; rec_mem = (float *) malloc(rec_length * sizeof(float)); filter_in = filter_length ? ALIGNED_MALLOC(sizeof(float *) * filter_length) : 0; if (!fft_setup || !excitation_sig || !spectrum_1.realp || (filter_length && !filter_in)) { object_error ((t_object *) x, "could not allocate temporary memory for processing"); hisstools_destroy_setup_d(fft_setup); free(excitation_sig); ALIGNED_FREE(spectrum_1.realp); ALIGNED_FREE(filter_in); return; } x->fft_size = fft_size; x->sample_rate = sample_rate; x->out_length_samps = out_length_samps; x->gen_length = gen_length; // Allocate output memory and get record memory out_mem = grow_mem_swap(&x->out_mem, fft_size * sizeof(double), fft_size); if (!out_mem) { object_error ((t_object *) x, "could not allocate memory for output storage"); free(excitation_sig); hisstools_destroy_setup_d(fft_setup); return; } // Generate Signal switch (x->measure_mode) { case SWEEP: ess_gen(&x->sweep_params, excitation_sig, true); break; case MLS: mls_gen(&x->max_length_params, excitation_sig, true); break; case NOISE: coloured_noise_gen(&x->noise_params, excitation_sig, true); break; } // Transform excitation signal into complex spectrum 2 time_to_halfspectrum_double(fft_setup, excitation_sig, gen_length, spectrum_2, fft_size); if (bandlimit) { // Calculate standard filter for bandlimited deconvolution (sweep * inv sweep) ess_igen(&x->sweep_params, excitation_sig, true, true); time_to_halfspectrum_double(fft_setup, excitation_sig, gen_length, spectrum_3, fft_size); convolve(spectrum_3, spectrum_2, fft_size, SPECTRUM_REAL); // Calculate full power spectrum from half spectrum - convert filter to have the required phase power_full_spectrum_from_half_spectrum(spectrum_3, fft_size); variable_phase_from_power_spectrum(fft_setup, spectrum_3, fft_size, deconvolve_phase, true); // Convert back to real format spectrum_3.imagp[0] = spectrum_3.realp[fft_size >> 1]; } else { // Find maximum power to scale for (i = 1, max_pow = 0; i < (fft_size >> 1); i++)