/****************************************************************************

    DRC: Digital Room Correction
    Copyright (C) 2002, 2003 Denis Sbragion

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

		You can contact the author on Internet at the following address:

				d.sbragion@infotecna.it

		This program uses the parsecfg library from Yuuki  NINOMIYA.  De­
		tails  on  this  library  can be found in the parsecfg.c and par­
		secfg.h files.  Many thanks to Yuuki NINOMIYA for this useful li­
		brary.

		This program uses  also the FFT  routines from  Takuya Ooura and
		the GNU Scientific  Library (GSL).  Many thanks  to Takuya Ooura
		and the GSL developers for these efficient routines.

****************************************************************************/

/* Opzioni di configurazione DRC */

/* Inclusioni */
#include "drccfg.h"
#include "baselib.h"
#include <stddef.h>
#include <string.h>
#include <stdlib.h>

/* Opzioni di configurazione */
CfgParmsType Cfg;

/* Definizione struttura file di configurazione */
cfgStruct CfgParmsDef[] =
	{
		/* Base configuration */
		{ (char *) "BCBaseDir",CFG_STRING,&Cfg.BCBaseDir },
		{ (char *) "BCInFile",CFG_STRING,&Cfg.BCInFile },
		{ (char *) "BCInFileType",CFG_STRING,&Cfg.BCInFileType },
		{ (char *) "BCSampleRate",CFG_INT,&Cfg.BCSampleRate },
		{ (char *) "BCImpulseCenterMode",CFG_STRING,&Cfg.BCImpulseCenterMode },
		{ (char *) "BCImpulseCenter",CFG_INT,&Cfg.BCImpulseCenter },
		{ (char *) "BCInitWindow",CFG_INT,&Cfg.BCInitWindow },
		{ (char *) "BCPreWindowLen",CFG_INT,&Cfg.BCPreWindowLen },
		{ (char *) "BCPreWindowGap",CFG_INT,&Cfg.BCPreWindowGap },
		{ (char *) "BCNormFactor",DRCCfgFloat,&Cfg.BCNormFactor },
		{ (char *) "BCNormType",CFG_STRING,&Cfg.BCNormType },

    /* Mic correction stage */
		{ (char *) "MCFilterType",CFG_STRING,&Cfg.MCFilterType },
		{ (char *) "MCInterpolationType",CFG_STRING,&Cfg.MCInterpolationType },
		{ (char *) "MCMultExponent",CFG_INT,&Cfg.MCMultExponent },
		{ (char *) "MCFilterLen",CFG_INT,&Cfg.MCFilterLen },
		{ (char *) "MCNumPoints",CFG_INT,&Cfg.MCNumPoints },
		{ (char *) "MCPointsFile",CFG_STRING,&Cfg.MCPointsFile },
		{ (char *) "MCMagType",CFG_STRING,&Cfg.MCMagType },
		{ (char *) "MCFilterFile",CFG_STRING,&Cfg.MCFilterFile },
		{ (char *) "MCFilterFileType",CFG_STRING,&Cfg.MCFilterFileType },
		{ (char *) "MCOutWindow",CFG_INT,&Cfg.MCOutWindow },
		{ (char *) "MCNormFactor",DRCCfgFloat,&Cfg.MCNormFactor },
		{ (char *) "MCNormType",CFG_STRING,&Cfg.MCNormType },
		{ (char *) "MCOutFile",CFG_STRING,&Cfg.MCOutFile },
		{ (char *) "MCOutFileType",CFG_STRING,&Cfg.MCOutFileType },

		/* Base configuration dip limiting stage */
		{ (char *) "BCDLType",CFG_STRING,&Cfg.BCDLType },
		{ (char *) "BCDLMinGain",DRCCfgFloat,&Cfg.BCDLMinGain },
		{ (char *) "BCDLStartFreq",DRCCfgFloat,&Cfg.BCDLStartFreq },
		{ (char *) "BCDLEndFreq",DRCCfgFloat,&Cfg.BCDLEndFreq },
		{ (char *) "BCDLStart",DRCCfgFloat,&Cfg.BCDLStart },
		{ (char *) "BCDLMultExponent",CFG_INT,&Cfg.BCDLMultExponent },

		/* Homomorphic Deconvolution */
		{ (char *) "HDMultExponent",CFG_INT,&Cfg.HDMultExponent },
		{ (char *) "HDMPNormFactor",DRCCfgFloat,&Cfg.HDMPNormFactor },
		{ (char *) "HDMPNormType",CFG_STRING,&Cfg.HDMPNormType },
		{ (char *) "HDMPOutFile",CFG_STRING,&Cfg.HDMPOutFile },
		{ (char *) "HDMPOutFileType",CFG_STRING,&Cfg.HDMPOutFileType },
		{ (char *) "HDEPNormFactor",DRCCfgFloat,&Cfg.HDEPNormFactor },
		{ (char *) "HDEPNormType",CFG_STRING,&Cfg.HDEPNormType },
		{ (char *) "HDEPOutFile",CFG_STRING,&Cfg.HDEPOutFile },
		{ (char *) "HDEPOutFileType",CFG_STRING,&Cfg.HDEPOutFileType },

		/* Minimum phase prefiltering stage */
		{ (char *) "MPPrefilterType",CFG_STRING,&Cfg.MPPrefilterType },
		{ (char *) "MPPrefilterFctn",CFG_STRING,&Cfg.MPPrefilterFctn },
		{ (char *) "MPWindowGap",CFG_INT,&Cfg.MPWindowGap },
		{ (char *) "MPLowerWindow",CFG_INT,&Cfg.MPLowerWindow },
		{ (char *) "MPUpperWindow",CFG_INT,&Cfg.MPUpperWindow },
		{ (char *) "MPStartFreq",DRCCfgFloat,&Cfg.MPStartFreq },
		{ (char *) "MPEndFreq",DRCCfgFloat,&Cfg.MPEndFreq },
		{ (char *) "MPWindowExponent",DRCCfgFloat,&Cfg.MPWindowExponent },
		{ (char *) "MPFilterLen",CFG_INT,&Cfg.MPFilterLen },
		{ (char *) "MPFSharpness",DRCCfgFloat,&Cfg.MPFSharpness },
		{ (char *) "MPBandSplit",CFG_INT,&Cfg.MPBandSplit },
		{ (char *) "MPHDRecover",CFG_STRING,&Cfg.MPHDRecover },
		{ (char *) "MPEPPreserve",CFG_STRING,&Cfg.MPEPPreserve },
		{ (char *) "MPHDMultExponent",CFG_INT,&Cfg.MPHDMultExponent },
		{ (char *) "MPPFFinalWindow",CFG_INT,&Cfg.MPPFFinalWindow },
		{ (char *) "MPPFNormFactor",DRCCfgFloat,&Cfg.MPPFNormFactor },
		{ (char *) "MPPFNormType",CFG_STRING,&Cfg.MPPFNormType },
		{ (char *) "MPPFOutFile",CFG_STRING,&Cfg.MPPFOutFile },
		{ (char *) "MPPFOutFileType",CFG_STRING,&Cfg.MPPFOutFileType },

		/* Dip limiting stage */
		{ (char *) "DLType",CFG_STRING,&Cfg.DLType },
		{ (char *) "DLMinGain",DRCCfgFloat,&Cfg.DLMinGain },
		{ (char *) "DLStartFreq",DRCCfgFloat,&Cfg.DLStartFreq },
		{ (char *) "DLEndFreq",DRCCfgFloat,&Cfg.DLEndFreq },
		{ (char *) "DLStart",DRCCfgFloat,&Cfg.DLStart },
		{ (char *) "DLMultExponent",CFG_INT,&Cfg.DLMultExponent },

		/* Excess fase phase prefiltering stage */
		{ (char *) "EPPrefilterType",CFG_STRING,&Cfg.EPPrefilterType },
		{ (char *) "EPPrefilterFctn",CFG_STRING,&Cfg.EPPrefilterFctn },
		{ (char *) "EPWindowGap",CFG_INT,&Cfg.EPWindowGap },
		{ (char *) "EPLowerWindow",CFG_INT,&Cfg.EPLowerWindow },
		{ (char *) "EPUpperWindow",CFG_INT,&Cfg.EPUpperWindow },
		{ (char *) "EPStartFreq",DRCCfgFloat,&Cfg.EPStartFreq },
		{ (char *) "EPEndFreq",DRCCfgFloat,&Cfg.EPEndFreq },
		{ (char *) "EPWindowExponent",DRCCfgFloat,&Cfg.EPWindowExponent },
		{ (char *) "EPFilterLen",CFG_INT,&Cfg.EPFilterLen },
		{ (char *) "EPFSharpness",DRCCfgFloat,&Cfg.EPFSharpness },
		{ (char *) "EPBandSplit",CFG_INT,&Cfg.EPBandSplit },
		{ (char *) "EPPFFlatGain",DRCCfgFloat,&Cfg.EPPFFlatGain },
		{ (char *) "EPPFOGainFactor",DRCCfgFloat,&Cfg.EPPFOGainFactor },
		{ (char *) "EPPFFlatType",CFG_STRING,&Cfg.EPPFFlatType },
		{ (char *) "EPPFFGMultExponent",CFG_INT,&Cfg.EPPFFGMultExponent },
		{ (char *) "EPPFFinalWindow",CFG_INT,&Cfg.EPPFFinalWindow },
		{ (char *) "EPPFNormFactor",DRCCfgFloat,&Cfg.EPPFNormFactor },
		{ (char *) "EPPFNormType",CFG_STRING,&Cfg.EPPFNormType },
		{ (char *) "EPPFOutFile",CFG_STRING,&Cfg.EPPFOutFile },
		{ (char *) "EPPFOutFileType",CFG_STRING,&Cfg.EPPFOutFileType },

		/* Prefiltering completion stage */
		{ (char *) "PCOutWindow",CFG_INT,&Cfg.PCOutWindow },
		{ (char *) "PCNormFactor",DRCCfgFloat,&Cfg.PCNormFactor },
		{ (char *) "PCNormType",CFG_STRING,&Cfg.PCNormType },
		{ (char *) "PCOutFile",CFG_STRING,&Cfg.PCOutFile },
		{ (char *) "PCOutFileType",CFG_STRING,&Cfg.PCOutFileType },

		/* Inversion stage */
		{ (char *) "ISType",CFG_STRING,&Cfg.ISType },
		{ (char *) "ISPETType",CFG_STRING,&Cfg.ISPETType },
		{ (char *) "ISPrefilterFctn",CFG_STRING,&Cfg.ISPrefilterFctn },
		{ (char *) "ISPELowerWindow",CFG_INT,&Cfg.ISPELowerWindow },
		{ (char *) "ISPEUpperWindow",CFG_INT,&Cfg.ISPEUpperWindow },
		{ (char *) "ISPEStartFreq",CFG_INT,&Cfg.ISPEStartFreq },
		{ (char *) "ISPEEndFreq",CFG_INT,&Cfg.ISPEEndFreq },
		{ (char *) "ISPEFilterLen",CFG_INT,&Cfg.ISPEFilterLen },
		{ (char *) "ISPEFSharpness",DRCCfgFloat,&Cfg.ISPEFSharpness },
		{ (char *) "ISPEBandSplit",CFG_INT,&Cfg.ISPEBandSplit },
		{ (char *) "ISPEWindowExponent",DRCCfgFloat,&Cfg.ISPEWindowExponent },
		{ (char *) "ISPEOGainFactor",DRCCfgFloat,&Cfg.ISPEOGainFactor },
		{ (char *) "ISSMPMultExponent",CFG_INT,&Cfg.ISSMPMultExponent },
		{ (char *) "ISOutWindow",CFG_INT,&Cfg.ISOutWindow },
		{ (char *) "ISNormFactor",DRCCfgFloat,&Cfg.ISNormFactor },
		{ (char *) "ISNormType",CFG_STRING,&Cfg.ISNormType },
		{ (char *) "ISOutFile",CFG_STRING,&Cfg.ISOutFile },
		{ (char *) "ISOutFileType",CFG_STRING,&Cfg.ISOutFileType },

		/* Psychoacoustic target stage */
		{ (char *) "PTType",CFG_STRING,&Cfg.PTType },
		{ (char *) "PTReferenceWindow",CFG_INT,&Cfg.PTReferenceWindow },
		{ (char *) "PTDLType",CFG_STRING,&Cfg.PTDLType },
		{ (char *) "PTDLMinGain",DRCCfgFloat,&Cfg.PTDLMinGain },
		{ (char *) "PTDLStart",DRCCfgFloat,&Cfg.PTDLStart },
		{ (char *) "PTDLStartFreq",DRCCfgFloat,&Cfg.PTDLStartFreq },
		{ (char *) "PTDLEndFreq",DRCCfgFloat,&Cfg.PTDLEndFreq },
		{ (char *) "PTDLMultExponent",CFG_INT,&Cfg.PTDLMultExponent },
		{ (char *) "PTBandWidth",DRCCfgFloat,&Cfg.PTBandWidth },
		{ (char *) "PTPeakDetectionStrength",DRCCfgFloat,&Cfg.PTPeakDetectionStrength },
		{ (char *) "PTMultExponent",CFG_INT,&Cfg.PTMultExponent },
		{ (char *) "PTFilterLen",CFG_INT,&Cfg.PTFilterLen },
		{ (char *) "PTFilterFile",CFG_STRING,&Cfg.PTFilterFile },
		{ (char *) "PTFilterFileType",CFG_STRING,&Cfg.PTFilterFileType },
		{ (char *) "PTNormFactor",DRCCfgFloat,&Cfg.PTNormFactor },
		{ (char *) "PTNormType",CFG_STRING,&Cfg.PTNormType },
		{ (char *) "PTOutFile",CFG_STRING,&Cfg.PTOutFile },
		{ (char *) "PTOutFileType",CFG_STRING,&Cfg.PTOutFileType },
		{ (char *) "PTOutWindow",CFG_INT,&Cfg.PTOutWindow },

		/* Peak limiting stage */
		{ (char *) "PLType",CFG_STRING,&Cfg.PLType },
		{ (char *) "PLMaxGain",DRCCfgFloat,&Cfg.PLMaxGain },
		{ (char *) "PLStart",DRCCfgFloat,&Cfg.PLStart },
		{ (char *) "PLStartFreq",DRCCfgFloat,&Cfg.PLStartFreq },
		{ (char *) "PLEndFreq",DRCCfgFloat,&Cfg.PLEndFreq },
		{ (char *) "PLMultExponent",CFG_INT,&Cfg.PLMultExponent },
		{ (char *) "PLOutWindow",CFG_INT,&Cfg.PLOutWindow },
		{ (char *) "PLNormFactor",DRCCfgFloat,&Cfg.PLNormFactor },
		{ (char *) "PLNormType",CFG_STRING,&Cfg.PLNormType },
		{ (char *) "PLOutFile",CFG_STRING,&Cfg.PLOutFile },
		{ (char *) "PLOutFileType",CFG_STRING,&Cfg.PLOutFileType },

		/* Ringing truncation stage */
		{ (char *) "RTType",CFG_STRING,&Cfg.RTType },
		{ (char *) "RTPrefilterFctn",CFG_STRING,&Cfg.RTPrefilterFctn },
		{ (char *) "RTWindowGap",CFG_INT,&Cfg.RTWindowGap },
		{ (char *) "RTLowerWindow",CFG_INT,&Cfg.RTLowerWindow },
		{ (char *) "RTUpperWindow",CFG_INT,&Cfg.RTUpperWindow },
		{ (char *) "RTStartFreq",DRCCfgFloat,&Cfg.RTStartFreq },
		{ (char *) "RTEndFreq",DRCCfgFloat,&Cfg.RTEndFreq },
		{ (char *) "RTWindowExponent",DRCCfgFloat,&Cfg.RTWindowExponent },
		{ (char *) "RTFilterLen",CFG_INT,&Cfg.RTFilterLen },
		{ (char *) "RTFSharpness",DRCCfgFloat,&Cfg.RTFSharpness },
		{ (char *) "RTBandSplit",CFG_INT,&Cfg.RTBandSplit },
		{ (char *) "RTOutWindow",CFG_INT,&Cfg.RTOutWindow },
		{ (char *) "RTNormFactor",DRCCfgFloat,&Cfg.RTNormFactor },
		{ (char *) "RTNormType",CFG_STRING,&Cfg.RTNormType },
		{ (char *) "RTOutFile",CFG_STRING,&Cfg.RTOutFile },
		{ (char *) "RTOutFileType",CFG_STRING,&Cfg.RTOutFileType },

		/* Target response stage */
		{ (char *) "PSFilterType",CFG_STRING,&Cfg.PSFilterType },
		{ (char *) "PSInterpolationType",CFG_STRING,&Cfg.PSInterpolationType },
		{ (char *) "PSMultExponent",CFG_INT,&Cfg.PSMultExponent },
		{ (char *) "PSFilterLen",CFG_INT,&Cfg.PSFilterLen },
		{ (char *) "PSNumPoints",CFG_INT,&Cfg.PSNumPoints },
		{ (char *) "PSPointsFile",CFG_STRING,&Cfg.PSPointsFile },
		{ (char *) "PSMagType",CFG_STRING,&Cfg.PSMagType },
		{ (char *) "PSOutWindow",CFG_INT,&Cfg.PSOutWindow },
		{ (char *) "PSNormFactor",DRCCfgFloat,&Cfg.PSNormFactor },
		{ (char *) "PSNormType",CFG_STRING,&Cfg.PSNormType },
		{ (char *) "PSOutFile",CFG_STRING,&Cfg.PSOutFile },
		{ (char *) "PSOutFileType",CFG_STRING,&Cfg.PSOutFileType },

		/* Minimum phase filter extraction stage */
		{ (char *) "MSMultExponent",CFG_INT,&Cfg.MSMultExponent },
		{ (char *) "MSOutWindow",CFG_INT,&Cfg.MSOutWindow },
		{ (char *) "MSFilterDelay",CFG_INT,&Cfg.MSFilterDelay },
		{ (char *) "MSNormFactor",DRCCfgFloat,&Cfg.MSNormFactor },
		{ (char *) "MSNormType",CFG_STRING,&Cfg.MSNormType },
		{ (char *) "MSOutFile",CFG_STRING,&Cfg.MSOutFile },
		{ (char *) "MSOutFileType",CFG_STRING,&Cfg.MSOutFileType },

		/* Test convolution stage */
		{ (char *) "TCNormFactor",DRCCfgFloat,&Cfg.TCNormFactor },
		{ (char *) "TCNormType",CFG_STRING,&Cfg.TCNormType },
		{ (char *) "TCOutFile",CFG_STRING,&Cfg.TCOutFile },
		{ (char *) "TCOutFileType",CFG_STRING,&Cfg.TCOutFileType },
		{ (char *) "TCOWFile",CFG_STRING,&Cfg.TCOWFile },
		{ (char *) "TCOWFileType",CFG_STRING,&Cfg.TCOWFileType },
		{ (char *) "TCOWNormFactor",DRCCfgFloat,&Cfg.TCOWNormFactor },
		{ (char *) "TCOWNormType",CFG_STRING,&Cfg.TCOWNormType },
		{ (char *) "TCOWSkip",CFG_INT,&Cfg.TCOWSkip },
		{ (char *) "TCOWPrewindow",CFG_INT,&Cfg.TCOWPrewindow },
		{ (char *) "TCOWLength",CFG_INT,&Cfg.TCOWLength },

		/* Chiusura lista parametri */
		{NULL, CFG_END, NULL}
	};

