/* Utilities ------------------------------------- */
double hoa_gain_get_input_mode_value(t_hoa_gain *x)
{
    switch (x->f_inputMode)
    {
        case DECIBELS :
            return x->j_valdB;
            break;
        case AMPLITUDE :
            return x->j_valdB > -70 ? dbtoa(x->j_valdB) : 0;
            break;
        case MIDI :
            return scale(x->j_valdB, -70, 0, 0, 128);
            break;
            
        default:
            break;
    }
    return 0;
}
void hoa_gain_set_gain(t_hoa_gain *x)
{
    x->f_amp->setValue(x->j_valdB > -70.0f ? dbtoa(x->j_valdB) : 0.0f);
}
long descriptors_descriptors_pf (enum PFDescriptorType descriptor_type, double *pf_params, t_atom **argv, short *argc, long num_params, long num_pf_descriptors, long *num_to_output, char rt_flag)
{
	long descriptor_num_params = 0;
	long num_to_output_local = 1;
	double double_arg_temp;
		
	t_atom *argv_local = *argv;
	short argc_local = *argc;
	
	// Check we have space to store this parameter
		
	switch (descriptor_type)
	{
		case DESCRIPTOR_PF_MKL:
		
			descriptor_num_params = 8;
			break;
			
		case DESCRIPTOR_PF_FLUX:
		
			descriptor_num_params = 7;
			break;
			
		case DESCRIPTOR_PF_FOOTE:
			
			descriptor_num_params = 5;
			break;
			
		case DESCRIPTOR_PF_ENERGY: 
		case DESCRIPTOR_PF_SPECTRAL_CREST:
		case DESCRIPTOR_PF_INHARMONICITY:
		case DESCRIPTOR_PF_BRIGHTNESS_LIN: 
		case DESCRIPTOR_PF_BRIGHTNESS_LOG: 
		
			descriptor_num_params = 4;
			break;
			
		case DESCRIPTOR_PF_ENERGY_RATIO:
		case DESCRIPTOR_PF_CENTROID_LIN: 
		case DESCRIPTOR_PF_SPREAD_LIN:
		case DESCRIPTOR_PF_SKEWNESS_LIN:
		case DESCRIPTOR_PF_KURTOSIS_LIN:
		case DESCRIPTOR_PF_CENTROID_LOG: 
		case DESCRIPTOR_PF_SPREAD_LOG:
		case DESCRIPTOR_PF_SKEWNESS_LOG:
		case DESCRIPTOR_PF_KURTOSIS_LOG:
		case DESCRIPTOR_PF_SPECTRAL_FLATNESS:
		case DESCRIPTOR_PF_ROUGHNESS:
		case DESCRIPTOR_PF_SPECTRAL_PEAKS:
				
			descriptor_num_params = 3;
			break;
			
		case DESCRIPTOR_PF_SPECTRAL_ROLLOFF:
		case DESCRIPTOR_PF_AVERAGE_AMP_ABS:
		case DESCRIPTOR_PF_AVERAGE_AMP_RMS:
		case DESCRIPTOR_PF_PEAK_AMP:
		case DESCRIPTOR_PF_LOUDNESS:
		case DESCRIPTOR_PF_NOISE_RATIO:
		case DESCRIPTOR_PF_NON_NOISE_RATIO:
		case DESCRIPTOR_PF_PITCH:
		case DESCRIPTOR_PF_PITCH_CONFIDENCE:
		
			descriptor_num_params = 2;
			break;
				
		case DESCRIPTOR_PF_NONE:
			
			descriptor_num_params = 0;
				break;

	}
	
	// If not then bail
	
	if ((num_params + descriptor_num_params) > MAX_PF_PARAMS)
	{
		error ("descriptors(rt)~: too many descriptors - bailing with %ld valid descriptors", num_pf_descriptors);
		return 0;
	}
		
	// Store descriptor type and then range check parameters / substitute defaults / store parameters

	pf_params[0] = (double) descriptor_type;
	
	switch (descriptor_type)
	{
		case DESCRIPTOR_PF_ENERGY:
		case DESCRIPTOR_PF_ENERGY_RATIO:
		case DESCRIPTOR_PF_SPECTRAL_CREST:
		
			pf_params[1] = 0.;					// min freq
			pf_params[2] = 192000.;				// max freq
			
			if (descriptor_type == DESCRIPTOR_PF_ENERGY || descriptor_type == DESCRIPTOR_PF_SPECTRAL_CREST) 
				pf_params[3] = 1.;				// db conversion flag
			
			if (!argc_local || atom_gettype(argv_local) == A_SYM) 
				break;
			pf_params[1] = atom_getfloat(argv_local++);
			argc_local--;
			if (pf_params[1] < 0) 
				error ("descriptors(rt)~: negative frequency");
			
			if (!argc_local || atom_gettype(argv_local) == A_SYM) 
				break;
			pf_params[2] = atom_getfloat(argv_local++);
			argc_local--;
			if (pf_params[2] < 0) 
				error ("descriptors(rt)~: negative frequency");
			
			if (descriptor_type == DESCRIPTOR_PF_ENERGY || descriptor_type == DESCRIPTOR_PF_SPECTRAL_CREST)
			{					
				 if (!argc_local || atom_gettype(argv_local) == A_SYM) 
					 break;
				pf_params[3] = atom_getfloat(argv_local++);
				argc_local--;
			}
							
			break;
		
		////////////////////////////////////////////////////////
		
		case DESCRIPTOR_PF_FLUX:
		
			pf_params[1] = 0.;					// min freq
			pf_params[2] = 192000.;				// max freq
			pf_params[3] = 1.;					// forward only flag
			pf_params[4] = 1.;					// square flag
			pf_params[5] = 1.;					// normalise spectrum flag
			pf_params[6] = 1.;					// frames to look back
						
			if (!argc_local || atom_gettype(argv_local) == A_SYM) 
				break;
			pf_params[1] = atom_getfloat(argv_local++);
			argc_local--;
			if (pf_params[1] < 0) 
				error ("descriptors(rt)~: negative frequency");
			
			if (!argc_local || atom_gettype(argv_local) == A_SYM) 
				break;
			pf_params[2] = atom_getfloat(argv_local++);
			argc_local--;
			if (pf_params[2] < 0) 
				error ("descriptors(rt)~: negative frequency");
			
			if (!argc_local || atom_gettype(argv_local) == A_SYM) 
				break;
			pf_params[3] = atom_getfloat(argv_local++) != 0.;
			argc_local--;
			
			if (!argc_local || atom_gettype(argv_local) == A_SYM) 
				break;
			pf_params[4] = atom_getfloat(argv_local++) != 0.;
			argc_local--;
			
			if (!argc_local || atom_gettype(argv_local) == A_SYM) 
				break;
			pf_params[5] = atom_getfloat(argv_local++) != 0.;
			argc_local--;
			
			if (!argc_local || atom_gettype(argv_local) == A_SYM) 
				break;
			pf_params[6] = atom_getlong(argv_local++);
			argc_local--;
			if (pf_params[6] >= RING_BUFFER_SIZE || pf_params[6] < 1)
			{ 
				error ("descriptors(rt)~: frame lookback not within range - using %ld", RING_BUFFER_SIZE - 1);
				pf_params[6] = RING_BUFFER_SIZE - 1;
			}
			
			break;
		
		////////////////////////////////////////////////////////
				
		case DESCRIPTOR_PF_MKL:
		
			pf_params[1] = 0.;					// min freq
			pf_params[2] = 192000.;				// max freq
			pf_params[3] = LOG_MIN;				// log threshold
			pf_params[4] = 1.;					// forward only flag
			pf_params[5] = 0.;					// weight with frame2 amplitudes
			pf_params[6] = 0.;					// normalise spectrum flag
			pf_params[7] = 1.;					// frames to look back
						
			if (!argc_local || atom_gettype(argv_local) == A_SYM) 
				break;
			pf_params[1] = atom_getfloat(argv_local++);
			if (pf_params[1] < 0) 
				error ("descriptors(rt)~: negative frequency");
			argc_local--;
			
			
			if (!argc_local || atom_gettype(argv_local) == A_SYM) 
				break;
			pf_params[2] = atom_getfloat(argv_local++);
			if (pf_params[2] < 0) 
				error ("descriptors(rt)~: negative frequency");
			argc_local--;
			
			if (!argc_local || atom_gettype(argv_local) == A_SYM) 
				break;
			pf_params[3] = log(dbtoa(atom_getfloat(argv_local++)));
			argc_local--;
			
			if (!argc_local || atom_gettype(argv_local) == A_SYM) 
				break;
			pf_params[4] = atom_getfloat(argv_local++) != 0.;
			argc_local--;
			
			if (!argc_local || atom_gettype(argv_local) == A_SYM) 
				break;
			pf_params[5] = atom_getfloat(argv_local++) != 0.;
			argc_local--;
			
			if (!argc_local || atom_gettype(argv_local) == A_SYM) 
				break;
			pf_params[6] = atom_getfloat(argv_local++) != 0.;
			argc_local--;
			
			if (!argc_local || atom_gettype(argv_local) == A_SYM) 
				break;
			pf_params[7] = atom_getlong(argv_local++);
			argc_local--;
			if (pf_params[7] >= RING_BUFFER_SIZE || pf_params[7] < 1)
			{ 
				error ("descriptors(rt)~: frame lookback not within range - using %ld", RING_BUFFER_SIZE - 1);
				pf_params[7] = RING_BUFFER_SIZE - 1;
			}
			
			break;

		////////////////////////////////////////////////////////
				
		case DESCRIPTOR_PF_FOOTE:
		
			pf_params[1] = 0.;					// min freq
			pf_params[2] = 192000.;				// max freq
			pf_params[3] = 1.;					// forward only flag
			pf_params[4] = 1.;					// frames to look back
						
			if (!argc_local || atom_gettype(argv_local) == A_SYM) 
				break;
			pf_params[1] = atom_getfloat(argv_local++);
			argc_local--;
			if (pf_params[1] < 0) 
				error ("descriptors(rt)~: negative frequency");
			
			if (!argc_local || atom_gettype(argv_local) == A_SYM) 
				break;
			pf_params[2] = atom_getfloat(argv_local++);
			argc_local--;
			if (pf_params[2] < 0) 
				error ("descriptors(rt)~: negative frequency");
			
			if (!argc_local || atom_gettype(argv_local) == A_SYM) 
				break;
			pf_params[3] = atom_getfloat(argv_local++) != 0.;
			argc_local--;
			
			if (!argc_local || atom_gettype(argv_local) == A_SYM) 
				break;
			pf_params[4] = atom_getlong(argv_local++);
			argc_local--;
			if (pf_params[4] >= RING_BUFFER_SIZE || pf_params[4] < 1)
			{ 
				error ("descriptors(rt)~: frame lookback not within range - using %ld", RING_BUFFER_SIZE - 1);
				pf_params[3] = RING_BUFFER_SIZE - 1;
			}
			
			break;
				
		////////////////////////////////////////////////////////
		
		case DESCRIPTOR_PF_SPECTRAL_ROLLOFF:
							
			pf_params[1] = 0.95;				// threshold
			
			if (!argc_local || atom_gettype(argv_local) == A_SYM) 
				break;
			double_arg_temp = atom_getfloat(argv_local++);
			argc_local--;
			if (double_arg_temp > 0. && double_arg_temp < 1.) 
				pf_params[1] = double_arg_temp;
			else error ("descriptors(rt)~: rolloff point should be between 0 and 1 - using %lf", pf_params[1]); 
			
			break;

		////////////////////////////////////////////////////////
		
		case DESCRIPTOR_PF_AVERAGE_AMP_ABS:
		case DESCRIPTOR_PF_AVERAGE_AMP_RMS:
		case DESCRIPTOR_PF_PEAK_AMP:
		case DESCRIPTOR_PF_LOUDNESS:
		
			pf_params[1] = 1.;					// db Conversion flag
			
			if (!argc_local || atom_gettype(argv_local) == A_SYM) 
				break;
			pf_params[1] = atom_getfloat(argv_local++);
			argc_local--;
			
			break;
									
		////////////////////////////////////////////////////////
		
		case DESCRIPTOR_PF_CENTROID_LIN: 
		case DESCRIPTOR_PF_SPREAD_LIN:
		case DESCRIPTOR_PF_SKEWNESS_LIN:
		case DESCRIPTOR_PF_KURTOSIS_LIN:
		case DESCRIPTOR_PF_CENTROID_LOG: 
		case DESCRIPTOR_PF_SPREAD_LOG:
		case DESCRIPTOR_PF_SKEWNESS_LOG:
		case DESCRIPTOR_PF_KURTOSIS_LOG:
		case DESCRIPTOR_PF_SPECTRAL_FLATNESS:
				
			pf_params[1] = 0.;					// min freq
			pf_params[2] = 192000.;				// max freq
			
			if (!argc_local || atom_gettype(argv_local) == A_SYM) 
				break;
			pf_params[1] = atom_getfloat(argv_local++);
			argc_local--;
			if (pf_params[1] < 0) 
				error ("descriptors(rt)~: negative frequency");
			
			if (!argc_local || atom_gettype(argv_local) == A_SYM) 
				break;
			pf_params[2] = atom_getfloat(argv_local++);
			argc_local--;
			if (pf_params[2] < 0) 
				error ("descriptors(rt)~: negative frequency");
							
			break;
			
			////////////////////////////////////////////////////////
			
			case DESCRIPTOR_PF_BRIGHTNESS_LIN:
			case DESCRIPTOR_PF_BRIGHTNESS_LOG:

			pf_params[1] = 0.;					// min freq
			pf_params[2] = 192000.;				// max freq
			pf_params[3] = 0.68;				// threshold

			if (!argc_local || atom_gettype(argv_local) == A_SYM) 
				break;
			pf_params[1] = atom_getfloat(argv_local++);
			argc_local--;
			if (pf_params[1] < 0) 
				error ("descriptors(rt)~: negative frequency");
			
			if (!argc_local || atom_gettype(argv_local) == A_SYM) 
				break;
			pf_params[2] = atom_getfloat(argv_local++);
			argc_local--;
			if (pf_params[2] < 0) 
				error ("descriptors(rt)~: negative frequency");
			
			if (!argc_local || atom_gettype(argv_local) == A_SYM) 
				break;
			double_arg_temp = atom_getfloat(argv_local++);
			argc_local--;	
			if (double_arg_temp > 0. && double_arg_temp <= 1.) 
				pf_params[3] = double_arg_temp;
			else 
				error("descriptors(rt)~: threshold should be between 0 and 1 - using %lf", pf_params[3]);
					
			break;

		////////////////////////////////////////////////////////


			case DESCRIPTOR_PF_NOISE_RATIO:
			case DESCRIPTOR_PF_NON_NOISE_RATIO:
		
				pf_params[1] = 15.;				// median span
			
				if (!argc_local || atom_gettype(argv_local) == A_SYM) 
					break;
				double_arg_temp = (double) atom_getlong(argv_local++);
				argc_local--;
				if (double_arg_temp < 0) 
					error("descriptors(rt)~: negative median span - using %ld", (long) pf_params[1]);
				else pf_params[1] = double_arg_temp;
									
				break;

			////////////////////////////////////////////////////////
			
			case DESCRIPTOR_PF_PITCH:
			case DESCRIPTOR_PF_PITCH_CONFIDENCE:
						
				pf_params[1] = 0.68;			// threshold
					
				if (!argc_local || atom_gettype(argv_local) == A_SYM) 
					break;
				double_arg_temp = atom_getfloat(argv_local++);
				argc_local--;	
				if (double_arg_temp > 0. && double_arg_temp <= 1.) 
					pf_params[1] = double_arg_temp;
				else 
					error("descriptors(rt)~: threshold should be between 0 and 1 - using %lf", pf_params[1]);

				break;
								
			////////////////////////////////////////////////////////
			
			case DESCRIPTOR_PF_INHARMONICITY:
			case DESCRIPTOR_PF_ROUGHNESS:
			case DESCRIPTOR_PF_SPECTRAL_PEAKS:
		
				pf_params[1] = 10.;				// n peaks
				pf_params[2] = 15.;				// median span
				
				if (descriptor_type == DESCRIPTOR_PF_INHARMONICITY)	
					pf_params[3] = 0.68;		// threshold
				if (descriptor_type == DESCRIPTOR_PF_SPECTRAL_PEAKS) 
					num_to_output_local = 2 * (long) pf_params[1];
					
				if (!argc_local || atom_gettype(argv_local) == A_SYM) 
					break;
				double_arg_temp = (double) atom_getlong(argv_local++);
				argc_local--;
				if (double_arg_temp < 0) 
					error("descriptors(rt)~: negative number of peaks - using %ld", (long) pf_params[1]);
				else pf_params[1] = double_arg_temp;
				
				if (descriptor_type == DESCRIPTOR_PF_SPECTRAL_PEAKS)
					num_to_output_local = 2 * (long) pf_params[1];
				
				if (!argc_local || atom_gettype(argv_local) == A_SYM) 
					break;
				double_arg_temp = (double) atom_getlong(argv_local++);
				argc_local--;
				if (double_arg_temp < 0) 
					error("descriptors(rt)~: negative median span - using %ld", (long) pf_params[2]);
				else pf_params[2] = double_arg_temp;
				
				if (descriptor_type == DESCRIPTOR_PF_INHARMONICITY)
				{
					 if (!argc_local || atom_gettype(argv_local) == A_SYM) 
						 break;
					double_arg_temp = atom_getfloat(argv_local++);
					argc_local--;	
					if (double_arg_temp > 0. && double_arg_temp <= 1.) 
						pf_params[3] = double_arg_temp;
					else 
						error("descriptors(rt)~: threshold should be between 0 and 1 - using %lf", pf_params[3]); 
				}
			
				break;
				
			case DESCRIPTOR_PF_NONE:
				break;
	}
	
	// Store variables
	
	*num_to_output = num_to_output_local;
	*argv = argv_local;
	*argc = argc_local;
	return descriptor_num_params;
}