예제 #1
0
void Hash::initHash(size_t bytes)
{
   if (!hash_init_done) {
      hashSize = (int)(bytes/sizeof(HashEntry));
      if (!hashSize) {
         hashMask = 0;
         hash_init_done++;
         return;
      }
      int hashPower;
      for (hashPower = 1; hashPower < 32; hashPower++) {
        if (((size_t)1 << hashPower) > hashSize) {
            hashPower--;
            break;
        }
      }
      hashSize = (size_t)1 << hashPower;
      hashMask = (uint64_t)(hashSize-1);
      size_t hashSizePlus = hashSize + MaxRehash;
      ALIGNED_MALLOC(hashTable,
         HashEntry,
         sizeof(HashEntry)*hashSizePlus,128);
      if (hashTable == NULL) {
          cerr << "hash table allocation failed!" << endl;
          hashSize = 0;
      }
      clearHash();
      hash_init_done++;
   }
}
void bufreverse_process_internal(t_bufreverse *x, t_symbol *sym, short argc, t_atom *argv)
{
    t_symbol *target = atom_getsym(argv++);
    t_symbol *source = atom_getsym(argv++);

    float *temp1;
    double *temp2;

    t_buffer_write_error error;

    AH_SIntPtr full_length = buffer_length(source);
    AH_SIntPtr i;

    double sample_rate = 0;
    t_atom_long read_chan = x->read_chan - 1;

    // Check source buffer

    if (buffer_check((t_object *) x, source, read_chan))
        return;
    sample_rate = buffer_sample_rate(source);

    // Allocate Memory

    temp1 = (float *) ALIGNED_MALLOC(full_length * (sizeof(double) + sizeof(float)));
    temp2 = (double *) (temp1 + full_length);

    // Check momory allocation

    if (!temp1)
    {
        object_error((t_object *)x, "could not allocate temporary memory for processing");
        free(temp1);
        return;
    }

    // Read from buffer

    buffer_read(source, read_chan, (float *) temp1, full_length);

    // Copy to double precision version

    for (i = 0; i < full_length; i++)
         temp2[i] = temp1[full_length - i - 1];

    // Copy out to buffer

    error = buffer_write(target, temp2, full_length, x->write_chan - 1, x->resize, sample_rate, 1.);
    buffer_write_error((t_object *)x, target, error);

    // Free Resources

    ALIGNED_FREE(temp1);

    if (!error)
        outlet_bang(x->process_done);
}
예제 #3
0
void *_lx_malloc(size_t size)
{
    if (size == 0) return NULL;
    
  #if defined(ALIGNED_MALLOC)
    return ALIGNED_MALLOC(size, ALIGNMENT);
  #else
  
    return malloc(size);
  #endif
}
예제 #4
0
void *_lx_calloc(size_t count, size_t size)
{
    if (size == 0 || count == 0) return NULL;
    
  #if defined(ALIGNED_MALLOC)
    size_t realSize = count*size;
    void *buf = ALIGNED_MALLOC(realSize, ALIGNMENT);
    memset(buf, 0, realSize);
    return buf;
  #else
  
    return calloc(count, size);
  #endif
}
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 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);
}
예제 #8
0
int main(int argc, char *argv[])
{
    cl_int ret;
    
    /* get platform ID */
    cl_platform_id platform_id;
    ret = clGetPlatformIDs(1, &platform_id, NULL);
    assert(CL_SUCCESS == ret);

    /* get device IDs */
    cl_device_id device_id;
    ret = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_ALL, 1, &device_id, NULL);
	assert(CL_SUCCESS == ret);
    
    /* create context */
    cl_context context = clCreateContext(NULL, 1, &device_id, NULL, NULL, &ret);
    assert(CL_SUCCESS == ret);

    /* create command queue */
    cl_command_queue command_queue = clCreateCommandQueue(context, device_id, 0, &ret);
    assert(CL_SUCCESS == ret);

    /* create image object */
    cl_image_format format;
    format.image_channel_order = CL_R;
    format.image_channel_data_type = CL_UNSIGNED_INT8;
    
    cl_image_desc desc;
	memset(&desc, 0, sizeof(desc));
    desc.image_type = CL_MEM_OBJECT_IMAGE2D;
    desc.image_width  = IMAGE_W;
    desc.image_height = IMAGE_H;
    
    cl_mem image = clCreateImage(context, 0, &format, &desc, NULL, &ret);
    assert(CL_SUCCESS == ret);

	/* filling background image */
    {
        const size_t origin[] = {0, 0, 0};
        const size_t region[] = {IMAGE_W, IMAGE_H, 1};
 		cl_uchar4 fill_color;
		fill_color.s[0] = 0;
		fill_color.s[1] = 0;
		fill_color.s[2] = 0;
		fill_color.s[3] = 0;
        ret = clEnqueueFillImage(command_queue, image, &fill_color, origin, region, 0, NULL, NULL);
        assert(CL_SUCCESS == ret);
    }

    /* filling front image */
    {
        const size_t origin[] = {(IMAGE_W*1)/4, (IMAGE_H*1)/4, 0};
        const size_t region[] = {(IMAGE_W*2)/4, (IMAGE_H*2)/4, 1};
        cl_uchar4 fill_color;
		fill_color.s[0] = 255;
		fill_color.s[1] = 0;
		fill_color.s[2] = 0;
		fill_color.s[3] = 0;
        ret = clEnqueueFillImage(command_queue, image, &fill_color, origin, region, 0, NULL, NULL);
        assert(CL_SUCCESS == ret);
    }

    /* reading image */
    cl_uchar *data = NULL;
    {
        size_t num_channels = 1;
        data = static_cast<cl_uchar*>(ALIGNED_MALLOC(IMAGE_W*IMAGE_H*sizeof(cl_uchar), num_channels*sizeof(cl_uchar)));
		assert(NULL != data);
		std::fill(&data[0], &data[IMAGE_W*IMAGE_H], 128);
        
        const size_t origin[] = {0, 0, 0};
        const size_t region[] = {IMAGE_W, IMAGE_H, 1};
        ret = clEnqueueReadImage(command_queue, image, CL_TRUE, origin, region, IMAGE_W*sizeof(cl_uchar), 0, data, 0, NULL, NULL);
        assert(CL_SUCCESS == ret);
    }

    /* print image */
    for (unsigned int h=0; h<IMAGE_H; ++h)
    {
        for (unsigned int w=0; w<IMAGE_W; ++w)
        {
            std::cout << std::setw(5) << std::right << static_cast<int>(data[h*IMAGE_W+w]);
        }
        std::cout << std::endl;
    }

    /* finalizing */
    ALIGNED_FREE(data);

    clReleaseMemObject(image);
    
    clReleaseCommandQueue(command_queue);
    clReleaseContext(context);

    return 0;
}
void ircropfade_process_internal(t_ircropfade *x, t_symbol *sym, short argc, t_atom *argv)
{
    // Load arguments

    t_symbol *target = atom_getsym(argv++);
    t_symbol *source = atom_getsym(argv++);
    t_atom_long crop1 = atom_getlong(argv++);
    t_atom_long crop2 = atom_getlong(argv++);
    double fade_start = atom_getfloat(argv++);
    double in_length = atom_getfloat(argv++);
    double fade_end = atom_getfloat(argv++);
    double out_length = atom_getfloat(argv++);

    // Set fade variables

    double fade_in_lo = fade_start - 1;
    double fade_in_hi = in_length > 0 ? fade_start + in_length : fade_start;
    double fade_out_lo = fade_end;
    double fade_out_hi = out_length > 0 ? fade_end - out_length : fade_end - 1;
    double fade_in_recip = 1. / (fade_in_hi - fade_in_lo);
    double fade_out_recip = 1. / (fade_out_hi - fade_out_lo);

    float *temp1;
    double *temp2;

    t_buffer_write_error error;

    AH_SIntPtr full_length = buffer_length(source);
    AH_SIntPtr final_length;
    AH_SIntPtr i;

    t_atom_long read_chan = x->read_chan - 1;

    double sample_rate = 0;

    // Check source buffer

    if (buffer_check((t_object *) x, source, read_chan))
        return;
    sample_rate = buffer_sample_rate(source);

    crop1 = crop1 < 0 ? 0 : crop1;
    crop2 = crop2 < 0 ? 0 : crop2;
    crop1 = crop1 > full_length - 1 ? full_length - 1: crop1;
    crop2 = crop2 > full_length ? full_length : crop2;

    if (crop1 >= crop2)
        return;

    final_length = crop2 - crop1;

    // Allocate Memory

    temp1 = (float *) ALIGNED_MALLOC(full_length  * sizeof(float) + final_length * sizeof(double));
    temp2 = (double *) (temp1 + full_length);

    // Check momory allocation

    if (!temp1)
    {
        object_error((t_object *)x, "could not allocate temporary memory for processing");
        free(temp1);
        return;
    }

    // Read from buffer

    buffer_read(source, read_chan, (float *) temp1, full_length);

    // Copy with crops / fades to double precision version

    for (i = 0; i < final_length; i++)
    {
        double in_val = temp1[i + crop1];
        double fade_in = calculate_fade((double) (i + crop1), fade_in_lo, fade_in_recip);
        double fade_out = calculate_fade((double) (i + crop1), fade_out_lo, fade_out_recip);

        temp2[i] = in_val * fade_in * fade_out;
    }

    // Copy out to buffer

    error = buffer_write(target, temp2, final_length, x->write_chan - 1, x->resize, sample_rate, 1.);
    buffer_write_error((t_object *)x, target, error);

    // Free Resources

    ALIGNED_FREE(temp1);

    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 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++)