/* Elenco dei parametri di configurazione che richiedo gestione della
directory base */
static const char * BaseDirParmsList[] =
	{
		"BCInFile",
		"HDMPOutFile",
		"HDEPOutFile",
		"MPPFOutFile",
		"EPPFOutFile",
		"PCOutFile",
		"ISOutFile",
		"PTFilterFile",
		"PTOutFile",
		"PLOutFile",
		"RTOutFile",
		"PSPointsFile",
		"PSOutFile",
		"MCPointsFile",
		"MCOutFile",
		"MSOutFile",
		"TCOutFile",
		"TCOWFile",
		NULL
	};

/* Concatena due stringhe allocando lo spazio necessario */
static char * StrJoin(const char * S1, const char * S2)
	{
		char * SJ;
		if ((SJ = (char *) malloc((1 + strlen(S1) + strlen(S2)) * sizeof(char))) == NULL)
			return NULL;
		strcpy(SJ,S1);
		strcat(SJ,S2);
		return SJ;
	}

/* Ritorna la posizione del parametro indicato */
static int GetCfgParmPos(const cfgStruct * CfgParmsDef, const char * ParmName)
	{
		int P = 0;
		while (CfgParmsDef[P].type != CFG_END)
			{
				if (strcmp(CfgParmsDef[P].parameterName,ParmName) == 0)
					return P;
				P++;
			}
		return -1;
	}

