void irreference_perform64 (t_irreference *x, t_object *dsp64, double **ins, long numins, double **outs, long numouts, long vec_size, long flags, void *userparam)
{
    double *out = outs[0];

    double *rec_ptr;
    double *in;
    double *rec_mem;

    double sample_rate = x->sample_rate;
    double progress_mul = 1.;

    AH_SIntPtr T;
    AH_SIntPtr current_t;
    AH_SIntPtr current_t2;
    AH_SIntPtr mem_size;
    AH_SIntPtr i, j;

    long record_on = 0;
    long mem_check;

    // Check for stop / start

    if (x->start_rec)
    {
        x->T = (AH_SIntPtr) (sample_rate * x->length);
        x->current_length = x->T;
        x->current_out_length = x->out_length;
        x->current_t = 0;
    }

    if (x->stop_rec)
    {
        x->current_length = x->current_t;
        x->current_t = x->T;
        record_on = x->stop_rec == 2;
    }

    x->start_rec = 0;
    x->stop_rec = 0;
    T = x->T;

    // Get counters

    current_t = x->current_t;
    current_t2 = current_t;
    record_on = record_on || current_t2 < T;

    // Check memory

    attempt_mem_swap(&x->rec_mem);
    rec_mem = x->rec_mem.current_ptr;
    mem_size = irreference_calc_mem_size(x, x->current_num_active_ins);
    mem_check = x->rec_mem.current_size >= (AH_UIntPtr) mem_size;

    if (mem_check)
    {
        // Record Inputs

        for (j = 0; j < x->current_num_active_ins + 1; j++)
        {
            in = ins[j];
            rec_ptr = rec_mem + (j * T);
            for (i = 0, current_t2 = current_t; (i < vec_size) && (current_t2 < T); i++, current_t2++)
                rec_ptr[current_t2] = *in++;
        }
    }

    if (x->abs_progress)
        progress_mul = 1000. / sample_rate;
    else if (T)
        progress_mul = 1. / T;

    for (i = 0, current_t2 = current_t; i < vec_size && current_t2 < T && mem_check; i++)
        *out++ = current_t2++ * progress_mul;
    for (; i < vec_size; i++)
        *out++ = progress_mul * T;

    // Store accumulators

    x->current_t = current_t2;

    // Process when done

    if (record_on && current_t2 >= T)
        defer(x, (method) irreference_process, 0, 0, 0);
}
void dynamicdsp_perform_common(t_dynamicdsp *x, void **sig_outs, long vec_size)
{
    void *new_temp_mem_ptr;
    t_ptr_uint new_temp_mem_size;
	
	long num_active_threads = x->request_num_active_threads;
    long multithread_flag = (x->slots->size() > 1) && x->multithread_flag;
	
	// Zero Outputs
	
	for (long i = 0; i < x->num_sig_outs; i++)
		memset(sig_outs[i], 0, sig_size * vec_size);
	
	// Update multithreading parameters (done in one thread and before processing to ensure uninterrupted audio processing
	
    x->num_active_threads = num_active_threads;
	x->manual_threading = x->request_manual_threading;		
    num_active_threads = !multithread_flag ? 1 : num_active_threads;
    
	if (!x->manual_threading)
        x->slots->resetProcessed();
	
	if (x->update_thread_map)
	{
		x->update_thread_map = 0;											
		x->slots->updateThreads();
	}
	
	// Update the temporary memory if relevant
	
	if (attempt_mem_swap(&x->temp_mem) == SWAP_DONE)
	{
		// Store the new pointers and size
		
		new_temp_mem_ptr = x->temp_mem.current_ptr;
		new_temp_mem_size = x->temp_mem.current_size;
		
		for (long i = 0; i < x->max_obj_threads; i++)
            x->threads->setTempMemory(i, (char *) new_temp_mem_ptr + (new_temp_mem_size * i), new_temp_mem_size);
	}
    
	// Do processing - the switching aims to get more speed out of inlining with a fixed loop size
	// Note that the signle threaded case is handled as a special case in the ThreadSet class
    
	switch (num_active_threads)
    {                
        case 2:
            dynamicdsp_multithread_perform(x, sig_outs, vec_size, 2);
            break;
				
        case 3:
            dynamicdsp_multithread_perform(x, sig_outs, vec_size, 3);
            break;
				
        case 4:
            dynamicdsp_multithread_perform(x, sig_outs, vec_size, 4);
            break;
				
        case 5:
            dynamicdsp_multithread_perform(x, sig_outs, vec_size, 5);
            break;
				
        case 6:
            dynamicdsp_multithread_perform(x, sig_outs, vec_size, 6);
            break;
				
        case 7:
            dynamicdsp_multithread_perform(x, sig_outs, vec_size, 7);
            break;
				
        case 8:
            dynamicdsp_multithread_perform(x, sig_outs, vec_size, 8);
            break;
				
        default:
            dynamicdsp_multithread_perform(x, sig_outs, vec_size, num_active_threads);
            break;
	}
}
t_int *irreference_perform (t_int *w)
{
    // Set pointers

    long vec_size = (long) w[1];
    t_irreference *x = (t_irreference *) w[2];

    float *out = (float *) w[3];
    float *in;

    double *rec_ptr;
    double *rec_mem;

    double sample_rate = x->sample_rate;
    double progress_mul = 1.;

    AH_SIntPtr T;
    AH_SIntPtr current_t;
    AH_SIntPtr current_t2;
    AH_SIntPtr mem_size;
    AH_SIntPtr i, j;

    long record_on = 0;
    long mem_check;

    // Check for stop / start

    if (x->start_rec)
    {
        x->T = (AH_SIntPtr) (sample_rate * x->length);
        x->current_length = x->T;
        x->current_out_length = x->out_length;
        x->current_t = 0;
    }

    if (x->stop_rec)
    {
        x->current_length = x->current_t;
        x->current_t = x->T;
        record_on = x->stop_rec == 2;
    }

    x->start_rec = 0;
    x->stop_rec = 0;
    T = x->T;

    // Get counters

    current_t = x->current_t;
    current_t2 = current_t;
    record_on = record_on || current_t2 < T;

    // Check memory

    attempt_mem_swap(&x->rec_mem);
    rec_mem = x->rec_mem.current_ptr;
    mem_size = irreference_calc_mem_size(x, x->current_num_active_ins);
    mem_check = x->rec_mem.current_size >= (AH_UIntPtr) mem_size;

    if (mem_check)
    {
        // Record Inputs

        for (j = 0; j < x->current_num_active_ins + 1; j++)
        {
            in = x->in_chans[j];
            rec_ptr = rec_mem + (j * T);
            for (i = 0, current_t2 = current_t; (i < vec_size) && (current_t2 < T); i++, current_t2++)
                rec_ptr[current_t2] = *in++;
        }
    }

    if (x->abs_progress)
        progress_mul = 1000. / sample_rate;
    else if (T)
        progress_mul = 1. / T;

    for (i = 0, current_t2 = current_t; i < vec_size && current_t2 < T && mem_check; i++)
        *out++ = (float) (current_t2++ * progress_mul);
    for (; i < vec_size; i++)
        *out++ = (float) (progress_mul * T);

    // Store accumulators

    x->current_t = current_t2;

    // Process when done

    if (record_on && current_t2 >= T)
        defer(x, (method) irreference_process, 0, 0, 0);

    return w + 4;
}