void irextract_mls (t_irextract *x, t_symbol *sym, long argc, t_atom *argv) { double sample_rate; double out_length = 0; t_atom_long num_channels = 1; t_atom_long order = 18; t_symbol *rec_buffer = 0; // Load parameters if (argc > 0) { rec_buffer = atom_getsym(argv++); sample_rate = buffer_sample_rate(rec_buffer); } if (argc > 1) order = atom_getlong(argv++); if (argc > 2) num_channels = atom_getlong(argv++); if (argc > 3) out_length = atom_getfloat(argv++); // Check parameters if (!rec_buffer) { object_error((t_object *)x, "no buffer given"); return; } order = (t_atom_long) irextract_param_check(x, "order", (double) order, 1, 24); num_channels = (t_atom_long) irextract_param_check(x, "number of channels", (double) num_channels, 1, HIRT_MAX_MEASURE_CHANS); x->out_length = irextract_param_check(x, "output length", out_length, 0., HUGE_VAL) / 1000.; // Process x->measure_mode = MLS; mls_params(&x->max_length_params, (long) order, db_to_a(x->amp)); irextract_process(x, rec_buffer, num_channels, sample_rate); }
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++)