/* Impostazione directory base di lavoro */
int SetupDRCCfgBaseDir(CfgParmsType * DRCCfg, const cfgStruct * CfgParmsDef,
	const CmdLineType * OptData)
	{
		/* Parametro corrente */
		int P;

		/* Indice verifica parametri */
		int I;

		/* Concatenazione stringhe */
		char * S;

		/* Verifica che la directory base sia presente. */
		if (DRCCfg->BCBaseDir == NULL)
			return 0;
		if (strlen(DRCCfg->BCBaseDir) == 0)
			return 0;

		/* Ciclo sui parametri modificabili */
		I = 0;
		while (BaseDirParmsList[I] != NULL)
			{
				/* Recupera la posizione del parametro */
				P = GetCfgParmPos(CfgParmsDef,BaseDirParmsList[I]);

				/* Verifica se il parametro č stato impostato
				a linea di comando */
				if ((OptData->ParmSet[P] == False ||
					OptData->ParmSet[BCBaseDirParmPos] == True) &&
					(*((void **) CfgParmsDef[P].value) != NULL))
					{
						/* Aggiunge la directory base al parametro */
						S = StrJoin(DRCCfg->BCBaseDir,
							(char *) (* ((void **) CfgParmsDef[P].value)));

						/* Verifica che la concatenazione sia riuscita */
						if (S == NULL)
							return 1;

						/* Dealloca la stringa precedente */
						free(*((void **) CfgParmsDef[P].value));

						/* Sostituisce la stringa precedente */
						*((void **) CfgParmsDef[P].value) = (void *) S;
					}

				/* Passa al parametro successivo */
				I++;
			}

		/* Operazione completata */
		return 0;
	}

/* Controllo validitā parametri di configurazione */
int CheckDRCCfg(const CfgParmsType * DRCCfg)
	{
		/* Calcolo finestra validazione parametri */
		int PWLen;
		int IWLen;

		/* Stringa temporanea errori */
		char TStr[256];

		/* Calcolo dimensione massima target psicoacustico */
		int PTLen;

		/*********************************************************************************/
		/* Importazione iniziale risposta all'impulso */
		/*********************************************************************************/

		if (DRCCfg->BCInFile == NULL)
			{
				sputs("BC->BCInFile: No input file name supplied.");
				return 1;
			}
		if (DRCCfg->BCInFileType == NULL)
			{
				sputs("BC->BCInFileType: No input file type supplied.");
				return 1;
			}
		if (DRCCfg->BCImpulseCenterMode == NULL)
			{
				sputs("BC->BCImpulseCenterMode: No impulse center mode supplied.");
				return 1;
			}
		if (DRCCfg->BCNormFactor > 0 && DRCCfg->BCNormType == NULL)
			{
				sputs("BC->BCNormType: No input normalization type supplied.");
				return 1;
			}
		if (DRCCfg->BCInitWindow < 3)
			{
				sputs("BC->BCInitWindow: Initial window should be at least 3.");
				return 1;
			}
		if (DRCCfg->BCPreWindowGap < 0)
			{
				sputs("BC->BCPreWindowGap: BCPreWindowGap can't be less than 0.");
				return 1;
			}
		if (DRCCfg->BCPreWindowLen > 0)
			if (DRCCfg->BCPreWindowLen + DRCCfg->BCPreWindowGap > DRCCfg->BCInitWindow)
				{
					sputs("BC: BCPreWindowLen + BCPreWindowGap must be less than BCInitWindow.");
					return 1;
				}

    /*********************************************************************************/
		/* Compensazione microfono */
		/*********************************************************************************/

		if (DRCCfg->MCFilterType == NULL)
			{
				sputs("MC->MCFilterType: No filter type supplied.");
				return 1;
			}
    if (DRCCfg->MCFilterType[0] != 'N')
      {
        if (DRCCfg->MCFilterType[0] != 'L' && DRCCfg->MCFilterType[0] != 'M'
          && DRCCfg->MCFilterType[0] != 'N')
          {
            sputs("MC->MCFilterType: Invalid filter type supplied.");
            return 1;
          }
        if (DRCCfg->MCInterpolationType == NULL)
          {
            sputs("MC->MCInterpolationType: No interpolation type supplied.");
            return 1;
          }
        if (DRCCfg->MCInterpolationType[0] != 'L' && DRCCfg->MCInterpolationType[0] != 'G'
          && DRCCfg->MCInterpolationType[0] != 'R' && DRCCfg->MCInterpolationType[0] != 'S'
          && DRCCfg->MCInterpolationType[0] != 'P' && DRCCfg->MCInterpolationType[0] != 'H')
          {
            sputs("MC->MCInterpolationType: Invalid interpolation type supplied.");
            return 1;
          }
        if (DRCCfg->MCMagType == NULL)
          {
            sputs("MC->MCMagType: No filter definition magnitude type supplied.");
            return 1;
          }
        if (DRCCfg->MCMagType[0] != 'L' && DRCCfg->MCMagType[0] != 'D')
          {
            sputs("MC->MCMagType: Invalid filter definition magnitude type supplied.");
            return 1;
          }
        if (DRCCfg->MCPointsFile == NULL)
          {
            sputs("MC->MCPointsFile: No correction point file supplied.");
            return 1;
          }
        if (DRCCfg->MCNumPoints < 0 || DRCCfg->MCNumPoints == 1)
          {
            sputs("MC->MCNumPoints: Invalid MCNumPoints supplied, it must be 0 or at least 2.");
            return 1;
          }
        if (DRCCfg->MCFilterFile != NULL && DRCCfg->MCFilterFileType == NULL)
          {
            sputs("MC->MCFilterFileType: No MCFilterFileType supplied.");
            return 1;
          }
        if (DRCCfg->MCNormFactor > 0 && DRCCfg->MCNormType == NULL)
          {
            sputs("MC->MCNormType: No normalization type supplied.");
            return 1;
          }
        if (DRCCfg->MCOutFile != NULL && DRCCfg->MCOutFileType == NULL)
          {
            sputs("MC->MCOutFileType: No output file type supplied.");
            return 1;
          }
        if (DRCCfg->MCFilterLen <= 0)
          {
            sputs("MC->MCFilterLen: MCFilterLen must be greater than 0.");
            return 1;
          }
        switch (DRCCfg->MCFilterType[0])
          {
            case 'L':
              if (DRCCfg->MCOutWindow > DRCCfg->BCInitWindow + DRCCfg->MCFilterLen - 1)
                {
                  sprintf(TStr,"%d.",DRCCfg->BCInitWindow + DRCCfg->MCFilterLen - 1);
                  sputsp("MC->MCOutWindow: MCOutWindow too big. Max allowed value: ", TStr);
                  return 1;
                }

              if (DRCCfg->MCOutWindow > 0)
                IWLen = DRCCfg->MCOutWindow;
              else
                IWLen = DRCCfg->BCInitWindow + DRCCfg->MCFilterLen - 1;
            break;
            case 'M':
              if (DRCCfg->MCOutWindow > DRCCfg->BCInitWindow)
                {
                  sprintf(TStr,"%d.",DRCCfg->BCInitWindow);
                  sputsp("MC->MCOutWindow: MCOutWindow too big. Max allowed value: ", TStr);
                  return 1;
                }

              if (DRCCfg->MCOutWindow > 0)
                IWLen = DRCCfg->MCOutWindow;
              else
                IWLen = DRCCfg->BCInitWindow;
            break;
          }
      }
    else
      IWLen = DRCCfg->BCInitWindow;

		/*********************************************************************************/
		/* Base configuration dip limiting */
		/*********************************************************************************/

		if (DRCCfg->BCDLType == NULL)
			{
				sputs("BC->BCDLType: No BCDLType supplied.");
				return 1;
			}
		if (DRCCfg->BCDLType[0] != 'L' && DRCCfg->BCDLType[0] != 'M')
			{
				sputs("BC->BCDLType: Invalid dip limiting type supplied.");
				return 1;
			}
		if (DRCCfg->BCDLStart < (DLReal) 0.0)
			{
				sputs("BC->BCDLStart: BCDLStart must be greater than or equal to 0.");
				return 1;
			}

		/*********************************************************************************/
		/* Deconvoluzione omomorfa */
		/*********************************************************************************/

		if (DRCCfg->HDMPNormFactor > 0 && DRCCfg->HDMPNormType == NULL)
			{
				sputs("HD->HDMPNormType: No MP normalization type supplied.");
				return 1;
			}
		if (DRCCfg->HDEPNormFactor > 0 && DRCCfg->HDEPNormType == NULL)
			{
				sputs("HD->HDEPNormType: No EP normalization type supplied.");
				return 1;
			}
		if (DRCCfg->HDMPOutFile != NULL && DRCCfg->HDMPOutFileType == NULL)
			{
				sputs("HD->HDMPOutFileType: No MP output file type supplied.");
				return 1;
			}
		if (DRCCfg->HDEPOutFile != NULL && DRCCfg->HDEPOutFileType == NULL)
			{
				sputs("HD->HDEPOutFileType: No EP output file type supplied.");
				return 1;
			}

		/*********************************************************************************/
		/* Prefiltratura componente MP */
		/*********************************************************************************/

		if (DRCCfg->MPPrefilterType == NULL)
			{
				sputs("MP->MPPrefilterType: No MPPrefilterType supplied.");
				return 1;
			}
		if (DRCCfg->MPPrefilterType[0] != 'B' && DRCCfg->MPPrefilterType[0] != 'b'
			&& DRCCfg->MPPrefilterType[0] != 'S' && DRCCfg->MPPrefilterType[0] != 's')
			{
				sputs("MP->MPPrefilterType: Invalid MPPrefilterType supplied.");
				return 1;
			}
		if (DRCCfg->MPPrefilterFctn == NULL)
			{
				sputs("MP->MPPrefilterFctn: No MPPrefilterFctn supplied.");
				return 1;
			}
		if (DRCCfg->MPPrefilterFctn[0] != 'P' && DRCCfg->MPPrefilterFctn[0] != 'B')
			{
				sputs("MP->MPPrefilterFctn: Invalid MPPrefilterFctn supplied.");
				return 1;
			}
		if (DRCCfg->MPWindowGap < 0)
			{
				sputs("MP->MPWindowGap: MPWindowGap must be greater or equal to 0.");
				return 1;
			}
		if (DRCCfg->MPLowerWindow <= 0)
			{
				sputs("MP->MPLowerWindow: No MPLowerWindow supplied.");
				return 1;
			}
		if (DRCCfg->MPLowerWindow > IWLen)
			{
        sprintf(TStr,"%d.",IWLen);
        sputsp("MP->MPLowerWindow: MPLowerWindow too big. Max allowed value: ", TStr);
				return 1;
			}
		if (DRCCfg->MPUpperWindow <= 0)
			{
				sputs("MP->MPUpperWindow: No MPUpperWindow supplied.");
				return 1;
			}
		if (DRCCfg->MPFSharpness <= (DLReal) 0.0)
			{
				sputs("MP->MPFSharpness: MPFSharpness must be greater than 0.");
				return 1;
			}
		if (DRCCfg->MPUpperWindow > DRCCfg->MPLowerWindow)
			{
				sputs("MP->MPUpperWindow: MPUpperWindow can't be greater than MPLowerWindow.");
				return 1;
			}
		if (DRCCfg->MPWindowExponent <= (DLReal) 0.0)
			{
				sputs("MP->MPWindowExponent: MPWindowExponent must be greater than 0.");
				return 1;
			}
		if (DRCCfg->MPHDRecover == NULL)
			{
				sputs("MP->MPHDRecover: No MPHDRecover supplied.");
				return 1;
			}
		if (DRCCfg->MPEPPreserve == NULL)
			{
				sputs("MP->MPEPPreserve: No MPEPPreserve supplied.");
				return 1;
			}
		if (DRCCfg->MPPFNormFactor > 0 && DRCCfg->MPPFNormType == NULL)
			{
				sputs("MP->MPPFNormType: No PF normalization type supplied.");
				return 1;
			}
		if (DRCCfg->MPPFOutFile != NULL && DRCCfg->MPPFOutFileType == NULL)
			{
				sputs("MP->MPPFOutFileType: No MPPF output file type supplied.");
				return 1;
			}
		if (DRCCfg->MPPFFinalWindow > DRCCfg->MPLowerWindow + DRCCfg->MPFilterLen - 1)
			{
				sputs("MP->MPPFFinalWindow: MPPFFinalWindow can't be greater than MPLowerWindow + MPFilterLen - 1.");
				return 1;
			}
		if (DRCCfg->MPPFFinalWindow <= 0)
			PWLen = DRCCfg->MPLowerWindow + DRCCfg->MPFilterLen - 1;
		else
			PWLen = DRCCfg->MPPFFinalWindow;

		/*********************************************************************************/
		/* Dip limiting */
		/*********************************************************************************/

		if (DRCCfg->DLType == NULL)
			{
				sputs("DL->DLType: No DLType supplied.");
				return 1;
			}
		if (DRCCfg->DLType[0] != 'L' && DRCCfg->DLType[0] != 'M')
			{
				sputs("DL->DLType: Invalid dip limiting type supplied.");
				return 1;
			}
		if (DRCCfg->DLStart < (DLReal) 0.0)
			{
				sputs("DL->DLStart: DLStart must be greater than or equal to 0.");
				return 1;
			}

		/*********************************************************************************/
		/* Prefiltratura componente EP */
		/*********************************************************************************/

		if (DRCCfg->EPPrefilterType == NULL)
			{
				sputs("EP->EPPrefilterType: No EPPrefilterType supplied.");
				return 1;
			}
		if (DRCCfg->EPPrefilterType[0] != 'B' && DRCCfg->EPPrefilterType[0] != 'b'
			&& DRCCfg->EPPrefilterType[0] != 'S' && DRCCfg->EPPrefilterType[0] != 's')
			{
				sputs("EP->EPPrefilterType: Invalid EPPrefilterType supplied.");
				return 1;
			}
		if (DRCCfg->EPPrefilterFctn == NULL)
			{
				sputs("EP->EPPrefilterFctn: No EPPrefilterFctn supplied.");
				return 1;
			}
		if (DRCCfg->EPPrefilterFctn[0] != 'P' && DRCCfg->EPPrefilterFctn[0] != 'B')
			{
				sputs("EP->EPPrefilterFctn: Invalid EPPrefilterFctn supplied.");
				return 1;
			}
		if (DRCCfg->EPWindowGap < 0)
			{
				sputs("EP->EPWindowGap: EPWindowGap must be greater or equal to 0.");
				return 1;
			}
		if (DRCCfg->EPLowerWindow <= 0)
			{
				sputs("EP->EPLowerWindow: EPLowerWindow must be greater than 0.");
				return 1;
			}
		if (DRCCfg->EPLowerWindow > IWLen)
			{
        sprintf(TStr,"%d.",IWLen);
        sputsp("EP->EPLowerWindow: EPLowerWindow  too big. Max allowed value: ", TStr);
				return 1;
			}
		if (DRCCfg->EPUpperWindow <= 0)
			{
				sputs("EP->EPUpperWindow: EPUpperWindow must be greater than 0.");
				return 1;
			}
		if (DRCCfg->EPUpperWindow > DRCCfg->EPLowerWindow)
			{
				sputs("EP->EPUpperWindow: EPUpperWindow can't be greater than EPLowerWindow.");
				return 1;
			}
		if (DRCCfg->EPFSharpness <= (DLReal) 0.0)
			{
				sputs("EP->EPFSharpness: EPFSharpness must be greater than 0.");
				return 1;
			}
		if (DRCCfg->EPWindowExponent <= (DLReal) 0.0)
			{
				sputs("EP->EPWindowExponent: EPWindowExponent must be greater than 0.");
				return 1;
			}
		if (DRCCfg->EPPFFlatGain > 0 && DRCCfg->EPPFFlatType == NULL)
			{
				sputs("EP->EPPFFlatType: No EPPFFlatType supplied.");
				return 1;
			}
		if (DRCCfg->EPPFFlatType[0] != 'L' && DRCCfg->EPPFFlatType[0] != 'M' &&
			DRCCfg->EPPFFlatType[0] != 'D')
			{
				sputs("EP->EPPFFlatType: Invalid EPPFFlatType supplied.");
				return 1;
			}
		if (DRCCfg->EPPFNormFactor > 0 && DRCCfg->EPPFNormType == NULL)
			{
				sputs("EP->EPPFNormType: No PF normalization type supplied.");
				return 1;
			}
		if (DRCCfg->EPPFOutFile != NULL && DRCCfg->EPPFOutFileType == NULL)
			{
				sputs("EP->EPPFOutFileType: No EPPF output file type supplied.");
				return 1;
			}
		if (DRCCfg->EPPFFinalWindow > DRCCfg->EPLowerWindow + DRCCfg->EPFilterLen - 1)
			{
				sputs("EP->EPPFFinalWindow: EPPFFinalWindow can't be greater than EPLowerWindow + EPFilterLen - 1.");
				return 1;
			}
		if (DRCCfg->EPPFFinalWindow <= 0)
			PWLen += (DRCCfg->EPLowerWindow + DRCCfg->EPFilterLen - 1) - 1;
		else
			PWLen += DRCCfg->EPPFFinalWindow - 1;

		/*********************************************************************************/
		/* Combinazione componente MP e EP */
		/*********************************************************************************/

		if (DRCCfg->PCOutWindow < 0)
			{
				sputs("PC->PCOutWindow: No PCOutWindow supplied.");
				return 1;
			}
		if (DRCCfg->PCNormFactor > 0 && DRCCfg->PCNormType == NULL)
			{
				sputs("PC->PCNormType: No normalization type supplied.");
				return 1;
			}
		if (DRCCfg->PCOutFile != NULL && DRCCfg->PCOutFileType == NULL)
			{
				sputs("PC->PCOutFileType: No output file type supplied.");
				return 1;
			}
		if (DRCCfg->PCOutWindow > PWLen)
			{
				sprintf(TStr,"%d.",PWLen);
				sputsp("PC->PCOutWindow: PCOutWindow too big. Max value allowed: ",TStr);
				return 1;
			}

		/*********************************************************************************/
		/* Inversione risposta all'impulso */
		/*********************************************************************************/

		if (DRCCfg->ISType == NULL)
			{
				sputs("IS->ISType: No inversion stage type supplied.");
				return 1;
			}
		if (DRCCfg->ISType[0] != 'L' && DRCCfg->ISType[0] != 'T')
			{
				sputs("IS->ISType: Invalid inversion stage type supplied.");
				return 1;
			}
		if (DRCCfg->ISPETType == NULL)
			{
				sputs("IS->ISPETType: No pre echo truncation type supplied.");
				return 1;
			}
		if (DRCCfg->ISPETType[0] != 'f' && DRCCfg->ISPETType[0] != 's')
			{
				sputs("IS->ISPETType: Invalid pre echo truncation type supplied.");
				return 1;
			}
		if (DRCCfg->ISPrefilterFctn == NULL)
			{
				sputs("IS->ISPrefilterFctn: No ISPrefilterFctn supplied.");
				return 1;
			}
		if (DRCCfg->ISPrefilterFctn[0] != 'P' && DRCCfg->ISPrefilterFctn[0] != 'B')
			{
				sputs("IS->ISPrefilterFctn: Invalid ISPrefilterFctn supplied.");
				return 1;
			}
		if (DRCCfg->ISPEFSharpness <= (DLReal) 0.0)
			{
				sputs("IS->ISPEFSharpness: ISPEFSharpness must be greater than 0.");
				return 1;
			}
		if (DRCCfg->ISNormFactor > 0 && DRCCfg->ISNormType == NULL)
			{
				sputs("IS->ISNormType: No normalization type supplied.");
				return 1;
			}
		if (DRCCfg->ISOutFile != NULL && DRCCfg->ISOutFileType == NULL)
			{
				sputs("IS->ISOutFileType: No output file type supplied.");
				return 1;
			}
		if (DRCCfg->ISOutWindow < 0)
			{
				sputs("IS->ISOutWindow: ISOutWindow must be greater than 0.");
				return 1;
			}
		if (DRCCfg->ISOutWindow > 0)
			PWLen = DRCCfg->ISOutWindow;

		/*********************************************************************************/
		/* Calcolo target psicoacustico */
		/*********************************************************************************/
		if (DRCCfg->PTType == NULL)
			{
				sputs("PT->PTType: No psychoacoustic target type supplied.");
				return 1;
			}
		if (DRCCfg->PTType[0] != 'N' && DRCCfg->PTType[0] != 'L' && DRCCfg->PTType[0] != 'M')
			{
				sputs("PT->PTType: Invalid psychoacoustic target type supplied.");
				return 1;
			}
		if (DRCCfg->PTType[0] != 'N')
			{
				if (DRCCfg->PTReferenceWindow <= 0)
					{
						sputs("PT->PTReferenceWindow: PTReferenceWindow must be greater than 0.");
						return 1;
					}
				if (DRCCfg->PTReferenceWindow > (DRCCfg->BCInitWindow + PWLen - 1))
					{
						sprintf(TStr,"%d.",DRCCfg->BCInitWindow + PWLen - 1);
						sputsp("PT->PTReferenceWindow: PTReferenceWindow too big. Max allowed value: ", TStr);
						return 1;
					}
				if (DRCCfg->PTDLType == NULL)
					{
						sputs("PT->PTDLType: No DLType supplied.");
						return 1;
					}
				if (DRCCfg->PTDLType[0] != 'L' && DRCCfg->PTDLType[0] != 'M')
					{
						sputs("PT->PTDLType: Invalid dip limiting type supplied.");
						return 1;
					}
				if (DRCCfg->PTDLStart < (DLReal) 0.0)
					{
						sputs("PT->PTDLStart: PTDLStart must be greater than or equal to 0.");
						return 1;
					}
				if (DRCCfg->PTFilterLen <= 0)
					{
						sputs("PT->PTFilterLen: PTFilterLen must be greater than 0.");
						return 1;
					}
				/* Calcola la lunghezza del target psicoacustico */
				if (DRCCfg->PTDLMultExponent >= 0)
					{
						/* Calcola la potenza di due superiore a N */
						for (PTLen = 1;PTLen <= DRCCfg->PTReferenceWindow;PTLen <<= 1);
						PTLen *= 1 << DRCCfg->PTDLMultExponent;
					}
				else
					PTLen = DRCCfg->PTReferenceWindow;
				PTLen *= 2;
				if (DRCCfg->PTFilterLen > PTLen)
					{
						sprintf(TStr,"%d.",PTLen);
						sputsp("PT->PTFilterLen: PTFilterLen too big. Max allowed value: ", TStr);
						return 1;
					}
				if (DRCCfg->PTFilterFile != NULL && DRCCfg->PTFilterFileType == NULL)
					{
						sputs("PT->PTFilterFileType: No PT filter file type supplied.");
						return 1;
					}
				if (DRCCfg->PTNormFactor > 0 && DRCCfg->PTNormType == NULL)
					{
						sputs("PT->PTNormType: No PT normalization type supplied.");
						return 1;
					}
				if (DRCCfg->PTOutFile != NULL && DRCCfg->PTOutFileType == NULL)
					{
						sputs("PT->PTOutFileType: No PT output file type supplied.");
						return 1;
					}
				if (DRCCfg->PTOutWindow < 0)
					{
						sputs("PT->PTOutWindow: PTOutWindow can't be less than 0.");
						return 1;
					}
				switch (DRCCfg->PTDLType[0])
					{
						case 'L':
							if (DRCCfg->PTOutWindow > PWLen + DRCCfg->PTFilterLen - 1)
								{
									sprintf(TStr,"%d.",PWLen + DRCCfg->PTFilterLen - 1);
									sputsp("PT->PTOutWindow: PTOutWindow too big. Max value allowed: ",TStr);
									return 1;
								}
							if (DRCCfg->PTOutWindow > 0)
								PWLen = DRCCfg->PTOutWindow;
							else
								PWLen = PWLen + DRCCfg->PTFilterLen - 1;
						break;

						case 'M':
							if (DRCCfg->PTOutWindow > PWLen + 2 * (DRCCfg->PTFilterLen - 1))
								{
									sprintf(TStr,"%d.",PWLen + 2 * (DRCCfg->PTFilterLen - 1));
									sputsp("PT->PTOutWindow: PTOutWindow too big. Max value allowed: ",TStr);
									return 1;
								}
							if (DRCCfg->PTOutWindow > 0)
								PWLen = DRCCfg->PTOutWindow;
							else
								PWLen = PWLen + DRCCfg->PTFilterLen - 1;
						break;
					}
			}

		/*********************************************************************************/
		/* Peak limiting */
		/*********************************************************************************/

		if (DRCCfg->PLType == NULL)
			{
				sputs("PL->PLType: No peak limiting type supplied.");
				return 1;
			}
		if (DRCCfg->PLType[0] != 'L' && DRCCfg->PLType[0] != 'M')
			{
				sputs("PL->PLType: Invalid peak limiting type supplied.");
				return 1;
			}
		if (DRCCfg->PLStart < (DLReal) 0.0)
			{
				sputs("PL->PLStart: PLStart must be greater than or equal to 0.");
				return 1;
			}
		if (DRCCfg->PLNormFactor > 0 && DRCCfg->PLNormType == NULL)
			{
				sputs("PL->PLNormType: No normalization type supplied.");
				return 1;
			}
		if (DRCCfg->PLOutFile != NULL && DRCCfg->PLOutFileType == NULL)
			{
				sputs("PL->PLOutFileType: No output file type supplied.");
				return 1;
			}
		if (DRCCfg->PLOutWindow > PWLen)
			{
				sprintf(TStr,"%d.",PWLen);
				sputsp("PL->PLOutWindow: PLOutWindow too big. Max allowed value: ", TStr);
				return 1;
			}
		if (DRCCfg->PLOutWindow > 0)
			PWLen = DRCCfg->PLOutWindow;

		/*********************************************************************************/
		/* Troncatura ringing */
		/*********************************************************************************/

		if (DRCCfg->RTType == NULL)
			{
				sputs("RT->RTType: No RTType supplied.");
				return 1;
			}
		if (DRCCfg->RTType[0] != 'N' && DRCCfg->RTType[0] != 'B' && DRCCfg->RTType[0] != 'b'
			&& DRCCfg->RTType[0] != 'S' && DRCCfg->RTType[0] != 's')
			{
				sputs("RT->RTType: Invalid RTType supplied.");
				return 1;
			}
		if (DRCCfg->RTType[0] != 'N')
			{
				if (DRCCfg->RTPrefilterFctn == NULL)
					{
						sputs("RT->RTPrefilterFctn: No RTPrefilterFctn supplied.");
						return 1;
					}
				if (DRCCfg->RTPrefilterFctn[0] != 'P' && DRCCfg->RTPrefilterFctn[0] != 'B')
					{
						sputs("RT->RTPrefilterFctn: Invalid RTPrefilterFctn supplied.");
						return 1;
					}
				if (DRCCfg->RTWindowGap < 0)
					{
						sputs("RT->RTWindowGap: RTWindowGap must be greater or equal to 0.");
						return 1;
					}
				if (DRCCfg->RTLowerWindow <= 0)
					{
						sputs("RT->RTLowerWindow: RTLowerWindow must be greater than 0.");
						return 1;
					}
				if (DRCCfg->RTLowerWindow > PWLen)
					{
						sprintf(TStr,"%d.",PWLen);
						sputsp("RT->RTLowerWindow: RTLowerWindow too big. Max allowed value: ", TStr);
						return 1;
					}
				if (DRCCfg->RTUpperWindow <= 0)
					{
						sputs("RT->RTUpperWindow: RTUpperWindow must be greater than 0.");
						return 1;
					}
				if (DRCCfg->RTFSharpness <= (DLReal) 0.0)
					{
						sputs("RT->RTFSharpness: RTFSharpness must be greater than 0.");
						return 1;
					}
				if (DRCCfg->RTUpperWindow > PWLen)
					{
						sprintf(TStr,"%d.",PWLen);
						sputsp("RT->RTUpperWindow: RTUpperWindow too big. Max allowed value: ", TStr);
						return 1;
					}
				if (DRCCfg->RTWindowExponent <= (DLReal) 0.0)
					{
						sputs("RT->RTWindowExponent: RTWindowExponent must be greater than 0.");
						return 1;
					}
				if (DRCCfg->RTNormFactor > 0 && DRCCfg->RTNormType == NULL)
					{
						sputs("RT->RTNormType: No RT normalization type supplied.");
						return 1;
					}
				if (DRCCfg->RTOutFile != NULL && DRCCfg->RTOutFileType == NULL)
					{
						sputs("RT->RTOutFileType: No RT output file type supplied.");
						return 1;
					}
				if (DRCCfg->RTOutWindow > DRCCfg->RTLowerWindow + DRCCfg->RTFilterLen - 1)
					{
						sputs("RT->RTOutWindow: RTOutWindow can't be greater than RTLowerWindow + RTFilterLen - 1.");
						return 1;
					}
				if (DRCCfg->RTOutWindow <= 0)
					PWLen = DRCCfg->RTLowerWindow + DRCCfg->RTFilterLen - 1;
				else
					PWLen = DRCCfg->RTOutWindow;
			}

		/*********************************************************************************/
		/* Applicazione risposta target */
		/*********************************************************************************/

		if (DRCCfg->PSFilterType == NULL)
			{
				sputs("PS->PSFilterType: No filter type supplied.");
				return 1;
			}
		if (DRCCfg->PSFilterType[0] != 'L' && DRCCfg->PSFilterType[0] != 'M'
			&& DRCCfg->PSFilterType[0] != 'T')
			{
				sputs("PS->PSFilterType: Invalid filter type supplied.");
				return 1;
			}
		if (DRCCfg->PSInterpolationType == NULL)
			{
				sputs("PS->PSInterpolationType: No interpolation type supplied.");
				return 1;
			}
		if (DRCCfg->PSInterpolationType[0] != 'L' && DRCCfg->PSInterpolationType[0] != 'G'
			&& DRCCfg->PSInterpolationType[0] != 'R' && DRCCfg->PSInterpolationType[0] != 'S'
			&& DRCCfg->PSInterpolationType[0] != 'P' && DRCCfg->PSInterpolationType[0] != 'H')
			{
				sputs("PS->PSInterpolationType: Invalid interpolation type supplied.");
				return 1;
			}
		if (DRCCfg->PSMagType== NULL)
			{
				sputs("PS->PSMagType: No filter definition magnitude type supplied.");
				return 1;
			}
		if (DRCCfg->PSMagType[0] != 'L' && DRCCfg->PSMagType[0] != 'D')
			{
				sputs("PS->PSMagType: Invalid filter definition magnitude type supplied.");
				return 1;
			}
		if (DRCCfg->PSPointsFile == NULL)
			{
				sputs("PS->PSPointsFile: No correction point file supplied.");
				return 1;
			}
		if (DRCCfg->PSNumPoints < 0 || DRCCfg->PSNumPoints == 1)
			{
				sputs("PS->PSNumPoints: Invalid PSNumPoints supplied, it must be 0 or at least 2.");
				return 1;
			}
		if (DRCCfg->PSNormFactor > 0 && DRCCfg->PSNormType == NULL)
			{
				sputs("PS->PSNormFactor: No normalization type supplied.");
				return 1;
			}
		if (DRCCfg->PSOutFile != NULL && DRCCfg->PSOutFileType == NULL)
			{
				sputs("PS->PSOutFileType: No output file type supplied.");
				return 1;
			}
		if (DRCCfg->PSFilterLen <= 0)
			{
				sputs("PS->PSFilterLen: PSFilterLen must be greater than 0.");
				return 1;
			}
		switch (DRCCfg->PSFilterType[0])
			{
				case 'L':
					if (DRCCfg->PSOutWindow > PWLen + DRCCfg->PSFilterLen - 1)
						{
							sprintf(TStr,"%d.",PWLen + DRCCfg->PSFilterLen - 1);
							sputsp("PS->PSOutWindow: PSOutWindow too big. Max allowed value: ", TStr);
							return 1;
						}
				break;
				case 'M':
					if (DRCCfg->PSOutWindow > PWLen)
						{
							sprintf(TStr,"%d.",PWLen);
							sputsp("PS->PSOutWindow: PSOutWindow too big. Max allowed value: ", TStr);
							return 1;
						}
				break;
				case 'T':
					if (DRCCfg->PSOutWindow > PWLen / 2 + DRCCfg->ISPELowerWindow + DRCCfg->PSFilterLen - 1)
						{
							sprintf(TStr,"%d.",PWLen / 2 + DRCCfg->ISPELowerWindow + DRCCfg->PSFilterLen - 1);
							sputsp("PS->PSOutWindow: PSOutWindow too big. Max allowed value: ", TStr);
							return 1;
						}
					if (DRCCfg->PSOutWindow < 2 * DRCCfg->ISPELowerWindow)
						{
							sprintf(TStr,"%d.",2 * DRCCfg->ISPELowerWindow);
							sputsp("PS->PSOutWindow: PSOutWindow too small. Min allowed value: ", TStr);
							return 1;
						}
					if (PWLen < 2 * DRCCfg->ISPELowerWindow)
						{
							sprintf(TStr,"%d.",2 * DRCCfg->ISPELowerWindow);
							sputsp("PS->PSFilterType: Output of previous stages too small to allow for the required pre-echo truncation length. Check either RTOutWindow, PLOutWindow, PTOutWindow or decrease ISPELowerWindow. Min allowed value: ", TStr);
							return 1;
						}
				break;
			}
    PWLen += DRCCfg->PSFilterLen - 1;

		/*********************************************************************************/
		/* Estrazione filtro a fase minima */
		/*********************************************************************************/

    if (DRCCfg->MSOutFile != NULL)
      {
        if (DRCCfg->MSOutWindow > PWLen)
          {
            sprintf(TStr,"%d.",PWLen);
            sputsp("MS->MSOutWindow: MSOutWindow too big. Max allowed value: ",TStr);
            return 1;
          }
        if (DRCCfg->MSFilterDelay < 0)
          {
            sputs("MS->MSFilterDelay: MSFilterDelay must be greater than 0.");
            return 1;
          }
        if (DRCCfg->MSOutWindow > 0)
          {
            if (DRCCfg->MSFilterDelay >= DRCCfg->MSOutWindow)
              {
                sputs("MS->MSFilterDelay: MSFilterDelay must be smaller than MSOutWindow.");
                return 1;
              }
          }
        else
          {
            if (DRCCfg->MSFilterDelay >= PWLen)
              {
                sprintf(TStr,"%d.",PWLen);
                sputsp("MS->MSFilterDelay: MSFilterDelay too big. Max allowed value: ",TStr);
                return 1;
              }
          }
        if (DRCCfg->MSNormFactor > 0 && DRCCfg->MSNormType == NULL)
          {
            sputs("MS->MSNormType: No normalization type supplied.");
            return 1;
          }
        if (DRCCfg->MSOutFile != NULL && DRCCfg->MSOutFileType == NULL)
          {
            sputs("MS->MSOutFileType: No output file type supplied.");
            return 1;
          }
      }
		/*********************************************************************************/
		/* Convoluzione di test */
		/*********************************************************************************/

		if (DRCCfg->TCNormFactor > 0 && DRCCfg->TCNormType == NULL)
			{
				sputs("TC->TCNormType: No normalization type supplied.");
				return 1;
			}
		if (DRCCfg->TCOutFile != NULL && DRCCfg->TCOutFileType == NULL)
			{
				sputs("TC->TCOutFileType: No output file type supplied.");
				return 1;
			}
		if (DRCCfg->TCOWFile != NULL)
			{
				if (DRCCfg->TCOWFileType == NULL)
					{
						sputs("TC->TCOWFileType: No overwrite file type supplied.");
						return 1;
					}
				if (DRCCfg->TCOWNormFactor > 0 && DRCCfg->TCOWNormType == NULL)
					{
						sputs("TC->TCOWNormType: No normalization type supplied.");
						return 1;
					}
			}

		/* Controllo completato */
		return 0;
	}
